MCPcopy
hub / github.com/codeaashu/claude-code / StickyTracker

Function StickyTracker

src/components/VirtualMessageList.tsx:892–1081  ·  view source on GitHub ↗

* Effect-only child that tracks the last user-prompt scrolled above the * viewport top and fires onChange when it changes. * * Rendered as a separate component (not a hook in VirtualMessageList) so it * can subscribe to scroll at FINER granularity than SCROLL_QUANTUM=40. The * list needs the co

({
  messages,
  start,
  end,
  offsets,
  getItemTop,
  getItemElement,
  scrollRef
}: {
  messages: RenderableMessage[];
  start: number;
  end: number;
  offsets: ArrayLike<number>;
  getItemTop: (index: number) => number;
  getItemElement: (index: number) => DOMElement | null;
  scrollRef: RefObject<ScrollBoxHandle | null>;
})

Source from the content-addressed store, hash-verified

890 * from the mount-range end; break when an item's top is above target.
891 */
892function StickyTracker({
893 messages,
894 start,
895 end,
896 offsets,
897 getItemTop,
898 getItemElement,
899 scrollRef
900}: {
901 messages: RenderableMessage[];
902 start: number;
903 end: number;
904 offsets: ArrayLike<number>;
905 getItemTop: (index: number) => number;
906 getItemElement: (index: number) => DOMElement | null;
907 scrollRef: RefObject<ScrollBoxHandle | null>;
908}): null {
909 const {
910 setStickyPrompt
911 } = useContext(ScrollChromeContext);
912 // Fine-grained subscription — snapshot is unquantized scrollTop+delta so
913 // every scroll action (wheel tick, PgUp, drag) triggers a re-render of
914 // THIS component only. Sticky bit folded into the sign so sticky→broken
915 // also triggers (scrollToBottom sets sticky without moving scrollTop).
916 const subscribe = useCallback((listener: () => void) => scrollRef.current?.subscribe(listener) ?? NOOP_UNSUB, [scrollRef]);
917 useSyncExternalStore(subscribe, () => {
918 const s = scrollRef.current;
919 if (!s) return NaN;
920 const t = s.getScrollTop() + s.getPendingDelta();
921 return s.isSticky() ? -1 - t : t;
922 });
923
924 // Read live scroll state on every render.
925 const isSticky = scrollRef.current?.isSticky() ?? true;
926 const target = Math.max(0, (scrollRef.current?.getScrollTop() ?? 0) + (scrollRef.current?.getPendingDelta() ?? 0));
927
928 // Walk the mounted range to find the first item at-or-below the viewport
929 // top. `range` is from the parent's coarse-quantum render (may be slightly
930 // stale) but overscan guarantees it spans well past the viewport in both
931 // directions. Items without a Yoga layout yet (newly mounted this frame)
932 // are treated as at-or-below — they're somewhere in view, and assuming
933 // otherwise would show a sticky for a prompt that's actually on screen.
934 let firstVisible = start;
935 let firstVisibleTop = -1;
936 for (let i = end - 1; i >= start; i--) {
937 const top = getItemTop(i);
938 if (top >= 0) {
939 if (top < target) break;
940 firstVisibleTop = top;
941 }
942 firstVisible = i;
943 }
944 let idx = -1;
945 let text: string | null = null;
946 if (firstVisible > 0 && !isSticky) {
947 for (let i = firstVisible - 1; i >= 0; i--) {
948 const t = stickyPromptText(messages[i]!);
949 if (t === null) continue;

Callers

nothing calls this directly

Calls 4

stickyPromptTextFunction · 0.85
maxMethod · 0.80
trimStartMethod · 0.80
searchMethod · 0.65

Tested by

no test coverage detected