From 3f392a2784ddfd889194d439eec9c165065261c8 Mon Sep 17 00:00:00 2001 From: "@navedmerchant" <14171946+navedmerchant@users.noreply.github.com> Date: Tue, 1 Sep 2026 18:05:47 +0000 Subject: [PATCH 1/3] feat(chat): jump to previous user messages --- webview-ui/playwright/gallery/stories.tsx | 17 ++++ webview-ui/src/components/chat/ChatView.tsx | 87 +++++++++++++++---- .../chat/PreviousUserMessageButton.tsx | 18 ++++ .../ChatView.scroll-debug-repro.spec.tsx | 80 +++++++++++++++++ .../PreviousUserMessageButton.visual.tsx | 25 ++++++ webview-ui/src/i18n/locales/en/chat.json | 1 + 6 files changed, 212 insertions(+), 16 deletions(-) create mode 100644 webview-ui/src/components/chat/PreviousUserMessageButton.tsx create mode 100644 webview-ui/src/components/chat/__tests__/PreviousUserMessageButton.visual.tsx diff --git a/webview-ui/playwright/gallery/stories.tsx b/webview-ui/playwright/gallery/stories.tsx index 1aa4f034df..08b4824f26 100644 --- a/webview-ui/playwright/gallery/stories.tsx +++ b/webview-ui/playwright/gallery/stories.tsx @@ -83,6 +83,23 @@ export const stories: Record = { await import("@/components/settings/providers/__tests__/OpenAICompatible.visual.fixture") return }, + "previous-user-message-button": async () => { + const [{ PreviousUserMessageButton }, { TooltipProvider }] = await Promise.all([ + import("@/components/chat/PreviousUserMessageButton"), + import("@/components/ui/tooltip"), + ]) + return ( + +
+ undefined} + /> +
+
+ ) + }, "rendered-content-contrast": async () => { const [{ AppProviders }, { RenderedContentContrastFixture }] = await Promise.all([ import("../AppProviders"), diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 988c98ba30..d79a8e8f8d 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -52,6 +52,7 @@ import { CheckpointWarning } from "./CheckpointWarning" import { QueuedMessages } from "./QueuedMessages" import { WorktreeSelector } from "./WorktreeSelector" import FileChangesPanel from "./FileChangesPanel" +import { PreviousUserMessageButton } from "./PreviousUserMessageButton" import { useScrollLifecycle } from "@src/hooks/useScrollLifecycle" export interface ChatViewProps { @@ -1334,14 +1335,30 @@ const ChatViewComponent: React.ForwardRefRenderFunction { + const indices: number[] = [] + for (let i = 0; i < groupedMessages.length; i++) { + const message = groupedMessages[i] + if (message?.type === "say" && message.say === "user_feedback") { + indices.push(i) + } + } + return indices + }, [groupedMessages]) const hasLatestCheckpoint = checkpointIndices.length > 0 + const hasUserMessages = userMessageIndices.length > 0 const checkpointJumpCursorRef = useRef(null) + const userMessageJumpCursorRef = useRef(null) useEffect(() => { checkpointJumpCursorRef.current = null }, [task?.ts, checkpointIndices.length]) + useEffect(() => { + userMessageJumpCursorRef.current = null + }, [task?.ts, userMessageIndices.length]) + // Scroll lifecycle is managed by a dedicated hook to keep ChatView focused // on message handling and UI orchestration. const { @@ -1480,11 +1497,29 @@ const ChatViewComponent: React.ForwardRefRenderFunction { + const handleScrollToBottomAndResetNavigationCursors = useCallback(() => { checkpointJumpCursorRef.current = null + userMessageJumpCursorRef.current = null handleScrollToBottomClick() }, [handleScrollToBottomClick]) + const handleScrollToPreviousUserMessage = useCallback(() => { + if (userMessageIndices.length === 0 || userMessageJumpCursorRef.current === 0) { + return + } + + const previousCursor = userMessageJumpCursorRef.current + const nextCursor = previousCursor === null ? userMessageIndices.length - 1 : previousCursor - 1 + userMessageJumpCursorRef.current = nextCursor + + enterUserBrowsingHistory("keyboard-nav-up") + virtuosoRef.current?.scrollToIndex({ + index: userMessageIndices[nextCursor], + align: "center", + behavior: "smooth", + }) + }, [enterUserBrowsingHistory, userMessageIndices]) + const handleScrollToLatestCheckpoint = useCallback(() => { if (checkpointIndices.length === 0) { return @@ -1642,7 +1677,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction - {showScrollToBottom && !hasApprovalButtons ? ( - <> - - - + {!hasApprovalButtons ? ( +
+ {hasUserMessages && ( + + )} + {showScrollToBottom && ( + + + + )} {hasLatestCheckpoint && ( )} - +
) : ( <> + {hasUserMessages && ( + + )} {showScrollToBottom && ( diff --git a/webview-ui/src/components/chat/PreviousUserMessageButton.tsx b/webview-ui/src/components/chat/PreviousUserMessageButton.tsx new file mode 100644 index 0000000000..1ffa2e5072 --- /dev/null +++ b/webview-ui/src/components/chat/PreviousUserMessageButton.tsx @@ -0,0 +1,18 @@ +import { Button, StandardTooltip } from "@src/components/ui" + +interface PreviousUserMessageButtonProps { + title: string + className?: string + onClick: () => void +} + +export const PreviousUserMessageButton = ({ title, className, onClick }: PreviousUserMessageButtonProps) => ( + + + +) diff --git a/webview-ui/src/components/chat/__tests__/ChatView.scroll-debug-repro.spec.tsx b/webview-ui/src/components/chat/__tests__/ChatView.scroll-debug-repro.spec.tsx index 56b008b862..9073277175 100644 --- a/webview-ui/src/components/chat/__tests__/ChatView.scroll-debug-repro.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/ChatView.scroll-debug-repro.spec.tsx @@ -232,6 +232,15 @@ const buildMessagesWithMultipleCheckpoints = (baseTs: number): ClineMessage[] => { type: "say", say: "text", ts: baseTs + 6, text: "row-6" }, ] +const buildMessagesWithUserFeedback = (baseTs: number): ClineMessage[] => [ + { type: "say", say: "text", ts: baseTs, text: "task" }, + { type: "say", say: "text", ts: baseTs + 1, text: "row-1" }, + { type: "say", say: "user_feedback", ts: baseTs + 2, text: "feedback-1" }, + { type: "say", say: "text", ts: baseTs + 3, text: "row-3" }, + { type: "say", say: "user_feedback", ts: baseTs + 4, text: "feedback-2" }, + { type: "say", say: "text", ts: baseTs + 5, text: "row-5" }, +] + const resolveFollowOutput = (isAtBottom: boolean): "auto" | false => { const followOutput = harness.followOutput if (typeof followOutput === "function") { @@ -361,6 +370,15 @@ const getScrollToCheckpointButton = (): HTMLButtonElement => { return button } +const getPreviousUserMessageButton = (): HTMLButtonElement => { + const button = document.querySelector("button[aria-label='chat:jumpToPreviousUserMessage']") + if (!(button instanceof HTMLButtonElement)) { + throw new Error("Expected jump-to-previous-user-message button") + } + + return button +} + const getButtonByText = (text: string): HTMLButtonElement => { const button = Array.from(document.querySelectorAll("button")).find((candidate) => candidate.textContent === text) if (!(button instanceof HTMLButtonElement)) { @@ -631,6 +649,68 @@ describe("ChatView scroll behavior regression coverage", () => { await expectChevronHidden() }) + it("only shows previous-user-message navigation when follow-up messages exist", async () => { + await hydrate(2) + await waitForCalls(2) + await waitForCallsSettled() + + expect(document.querySelector("button[aria-label='chat:jumpToPreviousUserMessage']")).toBeNull() + + await act(async () => { + postState(buildMessagesWithUserFeedback(Date.now() - 3_000)) + }) + await flushEffects() + + expect(getPreviousUserMessageButton()).toBeVisible() + }) + + it("steps backward through user messages and stops at the oldest", async () => { + await hydrate(2, buildMessagesWithUserFeedback(Date.now() - 3_000)) + await waitForCalls(2) + await waitForCallsSettled() + + const button = getPreviousUserMessageButton() + const callsBeforeClick = harness.scrollCalls + + await act(async () => { + button.click() + }) + expect(harness.scrollToIndexArgs.at(-1)).toMatchObject({ index: 3, align: "center", behavior: "smooth" }) + + await act(async () => { + button.click() + }) + expect(harness.scrollToIndexArgs.at(-1)).toMatchObject({ index: 1, align: "center", behavior: "smooth" }) + + await act(async () => { + button.click() + }) + expect(harness.scrollCalls).toBe(callsBeforeClick + 2) + }) + + it("resets previous-user-message navigation when a new user message arrives", async () => { + const baseTs = Date.now() - 3_000 + const initialMessages = buildMessagesWithUserFeedback(baseTs) + await hydrate(2, initialMessages) + await waitForCalls(2) + await waitForCallsSettled() + + await act(async () => { + getPreviousUserMessageButton().click() + getPreviousUserMessageButton().click() + }) + + await act(async () => { + postState([...initialMessages, { type: "say", say: "user_feedback", ts: baseTs + 6, text: "feedback-3" }]) + }) + await flushEffects() + + await act(async () => { + getPreviousUserMessageButton().click() + }) + expect(harness.scrollToIndexArgs.at(-1)).toMatchObject({ index: 5, align: "center", behavior: "smooth" }) + }) + it("shows jump-to-checkpoint button and scrolls to latest checkpoint", async () => { await hydrate(2, buildMessagesWithCheckpoint(Date.now() - 3_000)) await waitForCalls(2) diff --git a/webview-ui/src/components/chat/__tests__/PreviousUserMessageButton.visual.tsx b/webview-ui/src/components/chat/__tests__/PreviousUserMessageButton.visual.tsx new file mode 100644 index 0000000000..5e3f9b424d --- /dev/null +++ b/webview-ui/src/components/chat/__tests__/PreviousUserMessageButton.visual.tsx @@ -0,0 +1,25 @@ +import { expect, test } from "../../../../playwright/coverage-fixture" +import { mountedStory } from "../../../../playwright/mounted-story" + +const themes = [ + { name: "dark", bodyClass: "vscode-dark", themeId: "Default Dark Modern" }, + { name: "light", bodyClass: "vscode-light", themeId: "Default Light Modern" }, +] as const + +for (const theme of themes) { + test(`renders previous-user-message navigation in the VS Code ${theme.name} theme`, async ({ mount, page }) => { + const component = mountedStory(await mount("previous-user-message-button")) + await page.evaluate(({ bodyClass, themeId }) => { + document.documentElement.className = bodyClass + document.body.className = bodyClass + document.body.dataset.vscodeThemeId = themeId + }, theme) + + await component.evaluate(async () => { + await document.fonts.ready + await new Promise((resolve) => requestAnimationFrame(() => resolve())) + }) + + await expect(component).toHaveScreenshot(`previous-user-message-button-${theme.name}.png`) + }) +} diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index fe241f6145..cf433fbfe4 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -125,6 +125,7 @@ }, "scrollToBottom": "Scroll to bottom of chat", "scrollToLatestCheckpoint": "Scroll to previous checkpoint", + "jumpToPreviousUserMessage": "Jump to previous message you sent", "about": "Zoo is a whole AI dev team in your editor", "docs": "Check our docs to get started", "onboarding": "What would you like to do?", From 4680c5b1a9871228fbf16a9010ceb77b37d8a489 Mon Sep 17 00:00:00 2001 From: "@navedmerchant" <14171946+navedmerchant@users.noreply.github.com> Date: Tue, 1 Sep 2026 18:15:44 +0000 Subject: [PATCH 2/3] test(chat): add user message navigation baselines --- .../previous-user-message-button-dark.png | Bin 0 -> 1411 bytes .../previous-user-message-button-light.png | Bin 0 -> 1333 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/previous-user-message-button-dark.png create mode 100644 webview-ui/src/components/chat/__tests__/__screenshots__/previous-user-message-button-light.png diff --git a/webview-ui/src/components/chat/__tests__/__screenshots__/previous-user-message-button-dark.png b/webview-ui/src/components/chat/__tests__/__screenshots__/previous-user-message-button-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..50ede537b9495966205c46a2fe09cf49ff05ecd1 GIT binary patch literal 1411 zcma)+{Xf$Q0LQHEh$M{<>8ijb|g&Xacp9-MucW1&!#3~4wDkPSh?{UZDKU9 z!!nN<%6S+WmdCk-8JRp?&bj}fAKstW`}O$)-WeWlmz5OM6aWBFa&oly1OU*fJvWk* z+FRN{q!<9eW={5(knt4JCwE7!tLm~V13@Li;&-_owTDD9CYKaxp1g-|bOl%5nj_zx z-1oH_BLxqouJt=7jz^spw_1rjQ}G7oqLY511i9B3Ph-cFGwJn){z}(m3lXrwjGAVh z@yf-qZ>}>@JCYrBncYUG)JEnqXEKr8z+!m;fb{|xn34fWPs#lNU3x>@aFeVONB;Kq zHk)n1RsiOF>BzCk$#Ptc&rr;ZDqAInB4h`got>R~MiUXyie%Sz2bDZ|NHEjZFYa3w zi+P)xkPtJhN+pRTbLD6@TB-$pIRO_IMm@j`LsLDVYOr=;PDfza?b{CQDNpJF_Y0-H zzd(ZYutuRg0n*f4ih>(jqD#E?DUJu9!sgc;o=UtnF#d9`ERa>x5v^0C9KK`_m&5FvyHMV?VHfpgom4d5p8V4@^+JVm6lhZ* z5PbMMQcvF%kH>eKl+4J(y#Y+m62EynwmK%@eEbG~bAdE(#q3)g@%KmjZ0BG}?Kw}PyDe& z`sss(0EH6NG8H{?vGJShA57sC0(Ad=?D_bMRqD4HwD#7uUCyIIMcJoP6tK&=ph<7( z_EmHEGm4RkeD1h#!7TdFWl=YJs*JZ1h{8SO*%+X-bXvD1Zy+uSO$~9FCHSZibX#>q5uvzl6d8n4#Fmuxl&tndc>FY4Mbgq-%EbJi$w)0mOYf- z`id;=6(X0GLOV9-089HASc5es7x9J{c&m>VSp(E2H^IwoQ4Y$yqM(qXac{NbOV`{| zee*%Bw&kAn!^;59y_Nzp!+4Y92V6k?D>TOIbcS!p{aSt_hm%dP@{3eSuB_BwUzaIB z)gFee@qnW)+Ww^2O7chj&+@lkq`{G%2fcb!vdI{}9R>eC}$R;jb3Q4Sv_sc;Wxe#uGQn@zDWV5YQyY#ek~H=nzzObVUuBC;`48!BrbPe% literal 0 HcmV?d00001 diff --git a/webview-ui/src/components/chat/__tests__/__screenshots__/previous-user-message-button-light.png b/webview-ui/src/components/chat/__tests__/__screenshots__/previous-user-message-button-light.png new file mode 100644 index 0000000000000000000000000000000000000000..4d23bf03da29d51dbe721c2bb62329e4e8b4158b GIT binary patch literal 1333 zcma)+`#aMM0LH&tix3aep}ACA(rE6QZCNtf=8zDIAoB#AgI8kdxA7DBeLi}MlJNCxBgb!9E{4(NYKN4#L-B}$hwiaTG-4zo zVEjf~Vq?ZmBDo=Bk^kMn7%_5G$`43uI?~gPNUv}rE)MyJ9hBz!8}3h4DzdPQIKKY)EFqVW>v{|0spOpM#iE@$tRVJeW*L2jtz{@>>0C?{o(1wp*M}?mrlS-w1 zeM)Y&FPSVRlQ(q{H_Ba_JjAATz9@xGw@b0U#}%1+QTj<0}Bp>P7sB8gTYG!j`g z8b#_i1j@Q*V}B>v-+ARoYSK3^U`4eO0n~Os)XLh`ClM`62tN=SgBceJ_X1^^=Lg0x zVUMyBpHreg|8WvvuPNZ+IYlPF#36UP-FvI`CNYwSZbq`$@{N z6VJ`D^m~kOe(Cyx;QXs@De_k(o)0FnJdS0z)_a~?TlR}zD?GQMw;U*26rt}X&@!K} z5u78nGL)`}$8XIY6zR){d}7!e(ur{FYRgiu#4q6tDha>{V7L6CLA>% zbicH9dxkB<(uG`MZ>`DDHk-|@Q43f_R@J;!F@sX8JsREHG)tS~4t?qOf>-m!I|^{4 zFkVqk_U%`~ypQvShJoNwY9^t(i#N*Fa~(|HVd9NHdNQ?emWD1*bmjOT=;uaT)z@i_ zRF7nxRjm<~6!)9fMf{GWg@9vjJ{%pENwAhOhMBna4Re%5F{iHt6B$&;S-fHXN_|In z0j=8jdVFUqE)G=&fy4}7BWdyEwZfBwv$ncq!r~i$7OC+^{&agSWCHRY5^nqq+zT~= zK!Tin1e`{?)h(^;n_H+IYPd(W=!-MnS6q}78)l+)ODjG?XW~C$E0M8CgWblVme0HT zE5F>XFrk=;5`=#>6RG}T40UK$#@+f~UAvT7(1B0V22L0_7+>KVyDIEva68wE8+*p5 z@$J5Leg~U+ongk!)H!ZkK@L_&DJX$Sy+p4TEBhuS9Ojw)x}P4TQ9{3BRw>55UBB!_ zw8O&l-(cF2a2vD*H0d-OR;*B^4PqZe6lN{JK_YRN1SW7b&+3RSu0($O@M~pd1^Iy8 zBJDiS@aTdmbUv;RG=FU;aHiyXY@W%Wq Date: Tue, 1 Sep 2026 18:23:45 +0000 Subject: [PATCH 3/3] feat(i18n): translate user message navigation --- webview-ui/src/i18n/locales/ca/chat.json | 1 + webview-ui/src/i18n/locales/de/chat.json | 1 + webview-ui/src/i18n/locales/es/chat.json | 1 + webview-ui/src/i18n/locales/fr/chat.json | 1 + webview-ui/src/i18n/locales/hi/chat.json | 1 + webview-ui/src/i18n/locales/id/chat.json | 1 + webview-ui/src/i18n/locales/it/chat.json | 1 + webview-ui/src/i18n/locales/ja/chat.json | 1 + webview-ui/src/i18n/locales/ko/chat.json | 1 + webview-ui/src/i18n/locales/nl/chat.json | 1 + webview-ui/src/i18n/locales/pl/chat.json | 1 + webview-ui/src/i18n/locales/pt-BR/chat.json | 1 + webview-ui/src/i18n/locales/ru/chat.json | 1 + webview-ui/src/i18n/locales/tr/chat.json | 1 + webview-ui/src/i18n/locales/vi/chat.json | 1 + webview-ui/src/i18n/locales/zh-CN/chat.json | 1 + webview-ui/src/i18n/locales/zh-TW/chat.json | 1 + 17 files changed, 17 insertions(+) diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json index 87cec9f61f..2d9f898ed8 100644 --- a/webview-ui/src/i18n/locales/ca/chat.json +++ b/webview-ui/src/i18n/locales/ca/chat.json @@ -98,6 +98,7 @@ "enqueueMessage": "Afegeix el missatge a la cua (s'enviarà quan acabi la tasca actual)", "scrollToBottom": "Desplaça't al final del xat", "scrollToLatestCheckpoint": "Desplaça't al checkpoint anterior", + "jumpToPreviousUserMessage": "Salta al missatge anterior que has enviat", "about": "Zoo Code és tot un equip de desenvolupament d'IA al teu editor.", "docs": "Consulta els nostres documents per a més informació.", "onboarding": "La teva llista de tasques en aquest espai de treball està buida.", diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json index b9591fe3aa..36ee5ab9de 100644 --- a/webview-ui/src/i18n/locales/de/chat.json +++ b/webview-ui/src/i18n/locales/de/chat.json @@ -98,6 +98,7 @@ "enqueueMessage": "Nachricht zur Warteschlange hinzufügen (wird nach Abschluss der aktuellen Aufgabe gesendet)", "scrollToBottom": "Zum Chat-Ende scrollen", "scrollToLatestCheckpoint": "Zum vorherigen Checkpoint scrollen", + "jumpToPreviousUserMessage": "Zur vorherigen von dir gesendeten Nachricht springen", "about": "Zoo Code ist ein ganzes KI-Entwicklerteam in deinem Editor.", "docs": "Schau in unsere Dokumentation, um mehr zu erfahren.", "onboarding": "Deine Aufgabenliste in diesem Arbeitsbereich ist leer.", diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json index 1cbeab08e4..7d9bec0b89 100644 --- a/webview-ui/src/i18n/locales/es/chat.json +++ b/webview-ui/src/i18n/locales/es/chat.json @@ -98,6 +98,7 @@ "enqueueMessage": "Agregar mensaje a la cola (se enviará después de que termine la tarea actual)", "scrollToBottom": "Desplazarse al final del chat", "scrollToLatestCheckpoint": "Desplazarse al checkpoint anterior", + "jumpToPreviousUserMessage": "Saltar al mensaje anterior que enviaste", "about": "Zoo Code es todo un equipo de desarrollo de IA en tu editor.", "docs": "Consulta nuestra documentación para saber más.", "onboarding": "Tu lista de tareas en este espacio de trabajo está vacía.", diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json index 7ab8213cd5..6f698da532 100644 --- a/webview-ui/src/i18n/locales/fr/chat.json +++ b/webview-ui/src/i18n/locales/fr/chat.json @@ -98,6 +98,7 @@ "enqueueMessage": "Ajouter le message à la file d'attente (sera envoyé après la fin de la tâche en cours)", "scrollToBottom": "Défiler jusqu'au bas du chat", "scrollToLatestCheckpoint": "Défiler jusqu'au checkpoint précédent", + "jumpToPreviousUserMessage": "Accéder au message précédent que vous avez envoyé", "about": "Zoo Code est une équipe complète de développeurs IA dans votre éditeur.", "docs": "Consultez notre documentation pour en savoir plus.", "onboarding": "Votre liste de tâches dans cet espace de travail est vide.", diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json index 8b57cefc89..5fa9c8e237 100644 --- a/webview-ui/src/i18n/locales/hi/chat.json +++ b/webview-ui/src/i18n/locales/hi/chat.json @@ -98,6 +98,7 @@ "enqueueMessage": "संदेश को कतार में जोड़ें (वर्तमान कार्य पूरा होने के बाद भेजा जाएगा)", "scrollToBottom": "चैट के निचले हिस्से तक स्क्रॉल करें", "scrollToLatestCheckpoint": "पिछले चेकपॉइंट तक स्क्रॉल करें", + "jumpToPreviousUserMessage": "आपके भेजे गए पिछले संदेश पर जाएँ", "about": "Zoo Code आपके संपादक में एक पूरी AI देव टीम है।", "docs": "और जानने के लिए हमारे दस्तावेज़ देखें।", "onboarding": "इस कार्यक्षेत्र में आपकी कार्य सूची खाली है।", diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json index fe3d6808d8..99e38d82b6 100644 --- a/webview-ui/src/i18n/locales/id/chat.json +++ b/webview-ui/src/i18n/locales/id/chat.json @@ -128,6 +128,7 @@ "enqueueMessage": "Tambahkan pesan ke antrean (akan dikirim setelah tugas saat ini selesai)", "scrollToBottom": "Gulir ke bawah chat", "scrollToLatestCheckpoint": "Gulir ke checkpoint sebelumnya", + "jumpToPreviousUserMessage": "Lompat ke pesan sebelumnya yang Anda kirim", "about": "Zoo Code adalah seluruh tim pengembang AI di editor Anda.", "docs": "Lihat dokumentasi kami untuk mempelajari lebih lanjut.", "onboarding": "Daftar tugas Anda di ruang kerja ini kosong.", diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json index 9dcfd68997..ae9727bc8c 100644 --- a/webview-ui/src/i18n/locales/it/chat.json +++ b/webview-ui/src/i18n/locales/it/chat.json @@ -98,6 +98,7 @@ "enqueueMessage": "Aggiungi il messaggio alla coda (sarà inviato dopo che l'attività corrente sarà terminata)", "scrollToBottom": "Scorri fino alla fine della chat", "scrollToLatestCheckpoint": "Scorri al checkpoint precedente", + "jumpToPreviousUserMessage": "Vai al messaggio precedente che hai inviato", "about": "Zoo Code è un intero team di sviluppo AI nel tuo editor.", "docs": "Consulta la nostra documentazione per saperne di più.", "onboarding": "La tua lista di attività in questo spazio di lavoro è vuota.", diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json index f098c68879..eafb0e8eb3 100644 --- a/webview-ui/src/i18n/locales/ja/chat.json +++ b/webview-ui/src/i18n/locales/ja/chat.json @@ -98,6 +98,7 @@ "enqueueMessage": "メッセージをキューに追加(現在のタスク完了後に送信されます)", "scrollToBottom": "チャットの最下部にスクロール", "scrollToLatestCheckpoint": "前のチェックポイントまでスクロール", + "jumpToPreviousUserMessage": "以前に送信したメッセージに移動", "about": "Zoo Codeは、エディタに常駐するAI開発チームです。", "docs": "詳細については、ドキュメントをご確認ください。", "onboarding": "このワークスペースのタスクリストは空です。", diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json index 7c1b51f934..6a7500439f 100644 --- a/webview-ui/src/i18n/locales/ko/chat.json +++ b/webview-ui/src/i18n/locales/ko/chat.json @@ -98,6 +98,7 @@ "enqueueMessage": "메시지를 대기열에 추가 (현재 작업 완료 후 전송)", "scrollToBottom": "채팅 하단으로 스크롤", "scrollToLatestCheckpoint": "이전 체크포인트로 스크롤", + "jumpToPreviousUserMessage": "이전에 보낸 메시지로 이동", "about": "Zoo Code는 편집기 안에 있는 전체 AI 개발팀입니다.", "docs": "더 알아보려면 문서를 확인하세요.", "onboarding": "이 작업 공간의 작업 목록이 비어 있습니다.", diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json index d75e451b81..ab68dba20e 100644 --- a/webview-ui/src/i18n/locales/nl/chat.json +++ b/webview-ui/src/i18n/locales/nl/chat.json @@ -98,6 +98,7 @@ "enqueueMessage": "Bericht aan de wachtrij toevoegen (wordt verzonden nadat de huidige taak is voltooid)", "scrollToBottom": "Scroll naar onderaan de chat", "scrollToLatestCheckpoint": "Scroll naar het vorige checkpoint", + "jumpToPreviousUserMessage": "Ga naar je vorige bericht", "about": "Zoo Code is een heel AI-ontwikkelteam in je editor.", "docs": "Bekijk onze documentatie voor meer informatie.", "onboarding": "Je takenlijst in deze werkruimte is leeg.", diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json index 9769c48201..990865ea07 100644 --- a/webview-ui/src/i18n/locales/pl/chat.json +++ b/webview-ui/src/i18n/locales/pl/chat.json @@ -98,6 +98,7 @@ "enqueueMessage": "Dodaj wiadomość do kolejki (zostanie wysłana po zakończeniu bieżącego zadania)", "scrollToBottom": "Przewiń do dołu czatu", "scrollToLatestCheckpoint": "Przewiń do poprzedniego punktu kontrolnego", + "jumpToPreviousUserMessage": "Przejdź do poprzedniej wysłanej wiadomości", "about": "Zoo Code to cały zespół deweloperów AI w Twoim edytorze.", "docs": "Sprawdź naszą dokumentację, aby dowiedzieć się więcej.", "onboarding": "Twoja lista zadań w tym obszarze roboczym jest pusta.", diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json index 1ce9610adc..18a90c3bde 100644 --- a/webview-ui/src/i18n/locales/pt-BR/chat.json +++ b/webview-ui/src/i18n/locales/pt-BR/chat.json @@ -98,6 +98,7 @@ "enqueueMessage": "Adicionar mensagem à fila (será enviada após a conclusão da tarefa atual)", "scrollToBottom": "Rolar para o final do chat", "scrollToLatestCheckpoint": "Rolar para o checkpoint anterior", + "jumpToPreviousUserMessage": "Ir para a mensagem anterior que você enviou", "about": "Zoo Code é uma equipe inteira de desenvolvimento de IA em seu editor.", "docs": "Confira nossa documentação para saber mais.", "onboarding": "Sua lista de tarefas neste espaço de trabalho está vazia.", diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json index 4195d4d705..64f5853558 100644 --- a/webview-ui/src/i18n/locales/ru/chat.json +++ b/webview-ui/src/i18n/locales/ru/chat.json @@ -98,6 +98,7 @@ "enqueueMessage": "Добавить сообщение в очередь (будет отправлено после завершения текущей задачи)", "scrollToBottom": "Прокрутить чат вниз", "scrollToLatestCheckpoint": "Прокрутить к предыдущему чекпоинту", + "jumpToPreviousUserMessage": "Перейти к предыдущему отправленному вами сообщению", "about": "Zoo Code — это целая команда разработчиков ИИ в вашем редакторе.", "docs": "Ознакомьтесь с нашей документацией, чтобы узнать больше.", "onboarding": "Ваш список задач в этом рабочем пространстве пуст.", diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json index 9fdffcd14b..c8ee7e4948 100644 --- a/webview-ui/src/i18n/locales/tr/chat.json +++ b/webview-ui/src/i18n/locales/tr/chat.json @@ -98,6 +98,7 @@ "enqueueMessage": "Mesajı kuyruğa ekle (mevcut görev tamamlandıktan sonra gönderilecek)", "scrollToBottom": "Sohbetin altına kaydır", "scrollToLatestCheckpoint": "Önceki checkpoint'e kaydır", + "jumpToPreviousUserMessage": "Gönderdiğiniz önceki mesaja atla", "about": "Zoo Code, düzenleyicinizdeki bütün bir yapay zeka geliştirme ekibidir.", "docs": "Daha fazla bilgi için belgelerimize göz atın.", "onboarding": "Bu çalışma alanındaki görev listeniz boş.", diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json index 2812fbdccf..c1998d431e 100644 --- a/webview-ui/src/i18n/locales/vi/chat.json +++ b/webview-ui/src/i18n/locales/vi/chat.json @@ -98,6 +98,7 @@ "enqueueMessage": "Thêm tin nhắn vào hàng đợi (sẽ gửi sau khi nhiệm vụ hiện tại hoàn tất)", "scrollToBottom": "Cuộn xuống cuối cuộc trò chuyện", "scrollToLatestCheckpoint": "Cuộn đến checkpoint trước đó", + "jumpToPreviousUserMessage": "Chuyển đến tin nhắn trước đó bạn đã gửi", "about": "Zoo Code là một đội ngũ phát triển AI đầy đủ trong trình chỉnh sửa của bạn.", "docs": "Kiểm tra tài liệu của chúng tôi để tìm hiểu thêm.", "onboarding": "Danh sách nhiệm vụ của bạn trong không gian làm việc này đang trống.", diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index 5575dad5df..ec8055f3d5 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -98,6 +98,7 @@ "enqueueMessage": "将消息加入队列(当前任务完成后发送)", "scrollToBottom": "滚动到聊天底部", "scrollToLatestCheckpoint": "滚动到上一个检查点", + "jumpToPreviousUserMessage": "跳转到你之前发送的消息", "about": "Zoo Code 是您编辑器中的整个 AI 开发团队。", "docs": "查看我们的 文档 了解更多信息。", "onboarding": "此工作区中的任务列表为空。", diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index 184728d6a5..9c043489cc 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -125,6 +125,7 @@ }, "scrollToBottom": "捲動至對話底部", "scrollToLatestCheckpoint": "捲動至上一個檢查點", + "jumpToPreviousUserMessage": "跳至你先前傳送的訊息", "about": "Zoo 是編輯器中的完整 AI 開發團隊。", "docs": "請參閱 說明文件 開始使用。", "onboarding": "想要做什麼呢?",