Fix review findings on the Paratext 9 import WebView - #295
Fix review findings on the Paratext 9 import WebView#295alex-rawlings-yyc wants to merge 1 commit into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Team Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
This may be partially redundant with #292. I'm investigating now. |
|
@imnasnainaec Right you are. #292 already covers everything on this branch except one thing.
Everything else is duplicated by #292 or worse than it. Closing in favor of #292 plus that guard. |
Adopted from the review fixes on #295. The report stays dismissable while the Open's summary fetch is in flight, so Escape back to the picker and then a summary landing switched the active project and closed the picker the user had returned to. The handler now checks the report is still the modal on screen before acting, which also keeps its failure notice out of whatever they moved on to. Two smaller things from the same review: the failed-load line no longer prints under "Loading..." or a book error, which would have contradicted them; and `Pt9ImportModal`'s `onOpen` doc said Open renders in `import` mode alone, which stopped being true when the offer report was given its Open. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
I did take 3 things from this pr:
|
* Seal the read-only import and make its sync land Every editing affordance the read-only import view still offered is gone, and a sync now reaches the view it refreshed. - Merge, baseline-split, and arc-split controls read the store's read-only flag; the import view's segmentation dispatch is inert as a backstop, and a phrase mode entered on the draft no longer carries into the import. - The import's analysis is cleared before each fetch, so the store's mount-time seed cannot pin pre-sync content in the view; a fetch that brings back nothing says so in the view area. - The accepted first-open offer gets its intended single-door report. - Opening an import runs through the select modal's submit guard, and the first-open probe gives up rather than hanging the tab. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Bound the manifest read and catch the report's Open Reading a Paratext 9 manifest now goes through one helper that gives up when the provider never answers, so no caller can wait on it forever. - The select modal is held inert for the whole of an import open, so a hung manifest read had left it with no Escape, no outside-click, and a disabled Cancel. A read that never answers is now an ordinary failure: one warning, the stored import opens, the modal comes back. - The first-open probe reads through the same helper and keeps its plain try/catch. - A rejecting fetch behind the report's Open is logged and notified rather than escaping the click handler unhandled. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Tag the import analysis with the version it was fetched for The view derives what to show from the tag rather than having an effect clear the previous analysis: a fetched analysis and the version it belongs to now reach the view in the same commit, so the commit that carries a sync's new modification time has no pre-sync analysis to paint - previously it mounted the whole interlinear tree on the old content for a frame before the placeholder replaced it. Also records that the manifest timeout bounds the wait rather than the read, PAPI offering no cancellation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Trim the import-analysis comments to what outlives the code Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Report a failed import load once, in the panel The imported-analysis fetch sent a toast on top of the panel's own failure line, so one failure produced two messages with different advice - and the toast in the catch ran even for a fetch a sync or a switch back to the draft had already superseded. The panel line is now the whole report: it stays on screen next to the empty view instead of disappearing. Also seals two ways a stale mode or hover could outlive the control it came from: the import view pins its phrase mode to view, since the reset effect only covers crossing into the import and a mode set from inside it has no crossing to reset it; and a split hover clears when the analysis turns read-only, since the button that vanishes never fires its own mouse-leave. The read-only mock boilerplate that had been copied into three test files moves to a module of its own, and resets in beforeEach rather than afterEach. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Drop an Open fetch the user has already walked away from Adopted from the review fixes on #295. The report stays dismissable while the Open's summary fetch is in flight, so Escape back to the picker and then a summary landing switched the active project and closed the picker the user had returned to. The handler now checks the report is still the modal on screen before acting, which also keeps its failure notice out of whatever they moved on to. Two smaller things from the same review: the failed-load line no longer prints under "Loading..." or a book error, which would have contradicted them; and `Pt9ImportModal`'s `onOpen` doc said Open renders in `import` mode alone, which stopped being true when the offer report was given its Open. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Seal the read-only import and make its sync land Every editing affordance the read-only import view still offered is gone, and a sync now reaches the view it refreshed. - Merge, baseline-split, and arc-split controls read the store's read-only flag; the import view's segmentation dispatch is inert as a backstop, and a phrase mode entered on the draft no longer carries into the import. - The import's analysis is cleared before each fetch, so the store's mount-time seed cannot pin pre-sync content in the view; a fetch that brings back nothing says so in the view area. - The accepted first-open offer gets its intended single-door report. - Opening an import runs through the select modal's submit guard, and the first-open probe gives up rather than hanging the tab. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Bound the manifest read and catch the report's Open Reading a Paratext 9 manifest now goes through one helper that gives up when the provider never answers, so no caller can wait on it forever. - The select modal is held inert for the whole of an import open, so a hung manifest read had left it with no Escape, no outside-click, and a disabled Cancel. A read that never answers is now an ordinary failure: one warning, the stored import opens, the modal comes back. - The first-open probe reads through the same helper and keeps its plain try/catch. - A rejecting fetch behind the report's Open is logged and notified rather than escaping the click handler unhandled. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Tag the import analysis with the version it was fetched for The view derives what to show from the tag rather than having an effect clear the previous analysis: a fetched analysis and the version it belongs to now reach the view in the same commit, so the commit that carries a sync's new modification time has no pre-sync analysis to paint - previously it mounted the whole interlinear tree on the old content for a frame before the placeholder replaced it. Also records that the manifest timeout bounds the wait rather than the read, PAPI offering no cancellation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Trim the import-analysis comments to what outlives the code Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Report a failed import load once, in the panel The imported-analysis fetch sent a toast on top of the panel's own failure line, so one failure produced two messages with different advice - and the toast in the catch ran even for a fetch a sync or a switch back to the draft had already superseded. The panel line is now the whole report: it stays on screen next to the empty view instead of disappearing. Also seals two ways a stale mode or hover could outlive the control it came from: the import view pins its phrase mode to view, since the reset effect only covers crossing into the import and a mode set from inside it has no crossing to reset it; and a split hover clears when the analysis turns read-only, since the button that vanishes never fires its own mouse-leave. The read-only mock boilerplate that had been copied into three test files moves to a module of its own, and resets in beforeEach rather than afterEach. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Drop an Open fetch the user has already walked away from Adopted from the review fixes on #295. The report stays dismissable while the Open's summary fetch is in flight, so Escape back to the picker and then a summary landing switched the active project and closed the picker the user had returned to. The handler now checks the report is still the modal on screen before acting, which also keeps its failure notice out of whatever they moved on to. Two smaller things from the same review: the failed-load line no longer prints under "Loading..." or a book error, which would have contradicted them; and `Pt9ImportModal`'s `onOpen` doc said Open renders in `import` mode alone, which stopped being true when the offer report was given its Open. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…274) * Rebuild the import replacement from buildNew and drop the summary tests * Add the Paratext 9 import WebView experience with a first-open offer The UI half of the PT9 import. The select modal gains the import button (shown only when the source serves convertible data, via usePt9ImportAvailability); Pt9ImportModal carries the run, its report, and its failures, including the too-large refusal recognized by the RESOURCE_EXHAUSTED platform error code with the documented message marker as fallback. An import opens read-only: every editing affordance stays away, a banner carries sync and copy-to-editable, and CopyToEditableModal clones an import into an editable project. On the first open of a source with convertible PT9 data and no stored state, Pt9ConvertPromptModal offers the conversion up front: Yes runs the import as the only project created, No (or dismissing) persists the empty draft so the offer never repeats, per the user-questions entry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * State the read-only rendering on the provenance doc Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Follow the guard move and shared fixtures through the WebView tree The Loader imports isPt9ImportReport from the converter surface that now owns it, the frontend-mock helper rides this tree with its users, and the offer and hasDraft tests use the shared ENOENT fixture. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Open fast, indicate the probe, and make the offer report one door * Mark the unfolded sense counters as resolver-work TODO * Seal the read-only import and make its sync land (#292) * Seal the read-only import and make its sync land Every editing affordance the read-only import view still offered is gone, and a sync now reaches the view it refreshed. - Merge, baseline-split, and arc-split controls read the store's read-only flag; the import view's segmentation dispatch is inert as a backstop, and a phrase mode entered on the draft no longer carries into the import. - The import's analysis is cleared before each fetch, so the store's mount-time seed cannot pin pre-sync content in the view; a fetch that brings back nothing says so in the view area. - The accepted first-open offer gets its intended single-door report. - Opening an import runs through the select modal's submit guard, and the first-open probe gives up rather than hanging the tab. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Bound the manifest read and catch the report's Open Reading a Paratext 9 manifest now goes through one helper that gives up when the provider never answers, so no caller can wait on it forever. - The select modal is held inert for the whole of an import open, so a hung manifest read had left it with no Escape, no outside-click, and a disabled Cancel. A read that never answers is now an ordinary failure: one warning, the stored import opens, the modal comes back. - The first-open probe reads through the same helper and keeps its plain try/catch. - A rejecting fetch behind the report's Open is logged and notified rather than escaping the click handler unhandled. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Tag the import analysis with the version it was fetched for The view derives what to show from the tag rather than having an effect clear the previous analysis: a fetched analysis and the version it belongs to now reach the view in the same commit, so the commit that carries a sync's new modification time has no pre-sync analysis to paint - previously it mounted the whole interlinear tree on the old content for a frame before the placeholder replaced it. Also records that the manifest timeout bounds the wait rather than the read, PAPI offering no cancellation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Trim the import-analysis comments to what outlives the code Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Report a failed import load once, in the panel The imported-analysis fetch sent a toast on top of the panel's own failure line, so one failure produced two messages with different advice - and the toast in the catch ran even for a fetch a sync or a switch back to the draft had already superseded. The panel line is now the whole report: it stays on screen next to the empty view instead of disappearing. Also seals two ways a stale mode or hover could outlive the control it came from: the import view pins its phrase mode to view, since the reset effect only covers crossing into the import and a mode set from inside it has no crossing to reset it; and a split hover clears when the analysis turns read-only, since the button that vanishes never fires its own mouse-leave. The read-only mock boilerplate that had been copied into three test files moves to a module of its own, and resets in beforeEach rather than afterEach. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Drop an Open fetch the user has already walked away from Adopted from the review fixes on #295. The report stays dismissable while the Open's summary fetch is in flight, so Escape back to the picker and then a summary landing switched the active project and closed the picker the user had returned to. The handler now checks the report is still the modal on screen before acting, which also keeps its failure notice out of whatever they moved on to. Two smaller things from the same review: the failed-load line no longer prints under "Loading..." or a book error, which would have contradicted them; and `Pt9ImportModal`'s `onOpen` doc said Open renders in `import` mode alone, which stopped being true when the offer report was given its Open. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: D. Ror. <imnasnainaec@gmail.com>
Review fixes for #274, branched off
pt9-parsed-webviewat ef8e70b. Five defects, each with a regression test that fails against that commit.Read-only enforcement had three holes
#274 guards
BoundaryControlandPhraseStripParts, but three parallel mutation routes stayed live in an import view:SegmentListView.tsx:428— the between-rows merge button dispatchessegmentationDispatch.merge, which writes boundaries into the user's editable draft and flips the dirty indicator. Nothing visible happens in the import, sincebookis computed withresegmentBook(verseBook, undefined)there, so it silently corrupts an unrelated draft.SegmentView.tsx:191— Alt+click on a baseline-text split gap: the same silent draft write, in continuous-scroll mode. The Alt-gatedSplitMarkerinPhraseStripPartsis covered; this is its baseline-mode twin.ArcOverlay.tsx:291— the arc split button.analysisMerger.ts:401emitsphraseAnalysisLinks, so imports do draw arcs; hovering one revealsLink2Off, and a click deletes a 2-token phrase outright. WithPhraseBox's pill andTokenLinkIconboth gated, this was the only surviving route that visibly mutates the import.ArcOverlaytakes areadOnlyprop rather than reading the hook — it's a presentational leaf whose tests render it bare, so the hook would have forced a provider onto every call site.The offer mode never reached the modal
InterlinearizerLoader.tsx:1261collapsedpt9Mode === 'offer'into'import', leavingPt9ImportModal's entiremode === 'offer'branch dead outside its own unit test. Both consequences contradict the spec added inuser-questions.md("a single Open (dismissing the report also opens…)"): the offer report rendered Close + Open, and dismissing it routed throughhandlePt9Close→setModal('none'), so a successful conversion was never opened — the user had to go find it in Select. The test "returns to the plain view when an offer-run report is closed" locked that in; it's replaced by two tests asserting the documented behavior.A failed import-analysis load rendered a blank pane
Once the book has loaded and neither book error applies, all three of
loadingOrErrorPanel's conditionals are falsy, so the user got an empty content area plus a toast. Reachable throughopenImportedProject's:718fallback. Adds animportLoadFailedstate, an on-screen message, and a localized string.handlePt9Openwrote state after the user backed outThe report stays dismissable during
fetchSummary, so Escape → back to Select → resolve closed the Select modal and switched the active project anyway. Adds amodalRefin-flight guard.One finding investigated and rejected
A claim that a manual sync remounts the store seeded with the pre-sync analysis (
initialAnalysisis a non-reactive lazy-ref seed while the key carriesupdatedAt). Instrumenting the actual mount sequence with and without the proposed fix gave identical seeds both ways — React's batching means the remount already happens after the fresh analysis lands. No code change; the test asserting the correct behavior stays, since nothing covered it before.Verified clean
No change needed, recorded so it isn't re-checked:
savePt9Import'sbuildNew()spread is field-for-field equivalent to the literal it replaced; theopenRequesteffect's exhaustive-deps disable has no stale closure;hasDraft/hasNoInterlinearizerStatehandle ENOENT correctly;__setMockAnalysisReadOnly's module state is reset in every file that touches it.Left for review
isPt9TooLargeErrorcallserror.message.includes(...)afterisPlatformError, whose real guard only checks forplatformErrorVersion. A platform error withoutmessagewould throw out of thecatchinrunPt9Import. Whether any producer omits it is unverified, so this is untouched rather than guessed at.Also
A comment-rules pass: two mock docs naming the wrong lifecycle hook, one over-long doc, one mechanism-explaining inline.
This change is