MCPcopy Index your code
hub / github.com/codeaashu/claude-code / tick

Function tick

src/components/ScrollKeybindingHandler.tsx:657–714  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

655 }
656 }
657 function tick(): void {
658 const sel = selection.getState();
659 const s = scrollRef.current;
660 const dir = dirRef.current;
661 // dir === 0 defends against a stale interval (start() may have set one
662 // after the immediate tick already called stop() at a scroll boundary).
663 // ticks cap defends against a lost release event (mouse released
664 // outside terminal window) leaving isDragging stuck true.
665 if (!sel?.isDragging || !sel.focus || !s || dir === 0 || ++ticksRef.current > AUTOSCROLL_MAX_TICKS) {
666 stop();
667 return;
668 }
669 // scrollBy accumulates into pendingScrollDelta; the screen buffer
670 // doesn't update until the next render drains it. If a previous
671 // tick's scroll hasn't drained yet, captureScrolledRows would read
672 // stale content (same rows as last tick → duplicated in the
673 // accumulator AND missing the rows that actually scrolled out).
674 // Skip this tick; the 50ms interval will retry after Ink's 16ms
675 // render catches up. Also prevents shiftAnchor from desyncing.
676 if (s.getPendingDelta() !== 0) return;
677 const top = s.getViewportTop();
678 const bottom = top + s.getViewportHeight() - 1;
679 // Clamp anchor within [top, bottom]. Not [0, bottom]: the ScrollBox
680 // padding row at 0 would produce a blank line between scrolledOffAbove
681 // and the on-screen content in getSelectedText. The padding-row
682 // highlight was a minor visual nicety; text correctness wins.
683 if (dir < 0) {
684 if (s.getScrollTop() <= 0) {
685 stop();
686 return;
687 }
688 // Scrolling up: content moves down in viewport, so anchor row +N.
689 // Clamp to actual scroll distance so anchor stays in sync when near
690 // the top boundary (renderer clamps scrollTop to 0 on drain).
691 const actual = Math.min(AUTOSCROLL_LINES, s.getScrollTop());
692 // Capture rows about to scroll out the BOTTOM before scrollBy
693 // overwrites them. Only rows inside the selection are captured
694 // (captureScrolledRows intersects with selection bounds).
695 selection.captureScrolledRows(bottom - actual + 1, bottom, 'below');
696 selection.shiftAnchor(actual, 0, bottom);
697 s.scrollBy(-AUTOSCROLL_LINES);
698 } else {
699 const max = Math.max(0, s.getScrollHeight() - s.getViewportHeight());
700 if (s.getScrollTop() >= max) {
701 stop();
702 return;
703 }
704 // Scrolling down: content moves up in viewport, so anchor row -N.
705 // Clamp to actual scroll distance so anchor stays in sync when near
706 // the bottom boundary (renderer clamps scrollTop to max on drain).
707 const actual_0 = Math.min(AUTOSCROLL_LINES, max - s.getScrollTop());
708 // Capture rows about to scroll out the TOP.
709 selection.captureScrolledRows(top, top + actual_0 - 1, 'above');
710 selection.shiftAnchor(-actual_0, top, bottom);
711 s.scrollBy(AUTOSCROLL_LINES);
712 }
713 onScrollRef.current?.(false, s);
714 }

Callers 1

startFunction · 0.70

Calls 3

captureScrolledRowsMethod · 0.80
maxMethod · 0.80
stopFunction · 0.70

Tested by

no test coverage detected