App quality: offline badge, per-note history, keyboard study mode, notes import

- Study cards say whether the Bible text works offline, with a button to save
  the missing book (notes are always kept on the device).
- Each note keeps its last 12 versions with Restore (History under each note).
- Keyboard-only study: 1/2/3 write in Observe/Interpret/Apply, C/W/X/P switch
  resource tabs, V compares, Esc leaves a note box; listed under "?".
- Export > Import notes: bring Word/Markdown/text notes into the matching
  chunks without overwriting anything; can mark them as not your own.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-14 13:01:11 -04:00
1 parent 648c3206df
commit 67645cf1df
14 files changed
+421 -7

No files matched your search

+15
View File
@@ -43,3 +43,18 @@ export async function downloadChapters(translation, refs, { onProgress, signal,
await Promise.all(Array.from({ length: Math.min(concurrency, refs.length) }, worker));
return { done, failed };
}
// What a study needs from the network to open offline. Your notes are always kept on this device; only the
// Bible text must have been saved. `saved` is loadSavedBooks(). -> { state: 'ready' | 'partial' | 'licensed',
// translation, missing: [{ abbrev, name }] }
export function offlineStatus(project, saved = loadSavedBooks()) {
const translation = project?.translation ?? 'BSB';
if (!canSaveOffline(translation)) return { state: 'licensed', translation, missing: [] };
const books = [];
for (const chapter of project?.chapters ?? []) {
if (chapter.bookAbbrev && !books.some((b) => b.abbrev === chapter.bookAbbrev)) books.push({ abbrev: chapter.bookAbbrev, name: chapter.book });
}
const have = saved[translation] ?? [];
const missing = books.filter((b) => !have.includes(b.abbrev));
return { state: missing.length ? 'partial' : 'ready', translation, missing };
}