From b17f77463f1ec0198d33c83beae36fc31b812f6f Mon Sep 17 00:00:00 2001 From: James Clarke Date: Tue, 7 Jan 2025 21:41:29 +0000 Subject: [PATCH] Give items in repl history stable indexes to fix race when updating item heights (#397) --- shared/studio/tabs/repl/index.tsx | 23 ++++++++---- shared/studio/tabs/repl/state/itemHeights.ts | 37 ++++++++++---------- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/shared/studio/tabs/repl/index.tsx b/shared/studio/tabs/repl/index.tsx index 05b2f1d7..6b39a2db 100644 --- a/shared/studio/tabs/repl/index.tsx +++ b/shared/studio/tabs/repl/index.tsx @@ -171,16 +171,22 @@ const ReplList = observer(function ReplList({ setRenderHeader(scrollTop < headerHeight + 100); + const historyCount = replState.itemHeights.historyCount; + const startIndex = Math.max( 0, replState.itemHeights.getIndexAtHeight( Math.max(0, scrollTop - headerHeight) - ) - 2 + ) + + historyCount - + 2 ); const endIndex = Math.min( replState.itemHeights.getIndexAtHeight( Math.max(0, scrollTop - headerHeight + ref.current!.clientHeight) - ) + 2, + ) + + historyCount + + 2, replState.queryHistory.length - 1 ); @@ -191,7 +197,9 @@ const ReplList = observer(function ReplList({ startIndex, endIndex, old[0] !== startIndex - ? replState.itemHeights.getHeightAtIndex(startIndex) + ? replState.itemHeights.getHeightAtIndex( + startIndex - historyCount + ) : old[2], ] ); @@ -217,6 +225,7 @@ const ReplList = observer(function ReplList({ const items: JSX.Element[] = []; if (replState.queryHistory.length) { + const historyCount = replState.itemHeights.historyCount; let top = visibleBounds[2] + headerHeight; for (let i = visibleBounds[0]; i <= visibleBounds[1]; i++) { const item = replState.queryHistory[i]; @@ -224,7 +233,7 @@ const ReplList = observer(function ReplList({ this._totalHeight.set( @@ -30,11 +34,15 @@ export class ItemHeights { this._updateTotalHeight(); } + // to ensure stable item indexes: + // positive indexes are current items starting at 0 + // negative indexes are history items starting at -1 + updateItemHeight(index: number, height: number) { - if (index < this._history._length) { - this._history.updateHeight(this._history._length - index - 1, height); + if (index < 0) { + this._history.updateHeight(-1 - index, height); } else { - this._current.updateHeight(index - this._history._length, height); + this._current.updateHeight(index, height); } this._updateTotalHeight(); } @@ -42,29 +50,22 @@ export class ItemHeights { getIndexAtHeight(height: number) { if (height < this._history._root.total) { return ( - this._history._length - - this._history.getIndexAtHeight(this._history._root.total - height) - - 1 + -this._history.getIndexAtHeight(this._history._root.total - height) - 1 ); } else { - return ( - this._current.getIndexAtHeight(height - this._history._root.total) + - this._history._length + return this._current.getIndexAtHeight( + height - this._history._root.total ); } } getHeightAtIndex(index: number) { - if (index < this._history._length) { - return index - ? this._history._root.total - - this._history.getHeightAtIndex(this._history._length - index) - : 0; + if (index < 0) { + return -index >= this._history._length + ? 0 + : this._history._root.total - this._history.getHeightAtIndex(-index); } else { - return ( - this._history._root.total + - this._current.getHeightAtIndex(index - this._history._length) - ); + return this._history._root.total + this._current.getHeightAtIndex(index); } } }