Add Insights, Observe-first, compare, handout layouts, richer search, backup nudge

- Commentary and study aids wait for 15 words of your own Observe notes.
- Insights page: this week's own work, themes across studies, words you keep
  studying, what slipped in recalls, open follow-ups.
- Recall can record what slipped; session notes (teach it back, who came,
  group notes, follow-ups); "Pray about this" from Apply.
- Compare any two passages side by side.
- Handout layouts: standard, questions only, large print, note-taking.
- Search understands "in <book>", "last week/month/year" and a year.
- Home shows the last backup age and nudges after two weeks.
- Phone: the stage bar scrolls instead of clipping Script and Export.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-14 12:42:11 -04:00
1 parent 2ddc4e1ff6
commit d8e522dd06
24 files changed
+540 -28

No files matched your search

+22
View File
@@ -40,3 +40,25 @@ test('finds highlights by their words or colour name, and bookmarks by reference
expect(searchMarks(marks, 'promise')[0]).toMatchObject({ kind: 'highlight' });
expect(searchMarks(marks, 'john 3')[0]).toMatchObject({ kind: 'bookmark', chapter: 3, verse: 16 });
});
import { parseSearchQuery as parseQ } from './personalSearch.js';
test('search understands "in <book>" and time words', () => {
const now = new Date('2026-10-14T12:00:00Z').getTime();
const q = parseQ('grace in Romans last year', now);
expect(q.text).toBe('grace');
expect(q.book).toBe('Romans');
expect(q.since).toBe(now - 365 * 86400000);
expect(parseQ('hope 2025', now)).toMatchObject({ text: 'hope', since: new Date(2025, 0, 1).getTime(), until: new Date(2026, 0, 1).getTime() });
expect(parseQ('plain words', now)).toMatchObject({ text: 'plain words', book: null, since: null });
});
test('a passage and date search filters notes, even with no words to match', () => {
const now = new Date('2026-10-14T12:00:00Z').getTime();
const day = 86400000;
const make = (book, editedAt, observation) => ({ id: book + editedAt, title: 'S', lastEdited: now, chapters: [{ book, bookAbbrev: book.slice(0, 3), chapter: '1', chunks: [{ id: `${book}${editedAt}`, startVerse: 1, endVerse: 3, observation, editedAt }] }] });
const projects = [make('Romans', now - 10 * day, 'grace abounds'), make('Romans', now - 400 * day, 'grace long ago'), make('John', now - 10 * day, 'grace again')];
expect(searchNotes(projects, 'grace in Romans last year', { now })).toHaveLength(1);
expect(searchNotes(projects, 'in John last month', { now })).toHaveLength(1);
expect(searchNotes(projects, 'grace', { now })).toHaveLength(3);
});