From 268fa0e97e988383e56971d0437c963ac059dc58 Mon Sep 17 00:00:00 2001 From: Waleed Date: Mon, 18 May 2026 10:36:47 -0700 Subject: [PATCH] fix(knowledge): preserve scroll position when toggling tokenizer in chunk viewer (#4643) * fix(knowledge): preserve scroll position when toggling tokenizer in chunk viewer * fix(knowledge): skip scroll restore on initial mount of chunk editor * chore(dev): add dev:clean script to purge Turbopack cache --- .../components/chunk-editor/chunk-editor.tsx | 29 +++++++++++++++++-- apps/sim/package.json | 1 + 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/chunk-editor/chunk-editor.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/chunk-editor/chunk-editor.tsx index d0f241f1fd..0656d632bf 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/chunk-editor/chunk-editor.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/chunk-editor/chunk-editor.tsx @@ -1,6 +1,6 @@ 'use client' -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react' import { Label, Switch } from '@/components/emcn' import { isApiClientError } from '@/lib/api/client/errors' import { requestJson } from '@/lib/api/client/request' @@ -50,6 +50,8 @@ export function ChunkEditor({ onCreated, }: ChunkEditorProps) { const textareaRef = useRef(null) + const tokenizedScrollRef = useRef(null) + const preservedScrollTopRef = useRef(0) const { mutateAsync: updateChunk } = useUpdateChunk() const { mutateAsync: createChunk } = useCreateChunk() @@ -170,6 +172,24 @@ export function ChunkEditor({ [saveRef] ) + const hasToggledTokenizerRef = useRef(false) + + const handleTokenizerChange = useCallback( + (value: boolean) => { + const source = tokenizerOn ? tokenizedScrollRef.current : textareaRef.current + preservedScrollTopRef.current = source?.scrollTop ?? 0 + hasToggledTokenizerRef.current = true + setTokenizerOn(value) + }, + [tokenizerOn] + ) + + useLayoutEffect(() => { + if (!hasToggledTokenizerRef.current) return + const target = tokenizerOn ? tokenizedScrollRef.current : textareaRef.current + if (target) target.scrollTop = preservedScrollTopRef.current + }, [tokenizerOn]) + const tokenStrings = useMemo(() => { if (!tokenizerOn || !editedContent) return [] return getTokenStrings(editedContent) @@ -196,7 +216,10 @@ export function ChunkEditor({ }} > {tokenizerOn ? ( -
+
{tokenStrings.map((token, index) => ( diff --git a/apps/sim/package.json b/apps/sim/package.json index f175df18d5..dc6f615477 100644 --- a/apps/sim/package.json +++ b/apps/sim/package.json @@ -9,6 +9,7 @@ }, "scripts": { "dev": "next dev --port 3000", + "dev:clean": "rm -rf .next/dev/cache", "dev:webpack": "next dev --webpack", "load:workflow": "bun run load:workflow:baseline", "load:workflow:baseline": "BASE_URL=${BASE_URL:-http://localhost:3000} WARMUP_DURATION=${WARMUP_DURATION:-10} WARMUP_RATE=${WARMUP_RATE:-2} PEAK_RATE=${PEAK_RATE:-8} HOLD_DURATION=${HOLD_DURATION:-20} bunx artillery run scripts/load/workflow-concurrency.yml",