Complete the deferred-features tails: Review-tab polish, rotated-cell caret, reflow link-open, grid zoom, overflow-menu dismissal, and more#32
Merged
Conversation
…rops eq (5.11 tail, 6.7) Reflow half of feature 5.11: DocumentView resolves the URL against its continuous layout (reflow_link_at plumbing through RenderLayout and DocPageSource) and reports it via a new on_open_link handler; loki-text opens it with webbrowser, keeping the browser dependency in the app layer. Resolves TODO(link-click-reflow). Also replaces the hardwired-false DocumentViewProps PartialEq with a real field comparison (plan 6.7): doc/paginated_layout by Arc identity, scalars by value; event handlers deliberately omitted (Dioxus EventHandlers always compare equal). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017mBbeUqSR6utoozCfLoswr
…4b.5 tail) Resolves TODO(rotated-cell-caret). The caret line, selection fills, and selection handles now paint through a rotation-aware affine (scene_cursor::cursor_paint_transform composes the CellRotation the cell's content is painted with), so the caret tilts with rotated table-cell text instead of staying upright. Cursor painting moved to a new scene_cursor.rs (scene.rs is baselined and shrank instead). Up/down arrow navigation maps the caret position through PageParagraphData::local_to_page and aims at neighbouring paragraphs via a new visual_y_span (post-rotation bounding box), replacing the raw rect+origin math. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017mBbeUqSR6utoozCfLoswr
… (4a.2) Resolves TODO(review-para-mark-render). A tracked paragraph-mark deletion (direct_char_props.revision of kind Deletion) now paints a struck, author-coloured marker after the paragraph's last line: two short stems + a strikethrough segment, emitted as paint-only items in para_underlays so caret placement, hit-testing, and wrapping are untouched. The colour rides ResolvedParaProps.para_mark_deleted_color, set by resolve_para_props via revision_style::para_mark_deletion_color. Root-cause fix found while wiring: flatten_paragraph merged the paragraph's direct_char_props into the run base without clearing revision, so a pilcrow-deleted paragraph rendered its entire text struck in the author colour. The run base now drops the ¶'s revision. Regression-locked by tracked_para_mark_deletion_renders_struck_marker_without_striking_text. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017mBbeUqSR6utoozCfLoswr
…tail) The remaining Review-tab polish item: a tracked pilcrow deletion now survives save/open through ODF. Export emits an end-of-paragraph text:change milestone whose deletion region stows only the paragraph break (an empty text:p — LibreOffice's shape for a deleted paragraph mark); import maps an empty-deletion change point back onto the paragraph's CharProps.revision instead of materialising a struck empty run. The revision-mapping helpers moved to a new inlines_revision.rs sibling module to hold the 300-line ceiling. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017mBbeUqSR6utoozCfLoswr
Resolves TODO(split-optimise). Each ClippedGroup fragment of a page-spanning paragraph now carries only the items whose (conservatively over-estimated) vertical extent intersects the fragment's y-range (ParagraphLayout::items_in_y_range in para_query.rs), instead of a full copy of every paragraph item per page. The Option-A clip rect is kept, so any conservatively-retained extra item is still masked and rendering is pixel-identical; an item with unknown extent is always kept. Also retires the stale TODO(link-click) notes (5.11 shipped both halves). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017mBbeUqSR6utoozCfLoswr
Verification first: the paragraph and table-cell dispatch loops never skipped unknown elements, so inline (w:p/w:sdt) and cell-level (w:tc/w:sdt) sdtContent was already implicitly unwrapped — the deferral note was stale. This pins that behaviour with reader regression tests (inline runs + sdtPr chrome; cell paragraphs before/inside a control) and hardens both dispatches by skipping w:sdtPr/w:sdtEndPr wholesale, matching the explicit block-level unwrapper, so control chrome internals can never leak into the content dispatch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017mBbeUqSR6utoozCfLoswr
Migrates the border codec to a v2 layout (Style:width:spacing:color) whose color field comes last, so the total color codec's colon-delimited encodings fit unescaped — non-Rgb border colors no longer collapse to auto. The decoder accepts both layouts (v2's third field is always a number, v1's never is), so pre-migration CRDT snapshots keep decoding. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017mBbeUqSR6utoozCfLoswr
…tail) The zoom badge now cycles 50-200% (appthere_ui::next_zoom) and scales the rendered grid: column widths, row heights, header sizes, and cell/header fonts. The document keeps unzoomed pt widths — col_px multiplies the zoom in, resize commits divide the screen px back out (clamped in screen space), and auto-fit passes its document-px estimate through the same conversion. apply_change/sync_undo_redo moved to editor_mutate.rs (their natural home) to keep editor_inner.rs under its ceiling baseline. Also drops an unused import left by the border-codec migration. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017mBbeUqSR6utoozCfLoswr
…tail) New shared appthere_ui::AtViewportWidthSensor: an invisible zero-height, full-width scroll container that measures its own width into the responsive context at mount and re-measures on every shell resync_scroll_geometry tick (blitz re-emits onscroll to scroll containers after a window resize). Presentation and Spreadsheet now call use_provide_responsive() and mount the sensor, so AtHomeTab's breakpoint tracks the real window there instead of falling back to Expanded — loki-text keeps funnelling its editor scroll-container width as before. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017mBbeUqSR6utoozCfLoswr
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017mBbeUqSR6utoozCfLoswr
…backdrop (4a.1 tail) Resolves TODO(ribbon). New appthere_ui overlay primitives: use_provide_backdrop() + AtBackdropHost render a transparent viewport-spanning click-catcher inside the app's (now position: relative) root container — the host lives at the window level because position: fixed collapses to absolute in stylo_taffy, so a backdrop rendered inside the ribbon could never span the viewport. The overflow menu itself stays anchored to its More button (no coordinate plumbing); opening it raises the backdrop (menu z 41 > backdrop z 40), clicking anywhere outside closes it, and a use_drop guard clears a stale backdrop if the strip unmounts while open. All three apps wire the context for suite consistency; degrades to toggle-only dismissal without it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017mBbeUqSR6utoozCfLoswr
- deferred-features plan/audit: mark the tails completed this pass (4a.1 More-menu dismissal, 4a.2 struck-pilcrow render + ODF pilcrow round-trip, 4b.5 rotated caret/nav, 4c.5 grid zoom + F7a width plumbing, 5.9 sdt verification, 5.11 reflow open, 6.3 Option B filter, 6.7 props eq, loro-bridge border colors) and record two stale entries verified as already built (typed SaveError; inline/cell w:sdt were never dropped). - fidelity-status: Hyperlinks, Text Direction (rotated cells), and Track Changes rows updated to their completed state. - file-ceiling baseline ratcheted (scene.rs 727->613, spreadsheet editor_inner 1047->1014, resolve.rs 865->858, mapper files); CLAUDE.md worst-offenders table refreshed from it. - clippy 1.97 nits: doc_markdown/doc_lazy_continuation in new docs, needless_borrow in loki-vello's visual_conformance test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017mBbeUqSR6utoozCfLoswr
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the remaining actionable tails from
docs/deferred-features-plan-2026-07-04.md(the partially-implemented features' leftover work), plus two stale entries verified as already built. Twelve focused commits:Editor / Review tab (4a.2 polish — track changes now fully complete)
TODO(review-para-mark-render)): a tracked paragraph-mark deletion paints a struck, author-coloured end-of-paragraph marker (paint-only items, so caret/hit-test/wrapping are untouched — the constraint that had deferred it). Root-cause fix found while wiring:flatten_paragraphbled the ¶'s revision onto the runs, striking the whole paragraph text; regression-locked.text:changewhose deletion region stows the paragraph break (emptytext:p, LibreOffice's shape); import maps it back onto the paragraph. DOCX already round-tripped.Rotated table cells (4b.5 complete)
loki-vello/scene_cursor.rs; unit-tested againstCellRotation::local_to_page), so the caret tilts with the text; up/down arrow navigation is rotation-aware vialocal_to_page+ a newvisual_y_span.Hyperlinks (5.11 complete)
DocumentViewresolves the URL against its continuous layout and reports it via a newon_open_linkhandler; the browser dependency stays in the app layer.Apps (4c.5 tails + 4a.1 tail)
TODO(zoom)): the status-bar badge cycles 50–200%, scaling widths/heights/fonts while the document keeps unzoomed pt (resize commits divide the zoom back out).AtViewportWidthSensor; Presentation + Spreadsheet now provide the responsive context and push a measured width, soAtHomeTab's breakpoint tracks the real window.TODO(ribbon)): new window-level backdrop primitives (use_provide_backdrop+AtBackdropHost) hosted in the apps' now-positioned roots; the menu stays anchored, a viewport-spanning transparent backdrop closes it.Model / formats
w:sdt(5.9 tail): verified the reader never dropped them (stale deferral note); behaviour regression-locked and both dispatches hardened to skipw:sdtPrchrome wholesale.Performance
TODO(split-optimise)): split-paragraph fragments carry only the items near their own y-range instead of a full per-page copy; the Option-A clip is kept so rendering is pixel-identical.DocumentViewProps::eq(6.7): replaces the hardwired-falsecomparison (Arc-identity + value fields).Docs & hygiene
SaveErroralready existed; inline/cell sdt were never dropped); file-ceiling baseline ratcheted (scene.rs727→613, spreadsheeteditor_inner.rs1047→1014,resolve.rs865→858); CLAUDE.md offender table refreshed; staleTODO(link-click)notes retired.Verification
cargo +1.97 clippy --workspace --all-features -- -D warnings -D clippy::unwrap_used -D clippy::expect_used— clean (the toolchain CI uses).cargo +1.97 fmt --all -- --check— clean.scripts/check-file-ceiling.py— green (baseline only shrank).cargo test --workspace— all suites pass except 3 pre-existingappthere-conformanceraster tests that requirepdftoppm(poppler-utils is not installable in this sandbox; CI installs it).Remaining deferrals stay tracked in the plan: upstream-gated Watch-list items, device-gated Spec 06 work, post-MVP Calc/Slides scope, and the larger still-open workstreams (OMML 5.8, Spec 04 M6 touch posture, Spec 03 M4 type-scale, 4a.3 table-style/editing-UI tails, clipboard, memory 6.1/6.2, Phase 7 quality ratchets).
🤖 Generated with Claude Code
https://claude.ai/code/session_017mBbeUqSR6utoozCfLoswr
Generated by Claude Code