diff --git a/src/pages/ReaderPage.jsx b/src/pages/ReaderPage.jsx index 7b25d75..e31b69d 100644 --- a/src/pages/ReaderPage.jsx +++ b/src/pages/ReaderPage.jsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react'; +import { useState, useEffect, useRef } from 'react'; import { useApp } from '../context/AppContext.js'; import { bookOptions, BookmarkIcon, CopyIcon } from '../App.jsx'; import DrawCanvas from './DrawCanvas.jsx'; @@ -52,8 +52,42 @@ export default function ReaderPage() { const readerBook = bookOptions.find((b) => b.abbrev === readerBookAbbrev); const [readerDrawMode, setReaderDrawMode] = useState(false); + const [readerWideLayout, setReaderWideLayout] = useState(() => localStorage.getItem('reader-wide') === '1'); const readerPageInkStrokes = readerInkByPage?.[`${readerBookAbbrev}_${readerChapter}`] ?? []; const [selectionPicker, setSelectionPicker] = useState(null); + const swipeTouchRef = useRef(null); + + useEffect(() => { + localStorage.setItem('reader-wide', readerWideLayout ? '1' : '0'); + }, [readerWideLayout]); + + // Swipe left/right to navigate chapters + const handleTouchStart = (e) => { + if (readerDrawMode) return; + const t = e.changedTouches[0]; + swipeTouchRef.current = { x: t.clientX, y: t.clientY }; + }; + const handleTouchEnd = (e) => { + if (readerDrawMode || !swipeTouchRef.current) return; + const t = e.changedTouches[0]; + const dx = t.clientX - swipeTouchRef.current.x; + const dy = t.clientY - swipeTouchRef.current.y; + swipeTouchRef.current = null; + if (Math.abs(dx) < 60 || Math.abs(dy) > Math.abs(dx) * 0.8) return; + if (dx < 0) readerGoToNextChapter(); + else readerGoToPreviousChapter(); + }; + + // Arrow keys for desktop + useEffect(() => { + const handleKey = (e) => { + if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.isContentEditable) return; + if (e.key === 'ArrowLeft') readerGoToPreviousChapter(); + else if (e.key === 'ArrowRight') readerGoToNextChapter(); + }; + window.addEventListener('keydown', handleKey); + return () => window.removeEventListener('keydown', handleKey); + }, [readerGoToPreviousChapter, readerGoToNextChapter]); // Dismiss the highlight picker when tapping outside it useEffect(() => { @@ -167,7 +201,11 @@ export default function ReaderPage() { -
+
{/* Navigation + tools bar */}
{/* Whole-Bible search results */} @@ -404,7 +449,8 @@ export default function ReaderPage() { return

No verses match "{readerSearch}".

; } return ( -
{filtered.map((verse) => { const chapterInterlinear = readerInterlinear?.[String(readerChapter)]; @@ -416,7 +462,7 @@ export default function ReaderPage() { return (
+ + + )} + {/* Highlight color picker — appears above text selection */} {selectionPicker && (