feat: custom virtual slots nav list#368
Open
asuzuki-jumptrading wants to merge 2 commits into
Open
Conversation
asuzuki-jumptrading
commented
Jun 26, 2026
Collaborator
- Create a custom virtual slots list to improve nav performance
- Note: list height changes every time current slot increments. If looking at past slots only, we don't want a visual shift so we adjust the scrollTop manually to see the same items
Collaborator
Author
|
@greptile-jt review |
Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/features/Navigation/allSlotsUtils.ts
Line: 53
Comment:
**Falsy check treats slot 0 as undefined**
`!slot` is `true` for both `undefined` and `0`. If `getSlotAtIndex` returns slot `0` (possible in the first epoch), this would incorrectly return `undefined` instead of computing the real offset. This is inconsistent with the `slot == null` check used in `getIndexHeight` on line 72 of this same file, and in `mySlotsUtils.ts:65`.
```suggestion
if (slot == null) return;
```
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: src/features/Navigation/allSlotsUtils.ts
Line: 177-178
Comment:
**Next-leader count is wrong for sub-ranges**
`yourNextFutureCount = yourFutureCount > 0 ? 1 : 0` assumes that whenever there are future "your" slots in the range, one of them is the next leader slot. But `getSlotTopOffset` calls `getTypeCounts` with a sub-range `[slotAbove, lastLeaderSlot]` that excludes the next leader slot when computing offsets for items at or above the next leader. In that case, none of the future "your" slots in the range is the next leader, yet the code still counts one as such.
This introduces a constant 5px offset error (`YOUR_NEXT_LEADER_HEIGHT - YOUR_NON_NEXT_FUTURE_HEIGHT = 33 - 28`) for every slot positioned at or above the next leader slot. The same pattern exists in `mySlotsUtils.ts:164-165`.
The fix would be to pass `nextLeaderSlot` into `getTypeCounts` and check whether it's actually within the range before counting it.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: src/features/Navigation/allSlotsUtils.ts
Line: 133-153
Comment:
**Unused exported function**
`getTopOffsetAtIndex` is exported but never imported anywhere in the codebase. If it's not needed, consider removing it to avoid dead code.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: src/features/Navigation/VirtualSlotsList.tsx
Line: 305-309
Comment:
**Missing throttle cancel on cleanup**
The cleanup removes event listeners but doesn't call `updateSlotOverride.cancel()`. With `{ trailing: true }`, a pending trailing invocation could fire after the effect cleans up, causing a stale `setSlotOverride` call.
```suggestion
return () => {
container.removeEventListener("wheel", updateSlotOverride);
container.removeEventListener("touchmove", updateSlotOverride);
updateSlotOverride.cancel();
};
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "feat: custom virtual slots nav list" | Re-trigger Greptile |
37758aa to
2ff6aa6
Compare
Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/features/Navigation/allSlotsUtils.ts
Line: 59-61
Comment:
**Linear scan on every call to `getSlotHeight`**
`leaderSlots.includes(slot)` is O(n) per call. This function is invoked from the `MItems` render loop (via `getTopOffset`) for each visible + overscan item (~60 items), making the per-render cost O(`leaderSlots.length` × 60). For typical validator schedules (~500–1000 leader slots) this is likely fast enough, but converting `leaderSlots` to a `Set` once in `getAllSlotsOffsetHelpers` would make each lookup O(1) and future-proof against larger schedules.
```suggestion
const getSlotHeight = (anySlot: number) => {
const slot = getSlotGroupLeader(anySlot);
const isYours = leaderSlotsSet.has(slot);
```
(with `const leaderSlotsSet = new Set(leaderSlots);` added at the top of `getAllSlotsOffsetHelpers`)
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: src/features/Navigation/VirtualSlotsList.tsx
Line: 375-377
Comment:
**`cancelAnimationFrame(prevRafId)` is always a no-op**
`requestAnimationFrame` callbacks fire in order. By the time the new rAF callback executes (line 376), the previous rAF (`prevRafId`) has already executed — so `cancelAnimationFrame(prevRafId)` on line 377 cancels a frame that already ran. The actual cancellation logic that matters is in the cleanup function (lines 380-384), which correctly cancels the *current* pending frame on unmount/re-render.
This `if (prevRafId !== null) cancelAnimationFrame(prevRafId);` line can be safely removed to avoid confusion.
How can I resolve this? If you propose a fix, please make it concise.Reviews (2): Last reviewed commit: "feat: custom virtual slots nav list" | Re-trigger Greptile |
2ff6aa6 to
28e0e37
Compare
|
Reviews (3): Last reviewed commit: "feat: custom virtual slots nav list" | Re-trigger Greptile |
28e0e37 to
c166093
Compare
Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/features/Navigation/mySlotsUtils.ts
Line: 178-189
Comment:
**Current leader missed when on last slot**
When the user is leading on their last leader slot in the epoch, `nextLeaderSlotIndex` is `undefined` (no more future leader slots). In that case, this function returns `false` on line 184 even though `isCurrentlyLeader` is `true`. This causes `getTypeCountsForLeaderIndices` to count the current leader as "past" (`YOUR_PAST_HEIGHT = 44`) instead of "current" (`YOUR_CURRENT_HEIGHT = 57`), producing a 13px error in `totalHeight` and all `getIndexTopOffset` values below the current leader.
Concretely: if `mySlots = [4, 12, 20, 40, 44, 48]` and `currentSlot = 48`, then `nextLeaderSlotIndex = undefined`. The total height is computed as `6 × 44 = 264` instead of `5 × 44 + 1 × 57 = 277`. This clips the bottom of the scroll area and shifts items when scrolled past the current slot.
The `allSlotsUtils.ts` equivalent (`getTypeCounts`) does not have this problem because it checks `slot === currentLeaderSlot` directly rather than relying on `nextLeaderSlotIndex`.
```suggestion
function isCurrentLeaderAndInRange(
startIdx: number,
endIdx: number,
nextLeaderSlotIndex: number | undefined,
isCurrentlyLeader: boolean,
totalSlotsCount: number,
) {
if (!isCurrentlyLeader) return false;
const currentIndex =
nextLeaderSlotIndex != null ? nextLeaderSlotIndex - 1 : totalSlotsCount - 1;
if (currentIndex < 0) return false;
return currentIndex >= startIdx && currentIndex <= endIdx;
}
```
You'll also need to pass `mySlots.length` to callers of this function.
How can I resolve this? If you propose a fix, please make it concise.Reviews (4): Last reviewed commit: "chore: add leader slots set" | Re-trigger Greptile |
92a379e to
273dc53
Compare
c166093 to
ea071e9
Compare
|
Reviews (5): Last reviewed commit: "chore: add leader slots set" | Re-trigger Greptile |
ea071e9 to
f64db94
Compare
|
Reviews (6): Last reviewed commit: "chore: add leader slots set" | Re-trigger Greptile |
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.