diff --git a/src/renderer/src/components/PassageDetail/PassageDetailMarkVerses.test.tsx b/src/renderer/src/components/PassageDetail/PassageDetailMarkVerses.test.tsx index 8f09ff81..2f26ea73 100644 --- a/src/renderer/src/components/PassageDetail/PassageDetailMarkVerses.test.tsx +++ b/src/renderer/src/components/PassageDetail/PassageDetailMarkVerses.test.tsx @@ -537,15 +537,24 @@ test('blocks autosave when markup has hard reference errors', async () => { ?.firstChild as HTMLElement; await waitFor(() => expect(tbody.children.length).toBeTruthy()); + // Load saved segment data with an out-of-passage ref ("9:9") into the table. act(() => { if (mockPlayerAction) { mockPlayerAction( '{"regions":"[{\\"start\\":0,\\"end\\":5,\\"label\\":\\"9:9\\"}]"}', - false + true ); } }); + // Simulate a user boundary edit (init=false) so checkBlockersAndScheduleAutosave + // runs with "9:9" still in the table — the blocker should be detected and warned. + act(() => { + if (mockPlayerAction) { + mockPlayerAction('{"regions":"[{\\"start\\":0,\\"end\\":6}]"}', false); + } + }); + await waitFor(() => { expect(mockShowMessage).toHaveBeenCalledWith( expect.anything(), diff --git a/src/renderer/src/components/PassageDetail/PassageDetailMarkVerses.tsx b/src/renderer/src/components/PassageDetail/PassageDetailMarkVerses.tsx index d5dab1e8..e8f0fd93 100644 --- a/src/renderer/src/components/PassageDetail/PassageDetailMarkVerses.tsx +++ b/src/renderer/src/components/PassageDetail/PassageDetailMarkVerses.tsx @@ -185,7 +185,6 @@ export function PassageDetailMarkVerses({ width }: MarkVersesProps) { const { toolChanged, toolsChanged, - isChanged, saveRequested, saveCompleted, clearRequested, @@ -616,7 +615,10 @@ export function PassageDetailMarkVerses({ width }: MarkVersesProps) { if (reset) { resetSegments(regions); } - if (!init && !isChanged(verseToolId)) toolChanged(verseToolId); + if (!init) { + toolChanged(verseToolId); + checkBlockersAndScheduleAutosave(); + } } }; @@ -741,6 +743,7 @@ export function PassageDetailMarkVerses({ width }: MarkVersesProps) { setData(newData); setSegments(); toolChanged(verseToolId); + checkBlockersAndScheduleAutosave(); } }; @@ -845,8 +848,8 @@ export function PassageDetailMarkVerses({ width }: MarkVersesProps) { // eslint-disable-next-line react-hooks/exhaustive-deps }, [toolsChanged, scheduleAutosave]); - useEffect(() => { - if (!isChanged(verseToolId) || !hasPermission || savingRef.current) return; + const checkBlockersAndScheduleAutosave = () => { + if (!hasPermission) return; const allIssues = checkRefs(); const blockers = checkAutosaveBlockers(); setSaveIssues(allIssues); @@ -885,8 +888,7 @@ export function PassageDetailMarkVerses({ width }: MarkVersesProps) { setIssuesDialogOpen(false); } scheduleAutosave(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [toolsChanged, hasPermission, scheduleAutosave]); + }; return Boolean(mediafileId) && passType !== PassageTypeEnum.NOTE ? ( diff --git a/src/renderer/src/hoc/SnackBar.tsx b/src/renderer/src/hoc/SnackBar.tsx index d0e713df..4ea0a88f 100644 --- a/src/renderer/src/hoc/SnackBar.tsx +++ b/src/renderer/src/hoc/SnackBar.tsx @@ -1,5 +1,5 @@ /* eslint-disable react-refresh/only-export-components */ -import { useState, useEffect } from 'react'; +import { useState, useEffect, Fragment } from 'react'; import { useGlobal } from '../context/useGlobal'; import { Snackbar as MuiSnackbar, @@ -45,8 +45,9 @@ function SimpleSnackbar(props: ISBProps) { }; useEffect(() => { - if ((message?.type === 'span') !== open) { - setOpen(!open); + const hasMessage = !!message && message.type !== Fragment; + if (hasMessage !== open) { + setOpen(hasMessage); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [message]);