Skip to content

fix(watch): preserve viewport and center document paths - #268

Open
ljdstechva wants to merge 1 commit into
iOfficeAI:mainfrom
ljdstechva:codex/ogent-v0101-viewer-contract
Open

fix(watch): preserve viewport and center document paths#268
ljdstechva wants to merge 1 commit into
iOfficeAI:mainfrom
ljdstechva:codex/ogent-v0101-viewer-contract

Conversation

@ljdstechva

Copy link
Copy Markdown

Summary

  • preserve the latest semantic viewport anchor across Word, Excel, and PowerPoint live-watch DOM updates
  • stop PowerPoint replace/add updates from automatically scrolling to the edited slide
  • extend watch goto to trusted document paths and server-issued mark IDs for all three formats
  • allow exact mark removal by server-issued ID so embedders do not clear unrelated marks
  • honor reduced-motion preferences for explicit viewer navigation

Motivation

An embedder can keep its iframe identity stable and let OfficeCLI's SSE renderer update in place, but the viewer still moved during some internal DOM updates. PowerPoint replace/add always called scrollToSlide(slideNum), while Word pagination and Excel body/row replacement preserved only partial or raw scroll state. This made the edited target override a user's most recent manual viewing position.

Historical-selection navigation also needs a public, path-based command for Excel and PowerPoint. The existing watch goto path conversion was Word-only, and mark removal by path could remove another advisory mark on the same element.

Design

  • Capture immediately before each mutation so scrolling performed while an update is in flight wins.
  • Restore the nearest visible data-path and relative offset; fall back to adjacent paths, the closest surviving slide, then raw scroll coordinates.
  • Cancel a queued restoration whenever trusted wheel, touch, pointer, or keyboard navigation occurs.
  • Keep explicit goto separate from mutation updates and center it in both axes.
  • Resolve path requests against the watch server's cached HTML; callers never provide CSS selectors over the new path channel.
  • Resolve mark navigation/removal using server-issued numeric IDs.

The existing watch scope remains broadcast: every viewer connected to the same document watch receives an explicit navigation event.

Verification

  • node --check src/officecli/Resources/watch-sse-core.js
  • .NET 10 dotnet publish src/officecli/officecli.csproj -c Release -r win-x64
  • git diff --check
  • real Word acceptance: page 5/6 anchor retained at scrollY=5927.333496; focused targets centered at 49.99% and 50.08%
  • real Excel acceptance: active sheet plus horizontal/vertical viewport retained at (659.333313, 4143.333496); focused cell centered at 49.51% vertical and 49.19% horizontal
  • real PowerPoint acceptance: slide 12 viewport retained at scrollTop=5371.333496; focused shape centered at 49.06%
  • normal completion, controlled error, and stopped runs produced zero additional iframe loads
  • package SHA-256 checks confirmed viewer marks/navigation did not modify the Office files

The local build reports one pre-existing nullable warning in ExcelHandler.SheetShift.cs; there are no build errors.

@goworm

goworm commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Thanks for this — the viewport work is genuinely nice, and the bisection-level care shows.

One request before we merge: this PR bundles two different things, and we'd like to take them separately.

The bug fix — preserving the viewer's viewport across SSE updates (and dropping the forced scrollToSlide() on PPT replace/add). This is a real UX bug that affects every watch user, not just embedders — editing a doc shouldn't yank the viewport to the changed slide/page. We're happy to merge this on its own. Could you split it into a dedicated PR containing just that?

The new capabilitygoto by data-path for Excel/PPT, --mark-id navigation, unmark --id, the server-issued-mark contract. This is a larger surface that mainly serves a programmatic-embedding workflow, and merging it means we take on maintaining that contract long-term. Before we commit to it, could you describe the concrete use case driving it — what the embedder is building, and why path/mark-id navigation over the pipe is the right shape for it? That'll help us decide whether to adopt it as-is, scope it down, or track it against an issue.

Splitting also keeps the bug fix landing fast without waiting on the design discussion. Appreciate the work either way. 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants