Highlight translation differences, first-draft snapshot, verse notes, paste check

- Compare translations can highlight the words that differ from the first
  translation (toggle remembered).
- A copy of your notes is kept the first time commentary is shown; "First draft,
  before commentary" under More shows what changed since. Saving it doesn't
  count as editing the chunk.
- Notes on single verses: a pencil next to each verse in Study, and a note line
  under each verse in Compare. They merge per verse across devices.
- Pasting 15+ words into a note asks "Is this from AI?"; "I wrote it" counts the
  words as yours again.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-14 12:56:57 -04:00
1 parent 3a28ffa51a
commit 648c3206df
14 files changed
+232 -27

No files matched your search

+20 -1
View File
@@ -448,6 +448,26 @@ describe('Study workspace', () => {
expect(notes).toHaveAttribute('aria-expanded', 'true');
});
test('a long paste asks if it is from AI; "I wrote it" takes the tag back', async () => {
const user = await studyOneChunk();
const observe = screen.getByRole('textbox', { name: 'Observe' });
const pasted = Array.from({ length: 20 }, (_, i) => `pasted${i}`).join(' ');
fireEvent.paste(observe, { clipboardData: { getData: () => pasted } });
fireEvent.change(observe, { target: { value: pasted } });
expect(await screen.findByText(/is this from ai\?/i)).toBeInTheDocument();
expect(screen.getByText(/20 words here were pasted/i)).toBeInTheDocument();
await user.click(screen.getByRole('button', { name: /i wrote it/i }));
expect(screen.queryByText(/is this from ai\?/i)).not.toBeInTheDocument();
expect(screen.queryByText(/were pasted/i)).not.toBeInTheDocument();
});
test('a short paste is not asked about', async () => {
await studyOneChunk();
const observe = screen.getByRole('textbox', { name: 'Observe' });
fireEvent.paste(observe, { clipboardData: { getData: () => 'just a few words' } });
expect(screen.queryByText(/is this from ai\?/i)).not.toBeInTheDocument();
});
test('compare translations: the Observe / Interpret / Apply boxes edit the same notes', async () => {
const user = await studyOneChunk();
await user.click(screen.getByRole('button', { name: /compare…/i }));
@@ -549,4 +569,3 @@ describe('Reading plan with more days than chapters', () => {
expect(screen.queryByText(/back to today.s reading/i)).not.toBeInTheDocument();
});
});