Skip to content

Fix focus change re-renders - #15624

Open
samhh wants to merge 2 commits into
masterfrom
sah-branch-51
Open

Fix focus change re-renders#15624
samhh wants to merge 2 commits into
masterfrom
sah-branch-51

Conversation

@samhh

@samhh samhh commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Currently blocked from merging by this: #15612 (comment)

If someone with elevated permissions would like to merge please go ahead. 🙂

samhh added 2 commits August 28, 2026 13:19
Today I discovered that iterators are lazy, produce no intermediate allocations, and their creation is O(1) with only minor iteration overhead. They are similar to stream fusion in Haskell. This makes them a generally more performant, more readable - albeit more verbose - alternative to where I've abused flatMap as a filterMap.

This commit is me playing with them. It's a minor improvement we may as well keep.
The previous implementation triggered a re-render of the PageBody component that consumes the calling hook. In certain very large repos this would cause the UI to lock up on every focus change.

Whilst this performance problem was severely compounded by other performance issues to be addressed in due course, this is still a worthy fix.
@samhh
samhh marked this pull request as ready for review August 28, 2026 15:33
Copilot AI lite review requested due to automatic review settings August 28, 2026 15:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR aims to reduce unnecessary re-renders in the Lite workspace UI (notably those triggered by focus changes) by removing focus-driven subscriptions and by replacing several array-building patterns with iterator-based pipelines to reduce intermediate allocations and identity churn.

Changes:

  • Remove the useActiveElement focus subscription and compute focused scope at the time a hotkey is invoked.
  • Replace many flatMap/array-materialization patterns with iterator pipelines (values(), map, filter, toArray) and add small iterator utilities (reverseValues, iteratorConcat).
  • Export a couple of previously-internal types (CheckableAddress, CheckedConflict) to support new typing needs across workspace components.

Reviewed changes

Copilot reviewed 29 out of 29 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
apps/lite/ui/src/routes/project/$id/workspace/WorkspaceLists/WorkspaceLists.tsx Switch stack/changes/address derivations to iterator pipelines; reverse stack traversal without cloning.
apps/lite/ui/src/routes/project/$id/workspace/WorkspaceLists/useStackMenuItems.ts Build foldable ref list via iterators to avoid intermediate arrays.
apps/lite/ui/src/routes/project/$id/workspace/WorkspaceLists/commitTargetComboboxItems.ts Build commit-target combobox items using reversed iteration + iterator filtering.
apps/lite/ui/src/routes/project/$id/workspace/useUpstreamList.ts Refactor stack-branch extraction into iterator pipeline; adjust call site for optional headInfo.
apps/lite/ui/src/routes/project/$id/workspace/useCheckedActions.ts Derive selected hunks via iterator map/filter instead of flatMap.
apps/lite/ui/src/routes/project/$id/workspace/Sidebar.tsx Compute rebase updates inside the action and build them via iterators.
apps/lite/ui/src/routes/project/$id/workspace/Page.tsx Remove focus subscription hook usage; compute focus scope on-demand in hotkey callback.
apps/lite/ui/src/routes/project/$id/workspace/FilesTree.tsx Convert set-building and checked-path extraction to iterator pipelines.
apps/lite/ui/src/routes/project/$id/workspace/file-row.ts Return file-row items as an iterator (via iteratorConcat) and materialize only where needed.
apps/lite/ui/src/routes/project/$id/workspace/diff-minimap.ts Replace flatMap with iterator map/filter/toArray for selection endpoints.
apps/lite/ui/src/routes/project/$id/workspace/diff-line-target.ts Replace flatMap with iterator helpers to locate the first line-number attribute.
apps/lite/ui/src/routes/project/$id/workspace/Details.tsx Refactor multiple “derive collections” spots to iterator pipelines and tighten some types.
apps/lite/ui/src/routes/project/$id/workspace/DependencyIndicator.tsx Build dependency tooltip set via iterator map/filter.
apps/lite/ui/src/routes/project/$id/workspace/ConflictBar.tsx Build checked conflict mapping via iterator pipeline; add exported type dependency.
apps/lite/ui/src/routes/project/$id/workspace/CommitForm.tsx Build commit change specs via iterator filtering instead of flatMap.
apps/lite/ui/src/routes/project/$id/workspace/CommandPalette.tsx Accept iterables for grouping and use iteratorConcat to combine filtered items.
apps/lite/ui/src/routes/project/$id/workspace/BranchPicker.tsx Produce branch picker options via iterator pipeline and materialize once.
apps/lite/ui/src/routes/project/$id/workspace/ApplyBranchPicker.tsx Refactor option derivation/grouping to iterator pipelines (includes one runtime-compat concern).
apps/lite/ui/src/routes/project/$id/workspace/applied-address-space.ts Use reverseValues to walk stacks in reverse without toReversed() cloning.
apps/lite/ui/src/routes/project/$id/workspace/AnnotationCard.tsx Replace flatMap-based filtering with a type-narrowing filter.
apps/lite/ui/src/router.ts Refactor query-string building to iterator filter/map/toArray pipeline.
apps/lite/ui/src/reconcile.ts Refactor multiple checked-item derivations and query combine logic to iterators.
apps/lite/ui/src/projects/project.ts Export CheckableAddress and CheckedConflict types for cross-module use.
apps/lite/ui/src/project-events.ts Refactor integrated-review refresh collection building to iterator pipeline.
apps/lite/ui/src/native-menu.ts Remove @public doc comments from exported menu helpers.
apps/lite/ui/src/iterator.ts Add iterator utilities: iteratorConcat and reverseValues.
apps/lite/ui/src/hunk.ts Refactor selection positioning derivation to iterator map/filter/toArray.
apps/lite/ui/src/focus.ts Remove useActiveElement hook (and its focus event subscription).
apps/lite/ui/src/checking.ts Refactor range construction to iterator drop/take pipeline feeding Set.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread apps/lite/ui/src/routes/project/$id/workspace/ApplyBranchPicker.tsx
@samhh
samhh enabled auto-merge August 28, 2026 15:48
@krlvi krlvi added the bounded fix Autonomous fix with bounded scope and explicit validation label Aug 29, 2026
@krlvi

krlvi commented Aug 29, 2026

Copy link
Copy Markdown
Member

@samhh sorry for the blockage. It is not fixed in the latest version of the app - so if you just rebase or edit something here, the committer will be fixed

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

Labels

bounded fix Autonomous fix with bounded scope and explicit validation @gitbutler/lite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants