Skip to content

refactor(app): extract timeline scroll intent helper#671

Merged
Astro-Han merged 9 commits into
devfrom
codex/timeline-scroll-intent-contract
May 16, 2026
Merged

refactor(app): extract timeline scroll intent helper#671
Astro-Han merged 9 commits into
devfrom
codex/timeline-scroll-intent-contract

Conversation

@Astro-Han
Copy link
Copy Markdown
Owner

@Astro-Han Astro-Han commented May 16, 2026

Topology Update (2026-05-16)

Restored after #670 was squash-merged and its stacked base branch was deleted.

Final base: dev at #682 merge commit 6c643a4b.
Head after latest dev update: d1f5af8d on codex/timeline-scroll-intent-contract.
Dependency status: no longer targets the deleted #670 branch. This PR now carries only the #671 scroll-intent helper diff against dev.
Review order: review before #672, because #672 still stacks on codex/timeline-scroll-intent-contract.
Verification after latest dev update: bun --cwd packages/app test --preload ./happydom.ts src/pages/session/session-timeline-scroll-intents.test.ts src/pages/session/session-timeline-scroll-controller.test.ts -> 1138 pass; git diff --check origin/dev...HEAD && git diff --check -> pass. GitHub typecheck/lint/unit/e2e/desktop smoke were rerunning on the updated head.
CI after latest push: rerunning on the updated head. Fresh-eyes review P2 about staging scope was fixed by removing staging files from the current PR diff.


Summary

Extracted the MessageTimeline scroll intent and metrics adapter into session-timeline-scroll-intents.ts, then added focused unit coverage for the moved boundary.

Why

This is the next small #595/#615 scroll-perf slice in the frontend architecture governance stack. It does not claim to solve scroll stutter or consolidate the full scroll owner yet; it isolates the adapter code so the later controller/dock ownership work has a smaller, testable boundary.

Stack order after #670 merge: #671 -> #672 -> #674 -> #675.

Related Issue

Refs #595
Refs #615
Depends on #667, #669, and #670, all now merged to dev.

Canonical manifest: .github/frontend-architecture-manifest.md

Human Review Status

Pending. A human should make the final merge decision after reviewing the final diff and verification evidence.

Review Focus

Risk Notes

Low. This is a behavior-preserving extraction with focused tests. It does not change scroll strategy, controller transitions, createAutoScroll, dock state, visual layout, public UI exports, persistence, or platform behavior.

How To Verify

Focused tests: 1138 pass across app unit scope including session-timeline-scroll-intents and session-timeline-scroll-controller
Typecheck: 8 successful
Lint: passed
Diff check: no whitespace errors
CI: rerunning after latest #671 push on head d1f5af8d; required checks must pass before merge

Screenshots or Recordings

Not applicable. This is a non-visible extraction and test hardening PR.

Checklist

  • Human review status is stated above as pending, approved, or not required
  • I linked the related issue, or stated why there is no issue
  • This PR has type, primary area, and priority labels, or I requested maintainer labeling
  • I described the review focus and any meaningful risks
  • I listed the relevant verification steps and the key result for each
  • I did not introduce unrelated refactors, dependencies, generated files, or file changes beyond the stated scope
  • I manually checked visible UI or copy changes when needed, with screenshots or recordings
  • I considered macOS and Windows impact for platform, packaging, updater, signing, paths, shell, or permissions changes
  • I called out docs, release notes, dependencies, permissions, credentials, deletion behavior, generated content, or local file changes when relevant
  • I reviewed the final diff for unrelated changes and suspicious dependency changes
  • I am intentionally targeting dev; the previous stacked base was removed after refactor(app): extract timeline staging helper #670 merged

@Astro-Han Astro-Han added P2 Medium priority app Application behavior and product flows ui Design system and user interface task Maintainer or agent execution task tech-debt Internal cleanup and maintainability debt labels May 16, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 16, 2026

📝 Walkthrough

Walkthrough

This PR extracts reusable timeline scroll intent utilities (boundary detection, metric conversion, gesture factories) into a new module, then refactors message-timeline and session-timeline-staging to use the shared logic instead of local implementations.

Changes

Timeline scroll intent extraction and consumer refactoring

Layer / File(s) Summary
Timeline scroll intent module: boundary and conversion utilities
packages/app/src/pages/session/session-timeline-scroll-intents.ts
Exports TimelineBoundaryGesture type and boundary-detection functions (timelineBoundaryTarget, timelineBoundaryGesture, shouldMarkTimelineBoundaryGesture). Provides metric and intent conversion: scrollViewMetricsToTimelineMetrics computes top/bottom distances and near-threshold flags; scrollViewIntentToTimelineIntent maps scroll intents to timeline intents while preserving keyboard scroll semantics. Defines shouldMarkLegacyScrollIntent for keyboard and scrollbar-drag-start classification.
Timeline gesture intent factories and pointer builder
packages/app/src/pages/session/session-timeline-scroll-intents.ts
Exports createWheelTimelineScrollIntent and createTouchTimelineScrollIntent factories that normalize gesture deltas, compute boundary state, and return TimelineGestureIntentResult (delta, boundary info, classified intent). Internal pointer-intent builder handles metric enrichment and classification shared between wheel and touch paths.
Test coverage for timeline scroll intents
packages/app/src/pages/session/session-timeline-scroll-intents.test.ts
Comprehensive test suite covering metric conversion (distance/threshold computation and clamping), intent conversion (keyboard vs. scrollbar semantics), legacy intent classification, boundary gesture detection for main timeline vs. nested scrollables, and wheel/touch normalization including zero-delta edge cases.
Refactor message-timeline to use shared scroll intent utilities
packages/app/src/pages/session/message-timeline.tsx
Removes local gesture/scroll helper implementations. Updates imports and wheel/touch handlers to call createWheelTimelineScrollIntent/createTouchTimelineScrollIntent, sending results to props.onTimelineScrollIntent and conditionally marking gestures based on shouldMarkTimelineBoundaryGesture.
Session staging effect adjustments
packages/app/src/pages/session/session-timeline-staging.ts, packages/app/src/pages/session/session-timeline-staging.test.ts
Staging effect now calls cancel() before evaluating staging, and shouldStage includes guard state.activeSession !== sessionKey. Removes prior early-return path. Test case updated to verify completed-session backfill renders immediately without re-staging.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Astro-Han/pawwork#521: Earlier PR on session timeline gesture/scroll intent handling; this PR's new shared session-timeline-scroll-intents module directly extracts and generalizes similar boundary/intent classification logic.
  • Astro-Han/pawwork#630: Updates timeline scroll controller's handling of upward wheel/touch intents; both PRs affect the same wheel/touch gesture classification and intent generation flow.

🐰 A rabbit hops through the scroll, with intents so bright,
Boundaries and metrics dance in harmony's light,
Shared code now gleams, no duplication in sight,
Message-timeline freed from gesture work—clean and light! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main change: extracting timeline scroll intent helpers into a shared module.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The pull request description is comprehensive and follows the required template structure with all major sections completed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/timeline-scroll-intent-contract

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors scroll intent and metrics logic by extracting helper functions from the MessageTimeline component into a new dedicated module, session-timeline-scroll-intents.ts, and adds corresponding unit tests. The review feedback suggests widening the root parameter type from HTMLDivElement to HTMLElement for increased flexibility and recommends replacing hardcoded scroll thresholds with a configuration object to improve maintainability.

Comment thread packages/app/src/pages/session/session-timeline-scroll-intents.ts Outdated
Comment thread packages/app/src/pages/session/session-timeline-scroll-intents.ts
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 16, 2026

Perf delta summary

Comparator: pass

Profile / Scenario interaction median interaction worst long task max tbt frame gap p95 frame gap max jank count cls status
default / homepage-cold 24 -> 24 (0) 40 -> 40 (0) 62 -> 64 (+2) 12 -> 14 (+2) 16.8 -> 16.8 (0) 166.7 -> 166.6 (-0.1) 3 -> 3 (0) 0 -> 0 (0) pass
default / long-session-input-lag 48 -> 48 (0) 48 -> 48 (0) 0 -> 0 (0) 0 -> 0 (0) 16.7 -> 16.7 (0) 16.8 -> 16.8 (0) 0 -> 0 (0) 0 -> 0 (0) pass
default / session-streaming-long 48 -> 40 (-8) 64 -> 64 (0) 0 -> 0 (0) 0 -> 0 (0) 16.8 -> 16.8 (0) 33.4 -> 16.8 (-16.6) 0 -> 0 (0) 0 -> 0 (0) pass
default / tool-call-expand 16 -> 24 (+8) 16 -> 24 (+8) 0 -> 0 (0) 0 -> 0 (0) 16.7 -> 16.7 (0) 16.7 -> 16.7 (0) 0 -> 0 (0) 0 -> 0 (0) pass
default / tool-default-open-heavy-bash 24 -> 24 (0) 24 -> 24 (0) 66 -> 65 (-1) 16 -> 15 (-1) 50 -> 50 (0) 100 -> 116.6 (+16.6) 3 -> 2 (-1) 0 -> 0 (0) pass
default / terminal-side-panel-open 48 -> 48 (0) 56 -> 48 (-8) 0 -> 0 (0) 0 -> 0 (0) 33.4 -> 33.3 (-0.1) 49.9 -> 33.4 (-16.5) 0 -> 0 (0) 0 -> 0 (0) pass
default / session-scroll-reading 24 -> 24 (0) 24 -> 24 (0) 0 -> 0 (0) 0 -> 0 (0) 16.8 -> 16.8 (0) 16.8 -> 16.8 (0) 0 -> 0 (0) 0.505 -> 0.505 (0) warn: cls
low-end / session-scroll-reading-long 64 -> 64 (0) 80 -> 72 (-8) 72 -> 66 (-6) 34 -> 27 (-7) 16.8 -> 16.8 (0) 233.3 -> 199.9 (-33.4) 3 -> 2 (-1) 0.011 -> 0.011 (0) pass
low-end / session-timeline-recompute 136 -> 120 (-16) 152 -> 128 (-24) 125 -> 111 (-14) 281 -> 203 (-78) 116.6 -> 99.9 (-16.7) 200 -> 183.3 (-16.7) 4 -> 3 (-1) 0.081 -> 0.081 (0) pass
low-end / concurrent-shimmer-extreme 0 -> 0 (0) 0 -> 0 (0) 0 -> 0 (0) 0 -> 0 (0) 16.8 -> 16.8 (0) 16.8 -> 16.8 (0) 0 -> 0 (0) 0 -> 0 (0) pass

@Astro-Han Astro-Han force-pushed the codex/message-flow-staging-contract branch from 6e302c1 to 510653c Compare May 16, 2026 06:33
@Astro-Han Astro-Han force-pushed the codex/timeline-scroll-intent-contract branch from 1692f00 to 1b6320d Compare May 16, 2026 06:33
@Astro-Han Astro-Han force-pushed the codex/message-flow-staging-contract branch from 510653c to f690bf3 Compare May 16, 2026 09:38
@Astro-Han Astro-Han deleted the branch dev May 16, 2026 10:24
@Astro-Han Astro-Han closed this May 16, 2026
@Astro-Han Astro-Han reopened this May 16, 2026
@Astro-Han Astro-Han changed the base branch from codex/message-flow-staging-contract to dev May 16, 2026 10:32
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested priority: P2 (includes user-path files (packages/app/src/pages/session/message-timeline.tsx, packages/app/src/pages/session/session-timeline-scroll-intents.test.ts, packages/app/src/pages/session/session-timeline-scroll-intents.ts, packages/app/src/pages/session/session-timeline-staging.test.ts, packages/app/src/pages/session/session-timeline-staging.ts)).

P1/P0 are reserved for maintainer confirmation. Please relabel manually if this is a release blocker, security issue, data-loss risk, or updater/runtime failure.

@Astro-Han Astro-Han merged commit 6b83048 into dev May 16, 2026
28 checks passed
Astro-Han added a commit that referenced this pull request May 16, 2026
Goal: extract the per-message comment parsing and comment strip rendering from MessageTimeline into a focused session-message-comments helper without changing message-flow behavior.\n\nBoundary: scoped to packages/app/src/pages/session/message-timeline.tsx, session-message-comments.tsx, and focused comment/staging/scroll-intent tests. No scroll behavior, turn-change behavior, persistence, IPC, platform, dependency, or public export changes.\n\nRestack: rebased from codex/timeline-scroll-intent-contract onto latest dev after #671 was squash merged; verified the PR diff contains only this slice. Used --force-with-lease for codex/message-comment-strip-contract after confirming local HEAD matched origin before rebase and the worktree was clean.\n\nReview follow-up: Gemini bg token thread fixed and resolved by using bg-surface-base. Fresh-eyes/CI typography guard finding fixed by replacing old text-13 utilities with role typography. Final fresh-eyes review found no P0-P3 actionable findings. Review threads are resolved.\n\nVerification: bun test --preload ./happydom.ts src/pages/session/session-message-comments.test.ts src/pages/session/session-timeline-staging.test.ts src/pages/session/session-timeline-scroll-intents.test.ts -> 16 pass, 0 fail. bun test test/no-dead-tokens.test.ts from packages/ui -> 3 pass, 0 fail. bun run typecheck -> 8 successful. Targeted perf gate via bun script/e2e-local.ts -- e2e/perf/perf-probe.spec.ts --grep "long-session-input-lag|session-timeline-recompute" -> 1 passed, 1 skipped. git diff --check origin/dev...HEAD and git diff --check -> pass. GitHub required checks passed, including unit-ui-focused and perf-probe-baseline.\n\nResidual risk: low; Electron manual visual verification was not run for this behavior-preserving extraction.
@Astro-Han Astro-Han deleted the codex/timeline-scroll-intent-contract branch May 16, 2026 16:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app Application behavior and product flows P2 Medium priority task Maintainer or agent execution task tech-debt Internal cleanup and maintainability debt ui Design system and user interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant