- 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>
49 lines
3.0 KiB
JavaScript
49 lines
3.0 KiB
JavaScript
// What is different between a study as it is now and an earlier version of it, in words a person can read.
|
||
const FIELD_NAMES = {
|
||
observation: 'Observe', interpretation: 'Interpret', application: 'Apply', generalNotes: 'Background', finalScript: 'Script',
|
||
discussionQuestions: 'Questions', episodeNumber: 'Session number', episodeTitle: 'Session title',
|
||
teachBack: 'Teach it back', attendees: 'Who came', groupNotes: 'Group notes',
|
||
};
|
||
const same = (a, b) => JSON.stringify(a ?? '') === JSON.stringify(b ?? '');
|
||
|
||
const chunksOf = (project) => {
|
||
const out = new Map();
|
||
(project?.chapters ?? []).forEach((chapter) => (chapter.chunks ?? []).forEach((chunk) => out.set(chunk.id, { chunk, ref: `${chapter.book} ${chapter.chapter}:${chunk.startVerse}–${chunk.endVerse}` })));
|
||
return out;
|
||
};
|
||
|
||
// current vs older -> { titleChanged, changed: [{ ref, fields }], removedSince: [ref], addedSince: [ref], identical }
|
||
// "removedSince" = chunks the older version has that the study doesn't now (restoring brings them back);
|
||
// "addedSince" = chunks written since (restoring takes them away, though the copy you replace is kept).
|
||
export function diffProjects(current, older) {
|
||
const now = chunksOf(current);
|
||
const then = chunksOf(older);
|
||
const changed = [];
|
||
const removedSince = [];
|
||
const addedSince = [];
|
||
for (const [id, { chunk, ref }] of then) {
|
||
const mine = now.get(id);
|
||
if (!mine) { removedSince.push(ref); continue; }
|
||
const fields = Object.keys(FIELD_NAMES).filter((f) => !same(mine.chunk[f], chunk[f])).map((f) => FIELD_NAMES[f]);
|
||
if (!same(mine.chunk.tags, chunk.tags)) fields.push('Tags');
|
||
if (!same(mine.chunk.crossReferences, chunk.crossReferences)) fields.push('Cross-references');
|
||
if (!same(mine.chunk.greekWords, chunk.greekWords)) fields.push('Words');
|
||
if (fields.length) changed.push({ ref, fields });
|
||
}
|
||
for (const [id, { ref }] of now) if (!then.has(id)) addedSince.push(ref);
|
||
const titleChanged = (current?.title ?? '') !== (older?.title ?? '');
|
||
const outlineChanged = !same(current?.outline, older?.outline);
|
||
return { titleChanged, outlineChanged, changed, removedSince, addedSince, identical: !titleChanged && !outlineChanged && !changed.length && !removedSince.length && !addedSince.length };
|
||
}
|
||
|
||
export function describeDiff(diff) {
|
||
if (diff.identical) return ['This version is the same as what you have now.'];
|
||
const lines = [];
|
||
if (diff.titleChanged) lines.push('The title is different.');
|
||
for (const c of diff.changed) lines.push(`${c.ref}: ${c.fields.join(', ')} differ${c.fields.length === 1 ? 's' : ''}.`);
|
||
if (diff.removedSince.length) lines.push(`Brings back ${diff.removedSince.length} chunk${diff.removedSince.length === 1 ? '' : 's'} deleted since: ${diff.removedSince.join('; ')}.`);
|
||
if (diff.addedSince.length) lines.push(`Takes away ${diff.addedSince.length} chunk${diff.addedSince.length === 1 ? '' : 's'} added since: ${diff.addedSince.join('; ')}.`);
|
||
if (diff.outlineChanged) lines.push('The whole-study outline is different.');
|
||
return lines;
|
||
}
|