Stop re-rendering unchanged board views on every move - #72
Conversation
selectionsnapshot and toprowsnapshot are value projections of the observable session, captured once per body pass so board views can render from equatable slices instead of subscribing to the whole state. the pure canselecttableaucards mirrors the session rule for suffix runs — canfield's whole-pile transfer check reduces to a count comparison there — and parity tests pin the two together for every suffix of every pile across seeded deals of all ten variants.
tableaupileview and tableaurowview take the pile arrays, variant, and selection snapshot by value and prune through manual equatable — the session reference stays for tap wiring only and participates in == by identity. the interaction value types become nonisolated so the nonisolated == can compare drop targets. equatable regression tests assert pruning survives fresh gesture closures and breaks on every rendered input.
stock, waste, tableau stock, foundation, free cell, discard, the pyramid and tripeaks boards, canfield's reserve and board row, the top-row dispatcher, and all ten per-variant top rows now render from toprowsnapshot and selectionsnapshot slices, so a move that leaves a view's slice unchanged skips its body entirely. wasteview captures its top card's tilt at init and compares it in == because the invalid-drop return rerolls that tilt without touching the pile's contents. the per-variant rows carry no equatable of their own — the dispatcher's == gates the whole row.
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5d66450e2d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
codex review of #72 reasonably worried that toprowview's pruning could swallow the waste-return tilt reroll before wasteview's topcardtilt check runs. it cannot: cardview reads the tilt binding in its own body, and binding reads register direct per-reader dependencies that survive ancestor pruning — verified on the exact repro. record that contract where the next reader will look for it.
|
@codex review |
|
Codex Review: Didn't find any major issues. 👍 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
What Changed
BoardSnapshots.swift:SelectionSnapshotandTopRowSnapshot— value projections of the observable session, captured once perContentViewbody pass — plusFoundationPlaceholderfor the empty-foundation art.Equatablethat covers every rendered input. The session reference stays for tap/drag wiring only and participates in==by identity.GameRules.canSelectTableauCards(_:within:variant:)so pile rendering never calls the session's rule; Canfield's whole-pile transfer check reduces exactly to a count comparison for suffix runs.WasteViewcaptures its top card's tilt at init and compares it in==— the invalid-drop return rerolls that tilt without touching pile contents, and a pruned waste would otherwise visibly re-tilt on reveal.DropTargetet al.) markednonisolatedso the nonisolated==implementations can compare them.Why
Follow-up to #70/#71 and the last planned piece of the lag work: the session is
@Observablewith one coarsestateproperty, so every board view that readviewModel.state.*re-evaluated on every move — a TriPeaks draw re-ran all 28 peak slots, a Klondike move re-ran every pile and foundation. OnlyCardViewpruned. With value slices and per-viewEquatable, a move now re-evaluates only the views whose rendered data actually changed.Validation
@Bindable/session reads remain underViews/exceptDragOverlayView(renders the live drag by design) and theStatisticsViewsheet.