spread-navigation.js (3.1 KB)


  1 import { SPREADS } from './constants.js';
  2 
  3 // State
  4 let currentSpread = 0;
  5 let isFullscreen = false;
  6 
  7 // Get current spread index
  8 export function getCurrentSpread() {
  9 	return currentSpread;
 10 }
 11 
 12 // Set current spread index
 13 export function setCurrentSpread(index) {
 14 	currentSpread = index;
 15 }
 16 
 17 // Get fullscreen state
 18 export function getIsFullscreen() {
 19 	return isFullscreen;
 20 }
 21 
 22 // Set fullscreen state
 23 export function setIsFullscreen(value) {
 24 	isFullscreen = value;
 25 }
 26 
 27 // Update spread indicator and button states
 28 export function updateSpreadIndicator() {
 29 	const indicator = document.getElementById('spreadIndicator');
 30 	const prevBtn = document.getElementById('prevSpread');
 31 	const nextBtn = document.getElementById('nextSpread');
 32 
 33 	indicator.textContent = SPREADS[currentSpread].label;
 34 	prevBtn.disabled = currentSpread === 0;
 35 	nextBtn.disabled = currentSpread === SPREADS.length - 1;
 36 }
 37 
 38 // Navigate between spreads
 39 export function navigateSpread(delta, updatePreviewCallback) {
 40 	const newSpread = currentSpread + delta;
 41 	if (newSpread >= 0 && newSpread < SPREADS.length) {
 42 		currentSpread = newSpread;
 43 		updateSpreadIndicator();
 44 
 45 		// Try to animate if flip mode is enabled
 46 		const preview = document.getElementById('preview');
 47 		try {
 48 			const doc = preview.contentDocument;
 49 			const container = doc?._zineContainer;
 50 			const flipModeEnabled = doc?._flipModeEnabled;
 51 
 52 			if (container && flipModeEnabled) {
 53 				// Dynamic import to avoid circular dependency
 54 				import('./spread-layout.js').then(({ navigateToSpread }) => {
 55 					navigateToSpread(container, newSpread, doc, true, () => {
 56 						// Refocus preview so keyboard navigation continues to work
 57 						preview.focus();
 58 					});
 59 				});
 60 			} else {
 61 				updatePreviewCallback();
 62 				preview.focus();
 63 			}
 64 		} catch (e) {
 65 			// Fallback to regular update
 66 			updatePreviewCallback();
 67 			preview.focus();
 68 		}
 69 	}
 70 }
 71 
 72 // Fullscreen toggle
 73 export function toggleFullscreen() {
 74 	isFullscreen = !isFullscreen;
 75 	const editorPane = document.querySelector('.editor-pane');
 76 	const previewPane = document.querySelector('.preview-pane');
 77 	const preview = document.getElementById('preview');
 78 
 79 	if (isFullscreen) {
 80 		previewPane.classList.add('fullscreen');
 81 		editorPane.classList.add('hidden');
 82 	} else {
 83 		previewPane.classList.remove('fullscreen');
 84 		editorPane.classList.remove('hidden');
 85 	}
 86 
 87 	try {
 88 		const toggleButton = preview.contentDocument.getElementById('fullscreenToggle');
 89 		if (toggleButton) {
 90 			toggleButton.title = isFullscreen ? 'Exit fullscreen' : 'Toggle fullscreen';
 91 		}
 92 	} catch (e) {}
 93 
 94 	// Trigger resize after layout updates so scaleToFit() recalculates
 95 	requestAnimationFrame(() => {
 96 		try {
 97 			preview.contentWindow.dispatchEvent(new Event('resize'));
 98 		} catch (e) {}
 99 	});
100 }
101 
102 // Initialize spread navigation UI
103 export function initializeSpreadNav(navigateCallback) {
104 	document.getElementById('prevSpread').addEventListener('click', () => navigateCallback(-1));
105 	document.getElementById('nextSpread').addEventListener('click', () => navigateCallback(1));
106 	updateSpreadIndicator();
107 }