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:
1 parent
2ddc4e1ff6
commit
d8e522dd06
24 files changed
+540
-28
No files matched your search
@@ -2,7 +2,7 @@
|
||||
// conflict doesn't force a choice between them. Chunks are matched by id; each chunk carries the time it
|
||||
// was last edited here (editedAt). Nothing the person wrote is dropped: where both copies changed the
|
||||
// same note, the newer one stays and the older one is appended under a marker.
|
||||
const TEXT_FIELDS = ['observation', 'interpretation', 'application', 'generalNotes', 'finalScript', 'episodeNumber', 'episodeTitle'];
|
||||
const TEXT_FIELDS = ['observation', 'interpretation', 'application', 'generalNotes', 'finalScript', 'episodeNumber', 'episodeTitle', 'teachBack', 'attendees', 'groupNotes'];
|
||||
const LIST_FIELDS = ['tags', 'crossReferences', 'greekWords'];
|
||||
export const MERGE_MARKER = '— from your other device —';
|
||||
|
||||
@@ -22,6 +22,12 @@ function union(a = [], b = []) {
|
||||
return [...a, ...b].filter((item) => { const k = JSON.stringify(item); if (seen.has(k)) return false; seen.add(k); return true; });
|
||||
}
|
||||
|
||||
// Follow-ups are matched by id; the newer copy's wording and done-state win, nothing is dropped.
|
||||
function mergeById(newer = [], older = []) {
|
||||
const seen = new Set(newer.map((i) => i.id));
|
||||
return [...newer, ...older.filter((i) => !seen.has(i.id))];
|
||||
}
|
||||
|
||||
export function mergeChunk(mine, theirs) {
|
||||
if (same(mine, theirs)) return { chunk: mine, changed: false };
|
||||
const mineNewer = (mine.editedAt ?? 0) >= (theirs.editedAt ?? 0);
|
||||
@@ -31,6 +37,7 @@ export function mergeChunk(mine, theirs) {
|
||||
LIST_FIELDS.forEach((f) => { out[f] = union(newer[f], older[f]); });
|
||||
// Pastes follow their text: keep the union per field so merged notes still show what was pasted.
|
||||
out.aiPastes = Object.fromEntries(['observation', 'interpretation', 'application'].map((f) => [f, union(newer.aiPastes?.[f], older.aiPastes?.[f])]));
|
||||
out.followUps = mergeById(newer.followUps, older.followUps);
|
||||
out.recalls = union(newer.recalls, older.recalls);
|
||||
out.editedAt = Math.max(mine.editedAt ?? 0, theirs.editedAt ?? 0) || undefined;
|
||||
return { chunk: out, changed: !same(out, mine) };
|
||||
|
||||
Reference in new issue
Block a user