Passes selectedChunkVerses as headerContent to the inline DrawCanvas so
highlights overlay the actual scripture text, matching annotate mode.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Apple Pencil hover cursor: previews brush size/shape before contact
- Tilt shading: tilted pen strokes widen and reduce thinning via tiltX/Y
- Two-finger undo in draw mode (non-stylus two-finger tap)
- Copy & open Claude buttons: copies study/podcast prompt then opens claude.ai/new
- Inline ink canvas in study notes (DrawCanvas embedded in Notes tab)
- Full-text search across all project notes with 300ms debounce
- Reading plan: set a book + week goal, mark chapters read from the reader
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a "Page" toggle in the reader tool strip. When enabled, the verse
panel becomes a fixed-height container using CSS column-width to create
one column per page-width. Content flows naturally into successive pages;
long chapters simply have more pages. Bottom nav shows ← Back/Prev ch.
and Next/Next ch. → with a page counter (e.g. Genesis 1 · 2/3). Swipe
left/right and arrow keys also navigate pages before crossing chapter
boundaries. Preference persisted to localStorage.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wide mode now enters focus state automatically: the full toolbar collapses
and a slim frosted bar appears at the top showing the current chapter name,
Prev/Next buttons, and a ⚙ Tools button to restore the toolbar. A ✕ Hide
button inside the toolbar lets you re-enter focus mode without toggling wide.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Swipe left/right on mobile to go between chapters (60px threshold,
ignores vertical-dominant gestures so scrolling still works)
- Left/right arrow keys on desktop navigate chapters (skips inputs)
- Fixed side ‹ › buttons at viewport midpoint for one-tap chapter nav;
disappear when at the first/last chapter, hidden in draw mode
- Wide toggle (⊞) switches between narrow reading column (max-w-3xl)
and full-width two-column layout (max-w-7xl, md:columns-2); persisted
to localStorage so the preference survives page reloads
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace non-functional sticky nav with a fixed bottom bar (position: fixed)
that stays visible while scrolling long study notes; hides in draw mode
- Add pb-20 to main so the bar never covers the last study section
- Cache whole-Bible search index (BSB complete.json, ~7MB) in IndexedDB
with a 7-day TTL so repeated searches skip the network fetch entirely
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PWA:
- manifest.json with name, icons, theme/background color, standalone display
- PNG icons (192, 512, 180 apple-touch) generated via pure Node.js (no deps)
- index.html: manifest link, theme-color, apple-mobile-web-app-* meta tags,
viewport-fit=cover for iPhone notch/Dynamic Island
- service worker extended to cache app shell (static assets + index.html)
with network-first for navigation, cache-first for hashed assets,
network-first-with-cache-fallback for external Bible APIs
Expandable canvas:
- "Add More Space" button below each draw canvas adds a full notebook page
- Existing ink rescales to preserve visual pixel positions (no stretching)
- Page count embedded as metadata in the strokes array so it survives
navigation without a separate state key
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously draw mode was closed whenever the book or chapter changed.
Now it stays open so the user can flip between chapters while drawing;
each chapter has its own canvas (ink is keyed per bookAbbrev_chapter).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
iPadOS Pointer Events fire pointercancel immediately after pointerdown
for Apple Pencil strokes (triggered by palm detection or canvas-width
resets from React re-renders), forcing the user to tap twice to start
every stroke. The Touch Events API with touchType === 'stylus' bypasses
this issue entirely — Touch Events have no equivalent cancellation
problem and reliably identify Pencil vs finger input. Pointer Events
remain as the fallback for non-iOS platforms.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
React's synthetic event system delegates to the document root, which
on iOS Safari causes pointermove passive:true to block preventDefault
and introduces timing issues that drop every other stroke.
Attaching directly to the canvas element with {passive: false} on
pointermove gives iOS the explicit signal it needs to suppress scroll
and deliver all pen events reliably.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
setPointerCapture/hasPointerCapture is unreliable on iPadOS — Safari
sometimes fires pointercancel which releases capture, causing every other
stroke's pointermove events to be discarded. Replace with a simple
isDrawingRef boolean that is set on pointerdown and cleared on pointerup,
avoiding the capture API entirely.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add user-select: none (with WebKit prefix) to the DrawCanvas wrapper so
the browser does not start a text-selection gesture when the pencil drags
across the component.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
touchAction: 'pan-y pinch-zoom' let the browser intercept vertical
pencil movement as a scroll gesture before JavaScript could prevent it.
Setting 'none' hands all pointer input to our handlers exclusively.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use max-w-full on main when draw mode is active so the layout fills the
viewport. Scripture panel is a fixed 288px column; notebook canvas takes
all remaining space.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace stacked scripture-overlay layout with a side-by-side flex row:
the chapter text panel sits on the left (sticky, scrollable) and the
ruled notebook canvas sits on the right. Stacks vertically on mobile.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
DrawCanvas now accepts a headerContent prop — when provided, a transparent
canvas extends over the scripture text so you can draw directly on the
verses, with ruled notebook space below for additional notes.
Study page draw mode shows the full chunk passage this way instead of a
compact unwritable strip. Reader page draw mode replaces the verse list
with the same combined layout (all chapter verses + notebook canvas),
hiding the verse list while active.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Draw mode in the study page replaces all note panels with a full ruled
notebook canvas (no cross-refs, observations, or text boxes) so the user
has a clean writing surface. Ink strokes are saved per chunk and exported
as SVG in the HTML export.
The reader page gets a Draw toggle button that reveals the same notebook
canvas below the verse list, with strokes persisted per book+chapter in
localStorage via readerInkByPage.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a third layout option alongside Stacked and Split. In Draw mode a
canvas overlay covers the scripture panel; the Pointer Events API routes
Apple Pencil input to perfect-freehand strokes while letting finger
touches fall through for normal scrolling. A floating toolbar provides
pen, highlighter, and eraser tools, six color swatches, S/M/L sizes,
undo, clear, and a Done button to return to Stacked view.
Strokes are stored as inkStrokes[] on each chunk and rendered as a
read-only transparent canvas overlay (InkLayer) in Stacked/Split modes.
migrateChunk is updated so all existing chunks get inkStrokes: [] on
first load.
Also adds a simple in-memory rate limiter on auth endpoints (10 attempts
per 15 min per IP).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
App.jsx reduced from ~6,500 to ~3,900 lines by extracting each route into its
own page component (AdminPage, AuthPage, HomePage, ImportPage, ReaderPage,
SettingsPage, SetupPage, StudyPage). State and handlers are shared via
AppContext (React Context API); AppRouter handles routing at module level.
Also adds a network-first service worker (public/sw.js) that caches the last-
fetched Bible chapter data from bible.helloao.org and bolls.life so the app
stays usable when those APIs are temporarily unreachable.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>