mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
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
This commit is contained in:
+26
-3
@@ -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<HTMLTextAreaElement>(null)
|
||||
const tokenizedScrollRef = useRef<HTMLDivElement>(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 ? (
|
||||
<div className='h-full w-full cursor-default overflow-y-auto whitespace-pre-wrap break-words p-6 font-sans text-[var(--text-body)] text-sm'>
|
||||
<div
|
||||
ref={tokenizedScrollRef}
|
||||
className='h-full w-full cursor-default overflow-y-auto whitespace-pre-wrap break-words p-6 font-sans text-[var(--text-body)] text-sm'
|
||||
>
|
||||
{tokenStrings.map((token, index) => (
|
||||
<span
|
||||
key={index}
|
||||
@@ -232,7 +255,7 @@ export function ChunkEditor({
|
||||
<div className='flex items-center justify-between border-[var(--border)] border-t px-6 py-2.5'>
|
||||
<TokenizerToggle
|
||||
checked={tokenizerOn}
|
||||
onCheckedChange={setTokenizerOn}
|
||||
onCheckedChange={handleTokenizerChange}
|
||||
hoveredTokenIndex={tokenizerOn ? hoveredTokenIndex : null}
|
||||
/>
|
||||
<span className='text-[var(--text-secondary)] text-caption'>
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user