From b511abf7f9cc06efdd749406a9c7767049aec169 Mon Sep 17 00:00:00 2001 From: Serhii Vecherenko Date: Sat, 22 Aug 2026 00:45:15 -0700 Subject: [PATCH] fix(threads): add configurable deletion confirmation - Add thread deletion confirmation popover with persistent preference - Preserve focus and anchor context-menu actions correctly - Refactor worktree deletion dialogs and sidebar row handling - Update localized strings and coverage tests --- src/renderer/actions/threadActions.test.ts | 77 ++++++- src/renderer/actions/threadActions.ts | 89 +++++--- .../components/common/ConfirmationPopover.tsx | 95 ++++++++ .../components/common/ContextMenu.test.tsx | 19 +- .../components/common/ContextMenu.tsx | 10 +- src/renderer/locales/de/messages.po | 97 +++++++-- src/renderer/locales/en/messages.po | 97 +++++++-- src/renderer/locales/es/messages.po | 97 +++++++-- src/renderer/locales/fr/messages.po | 97 +++++++-- src/renderer/locales/ja/messages.po | 97 +++++++-- src/renderer/locales/ko/messages.po | 97 +++++++-- src/renderer/locales/pl/messages.po | 97 +++++++-- src/renderer/locales/pt-BR/messages.po | 97 +++++++-- src/renderer/locales/ru/messages.po | 97 +++++++-- src/renderer/locales/tr/messages.po | 97 +++++++-- src/renderer/locales/uk/messages.po | 97 +++++++-- src/renderer/locales/vi/messages.po | 97 +++++++-- src/renderer/locales/zh-CN/messages.po | 97 +++++++-- src/renderer/state/threadDeletePreference.ts | 15 ++ src/renderer/state/worktreeDeleteStore.ts | 10 +- .../parts/DeleteThreadPopover.test.tsx | 96 +++++++++ .../Sidebar/parts/DeleteThreadPopover.tsx | 60 ++++++ .../Sidebar/parts/DeleteWorktreeDialog.tsx | 80 ------- .../Sidebar/parts/SidebarThreadRow.test.tsx | 204 ++++++++++++++++++ .../parts/Sidebar/parts/SidebarThreadRow.tsx | 104 ++++++++- .../parts/ThreadItemSuffix.tsx | 37 +++- .../parts/Sidebar/parts/ThreadContextMenu.tsx | 9 +- .../Sidebar/parts/sidebarProjectRows.test.ts | 25 +++ .../parts/Sidebar/parts/sidebarProjectRows.ts | 23 +- .../parts/WorktreeDeleteDialogs.test.tsx | 90 +++++++- .../MainView/parts/WorktreeDeleteDialogs.tsx | 38 ++-- .../parts/ThreadSettings.test.tsx | 24 ++- .../SettingsOverlay/parts/ThreadSettings.tsx | 24 ++- .../parts/settingsSearchIndex.test.ts | 3 + .../parts/settingsSearchIndex.ts | 8 + 35 files changed, 2039 insertions(+), 362 deletions(-) create mode 100644 src/renderer/components/common/ConfirmationPopover.tsx create mode 100644 src/renderer/state/threadDeletePreference.ts create mode 100644 src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.test.tsx create mode 100644 src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx delete mode 100644 src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx create mode 100644 src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.test.tsx diff --git a/src/renderer/actions/threadActions.test.ts b/src/renderer/actions/threadActions.test.ts index 15194835d..0ee3b2275 100644 --- a/src/renderer/actions/threadActions.test.ts +++ b/src/renderer/actions/threadActions.test.ts @@ -11,6 +11,7 @@ import { useWorktreeDeleteStore } from "@/renderer/state/worktreeDeleteStore"; import { archiveThread, deleteThread, + requestDeleteThread, openNewThread, openThread, reopenPaneThreadsIfInactive, @@ -657,7 +658,9 @@ describe("threadActions", () => { }); useAppStore.setState((state) => ({ ...state, threads: [thread] })); - deleteThread(thread.id, worktreePath, thread.projectId); + requestDeleteThread(thread.id, worktreePath, thread.projectId, { + anchorPosition: { x: 240, y: 120 }, + }); expect(useAppStore.getState().threads).toHaveLength(1); expect(bridge.closeThread).not.toHaveBeenCalled(); @@ -667,11 +670,80 @@ describe("threadActions", () => { projectId: thread.projectId, worktreePath, worktreeBranch: "poracode/feature", + anchorPosition: { x: 240, y: 120 }, }); }); - it("routes local worktree deletion through the group action", () => { + it("asks again for the legacy thread-only preference instead of deleting a worktree", () => { + localStorage.setItem("poracode-delete-worktree-pref", "thread-only"); + const worktreePath = "/repo/.worktrees/feature"; + const thread = makeThread({ + worktreePath, + worktreeBranch: "poracode/feature", + }); + useAppStore.setState((state) => ({ ...state, threads: [thread] })); + + requestDeleteThread(thread.id, worktreePath, thread.projectId, { + anchorPosition: { x: 240, y: 120 }, + }); + + expect(useAppStore.getState().threads).toHaveLength(1); + expect(deleteWorktreeGroup).not.toHaveBeenCalled(); + expect(useWorktreeDeleteStore.getState().dialog?.kind).toBe("single-thread"); + }); + + it("confirms a thread that has no worktree without naming one", () => { + const thread = makeThread({}); + useAppStore.setState((state) => ({ ...state, threads: [thread] })); + + requestDeleteThread(thread.id, undefined, thread.projectId, { + anchorPosition: { x: 240, y: 120 }, + }); + + expect(useAppStore.getState().threads).toHaveLength(1); + expect(bridge.closeThread).not.toHaveBeenCalled(); + expect(useWorktreeDeleteStore.getState().dialog).toEqual({ + kind: "single-thread", + threadId: thread.id, + projectId: thread.projectId, + anchorPosition: { x: 240, y: 120 }, + }); + }); + + it("confirms a shared-worktree thread without promising to remove the worktree", () => { + const worktreePath = "/repo/.worktrees/feature"; + const firstThread = makeThread({ id: "thread-a", worktreePath }); + const secondThread = makeThread({ id: "thread-b", worktreePath }); + useAppStore.setState((state) => ({ ...state, threads: [firstThread, secondThread] })); + + requestDeleteThread(firstThread.id, worktreePath, firstThread.projectId, { + anchorPosition: { x: 240, y: 120 }, + }); + + expect(useAppStore.getState().threads).toHaveLength(2); + expect(useWorktreeDeleteStore.getState().dialog).toEqual({ + kind: "single-thread", + threadId: firstThread.id, + projectId: firstThread.projectId, + anchorPosition: { x: 240, y: 120 }, + }); + }); + + it("skips the confirmation entirely once the user opted out", () => { localStorage.setItem("poracode-delete-worktree-pref", "thread-and-worktree"); + const thread = makeThread({}); + useAppStore.setState((state) => ({ ...state, threads: [thread] })); + + requestDeleteThread(thread.id, undefined, thread.projectId, { + anchorPosition: { x: 240, y: 120 }, + }); + + expect(useAppStore.getState().threads).toEqual([]); + expect(bridge.closeThread).toHaveBeenCalledWith({ threadId: thread.id }); + expect(useWorktreeDeleteStore.getState().dialog).toBeNull(); + }); + + it("routes local worktree deletion through the group action", () => { const worktreePath = "/repo/.worktrees/feature"; const project = useAppStore.getState().addProject({ kind: "posix", @@ -691,7 +763,6 @@ describe("threadActions", () => { }); it("routes remote worktree deletion through the remote-aware group action", () => { - localStorage.setItem("poracode-delete-worktree-pref", "thread-and-worktree"); const worktreePath = "/repo/.worktrees/feature"; const localProject = useAppStore.getState().addProject({ kind: "posix", diff --git a/src/renderer/actions/threadActions.ts b/src/renderer/actions/threadActions.ts index 061670799..7ac4c38be 100644 --- a/src/renderer/actions/threadActions.ts +++ b/src/renderer/actions/threadActions.ts @@ -23,9 +23,9 @@ import { } from "@/renderer/state/chatRuntimePersister"; import { useSharedSettings } from "@/renderer/state/sharedSettingsStore"; import { useSidebarUiStore } from "@/renderer/state/sidebarUiStore"; +import { shouldConfirmThreadDelete } from "@/renderer/state/threadDeletePreference"; import { getActiveWorkspaceId, getLastWorkspaceProjectId } from "@/renderer/state/workspaceStore"; import { useWorktreeDeleteStore } from "@/renderer/state/worktreeDeleteStore"; -import { readWorktreeDeletePref } from "@/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog"; import { buildSidebarProjectRows } from "@/renderer/views/MainView/parts/Sidebar/parts/sidebarProjectRows"; import { resolveWorktreeBranch } from "@/renderer/utils/gitHelpers"; import { closeThreads } from "@/renderer/utils/shellUtils"; @@ -627,48 +627,81 @@ function deleteThreadOnly(threadId: string): void { .catch(() => undefined); } +/** True when `threadId` is the only thread still using `worktreePath`. */ +function ownsWorktreeAlone(threadId: string, worktreePath: string): boolean { + return !useAppStore + .getState() + .threads.some( + (candidate) => candidate.worktreePath === worktreePath && candidate.id !== threadId, + ); +} + +/** + * Deletes a thread, also removing its worktree directory when this was the last + * thread using it. Confirmation is the caller's job — see `requestDeleteThread` + * for the interactive entry point. + */ export function deleteThread(threadId: string, worktreePath?: string, projectId?: string): void { if (findExperimentByThreadId(threadId)) return; - if (!worktreePath) { + // No worktree, or siblings still use it — drop the thread and keep the directory. + if (!worktreePath || !ownsWorktreeAlone(threadId, worktreePath)) { deleteThreadOnly(threadId); return; } - const allThreads = useAppStore.getState().threads; - const siblings = allThreads.filter((t) => t.worktreePath === worktreePath && t.id !== threadId); - - // Other threads still use this worktree — delete the thread without offering worktree removal. - if (siblings.length > 0) { - deleteThreadOnly(threadId); - return; - } - - const pref = readWorktreeDeletePref(); - if (pref === "thread-only") { - deleteThreadOnly(threadId); + const project = useAppStore.getState().projects.find((p) => p.id === projectId); + if (!project) { + useAppStore.getState().deleteThread(threadId); return; } + deleteWorktreeGroup(project.id, worktreePath, [threadId]); +} - if (pref === "thread-and-worktree") { - const project = useAppStore.getState().projects.find((p) => p.id === projectId); - if (project) { - deleteWorktreeGroup(project.id, worktreePath, [threadId]); - return; - } - useAppStore.getState().deleteThread(threadId); +/** + * Sidebar-initiated delete: asks first unless the user turned confirmation off, + * then routes through `deleteThread`. Every thread is confirmed the same way, + * whether or not it owns a worktree — the popover only names the worktree when + * deleting this thread is what would take the directory with it. + */ +export function requestDeleteThread( + threadId: string, + worktreePath: string | undefined, + projectId: string | undefined, + options?: { + anchorPosition?: { x: number; y: number }; + returnFocusElement?: HTMLElement; + }, +): void { + if (findExperimentByThreadId(threadId)) return; + if (!shouldConfirmThreadDelete()) { + deleteThread(threadId, worktreePath, projectId); return; } - const thread = allThreads.find((t) => t.id === threadId); + const thread = useAppStore.getState().threads.find((candidate) => candidate.id === threadId); + // Named in the confirmation only when this delete is what removes the directory. + const worktreeToRemove = + worktreePath !== undefined && + projectId !== undefined && + ownsWorktreeAlone(threadId, worktreePath) + ? { + worktreePath, + worktreeBranch: + resolveWorktreeBranch(projectId, worktreePath, thread?.worktreeBranch) ?? + worktreePath.split(/[/\\]/).pop() ?? + worktreePath, + } + : {}; useWorktreeDeleteStore.getState().setDialog({ kind: "single-thread", threadId, - projectId: projectId!, - worktreePath, - worktreeBranch: - resolveWorktreeBranch(projectId!, worktreePath, thread?.worktreeBranch) ?? - worktreePath.split(/[/\\]/).pop() ?? - worktreePath, + ...(projectId !== undefined ? { projectId } : {}), + ...worktreeToRemove, + anchorPosition: options?.anchorPosition ?? { + x: window.innerWidth / 2, + y: window.innerHeight / 2, + }, + ...(options?.returnFocusElement ? { returnFocusElement: options.returnFocusElement } : {}), }); } diff --git a/src/renderer/components/common/ConfirmationPopover.tsx b/src/renderer/components/common/ConfirmationPopover.tsx new file mode 100644 index 000000000..a82d84622 --- /dev/null +++ b/src/renderer/components/common/ConfirmationPopover.tsx @@ -0,0 +1,95 @@ +import type { ComponentProps, ReactNode } from "react"; +import { Popover } from "@heroui/react"; +import { useLingui } from "@lingui/react/macro"; +import { Button } from "./Button"; + +type ButtonVariant = ComponentProps["variant"]; +type PopoverPlacement = ComponentProps["placement"]; + +export interface ConfirmationPopoverAction { + label: string; + variant?: ButtonVariant; + className?: string; + onPress: () => void; +} + +type ConfirmationPopoverProps = { + isOpen: boolean; + onOpenChange: (isOpen: boolean) => void; + title: string; + body: ReactNode; + actions: readonly ConfirmationPopoverAction[]; + placement?: PopoverPlacement; + className?: string; + children?: ReactNode; + returnFocusElement?: HTMLElement | null; +} & ( + | { trigger: ReactNode; anchorPosition?: never } + | { trigger?: never; anchorPosition: { x: number; y: number } } +); + +export function ConfirmationPopover(props: ConfirmationPopoverProps) { + const { t } = useLingui(); + const handleOpenChange = (isOpen: boolean) => { + props.onOpenChange(isOpen); + if (!isOpen && props.returnFocusElement?.isConnected) { + requestAnimationFrame(() => props.returnFocusElement?.focus({ preventScroll: true })); + } + }; + const trigger = + props.trigger ?? + (props.anchorPosition ? ( + + {props.actions.map((action) => ( + + ))} + + + + + ); + + if (!props.anchorPosition) return popover; + return ( +
+ {popover} +
+ ); +} diff --git a/src/renderer/components/common/ContextMenu.test.tsx b/src/renderer/components/common/ContextMenu.test.tsx index d2ea1e341..01143321d 100644 --- a/src/renderer/components/common/ContextMenu.test.tsx +++ b/src/renderer/components/common/ContextMenu.test.tsx @@ -44,7 +44,14 @@ describe("ContextMenu", () => { }); it("dispatches an item's trailing action without dispatching the row", async () => { - const onAction = vi.fn<(key: string) => void>(); + const onAction = + vi.fn< + ( + key: string, + anchorPosition?: { x: number; y: number }, + returnFocusElement?: HTMLElement, + ) => void + >(); render( { , ); - fireEvent.contextMenu(screen.getByRole("button", { name: "Row" })); + const row = screen.getByRole("button", { name: "Row" }); + fireEvent.contextMenu(row, { + clientX: 240, + clientY: 120, + }); const stopButton = await screen.findByRole("button", { name: "Stop Run" }); expect(stopButton).toHaveClass("[--button-bg-hover:var(--row-hover)]"); fireEvent.pointerDown(stopButton, { pointerId: 1, pointerType: "mouse", button: 0 }); fireEvent.pointerUp(stopButton, { pointerId: 1, pointerType: "mouse", button: 0 }); fireEvent.click(stopButton); - expect(onAction).toHaveBeenCalledWith("stop"); - expect(onAction).not.toHaveBeenCalledWith("run"); + expect(onAction).toHaveBeenCalledWith("stop", { x: 240, y: 120 }, row); + expect(onAction).not.toHaveBeenCalledWith("run", expect.anything()); await vi.waitFor(() => { expect(screen.queryByRole("menuitem", { name: "Run" })).not.toBeInTheDocument(); }); diff --git a/src/renderer/components/common/ContextMenu.tsx b/src/renderer/components/common/ContextMenu.tsx index 676aab5e4..ca83985c7 100644 --- a/src/renderer/components/common/ContextMenu.tsx +++ b/src/renderer/components/common/ContextMenu.tsx @@ -76,7 +76,11 @@ export type ContextMenuEntry = ContextMenuItem | ContextMenuSubmenu | ContextMen export interface ContextMenuProps { items: ContextMenuEntry[]; - onAction: (key: string) => void; + onAction: ( + key: string, + anchorPosition?: { x: number; y: number }, + returnFocusElement?: HTMLElement, + ) => void; children: ReactNode; } @@ -406,6 +410,7 @@ export function ContextMenuSurface(props: { export function ContextMenu(props: ContextMenuProps) { const { items, onAction, children } = props; const [position, setPosition] = useState<{ x: number; y: number } | null>(null); + const [returnFocusElement, setReturnFocusElement] = useState(null); function handleContextMenu(e: React.MouseEvent) { e.preventDefault(); @@ -414,6 +419,7 @@ export function ContextMenu(props: ContextMenuProps) { // handles itself). closeAllMenus(); setPosition({ x: e.clientX, y: e.clientY }); + setReturnFocusElement(e.currentTarget instanceof HTMLElement ? e.currentTarget : null); } const trigger = React.isValidElement<{ onContextMenu?: MouseEventHandler }>(children) ? ( @@ -435,7 +441,7 @@ export function ContextMenu(props: ContextMenuProps) { onAction(key, position ?? undefined, returnFocusElement ?? undefined)} onClose={() => setPosition(null)} /> diff --git a/src/renderer/locales/de/messages.po b/src/renderer/locales/de/messages.po index 754e23642..ac8abd26b 100644 --- a/src/renderer/locales/de/messages.po +++ b/src/renderer/locales/de/messages.po @@ -1242,6 +1242,14 @@ msgstr "Alle Projekte" msgid "All sources" msgstr "Alle Quellen" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be archived." +msgstr "Alle Threads unter „Fertig“ werden archiviert." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be permanently deleted." +msgstr "Alle Threads unter „Fertig“ werden dauerhaft gelöscht." + #: src/renderer/views/MainView/parts/Sidebar/parts/useProjectMenu.tsx #: src/renderer/views/SettingsOverlay/parts/WorkspacesSettings.tsx msgid "All workspaces" @@ -1387,6 +1395,7 @@ msgid "Approved" msgstr "Genehmigt" #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Archive" msgstr "Archiv" @@ -1402,11 +1411,19 @@ msgstr "{0} archivieren" msgid "Archive All" msgstr "Alle archivieren" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Archive all done threads" +#~ msgstr "Alle erledigten Threads archivieren" + #: src/mobile/views/threadActionSurfaces.tsx #: src/mobile/views/threadContextMenus.tsx msgid "Archive all threads" msgstr "Alle Threads archivieren" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Archive done threads" +msgstr "Erledigte Threads archivieren" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Aktuellen Thread archivieren" @@ -2023,11 +2040,11 @@ msgstr "Ports konnten nicht geladen werden" msgid "Can't reach the remote server. Check that it is online, then reconnect it." msgstr "Der Remote-Server ist nicht erreichbar. Prüfe, ob er online ist, und verbinde ihn neu." -#. Dialog button: dismiss without deleting #: src/mobile/push/WebPushPermissionPrompt.tsx #: src/mobile/views/DesktopsView.tsx #: src/mobile/views/FilesView.tsx #: src/mobile/views/GitActionSheet.tsx +#: src/renderer/components/common/ConfirmationPopover.tsx #: src/renderer/components/common/ConfirmDialog.tsx #: src/renderer/components/experiment/ExperimentDraftTargets.tsx #: src/renderer/components/mcp/McpServerEditor.tsx @@ -2050,7 +2067,6 @@ msgstr "Der Remote-Server ist nicht erreichbar. Prüfe, ob er online ist, und ve #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx @@ -3007,6 +3023,16 @@ msgstr "Konfigurieren Sie den Server, den Poracode beim Start unterstützter Age msgid "Configured MCP servers" msgstr "Konfigurierte MCP-Server" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Confirm before deleting threads" +msgstr "Vor dem Löschen von Threads bestätigen" + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Confirm before deleting worktrees" +#~ msgstr "Vor dem Löschen von Worktrees bestätigen" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Conflict Resolver" @@ -3883,6 +3909,8 @@ msgstr "Delegieren Sie Aufgaben an andere KI-Agenten." #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -3921,10 +3949,18 @@ msgstr "{serverName} löschen" msgid "Delete <0>{0}? This cannot be undone." msgstr "<0>{0} löschen? Dies kann nicht rückgängig gemacht werden." +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Delete all done threads" +#~ msgstr "Alle erledigten Threads löschen" + #: src/renderer/components/common/BranchSelector/BranchSelector.tsx msgid "Delete branch?" msgstr "Zweig löschen?" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Delete done threads" +msgstr "Erledigte Threads löschen" + #: src/renderer/components/thread/ChatPane/parts/items/FileChange.tsx msgid "Delete file" msgstr "Datei löschen" @@ -3970,7 +4006,7 @@ msgstr "Thread löschen" msgid "Delete Thread" msgstr "Thread löschen" -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Delete thread?" msgstr "Thread löschen?" @@ -4295,7 +4331,7 @@ msgid "Docs" msgstr "Doku" #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Don't ask again" msgstr "Fragen Sie nicht noch einmal" @@ -4827,6 +4863,14 @@ msgstr "Der Experimentkandidat stammt nicht mehr von seinem eingefrorenen Basis- msgid "Experiment candidate thread ids must be unique" msgstr "Die Thread-IDs der Experimentkandidaten müssen eindeutig sein" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be archived." +msgstr "Experimentkandidaten bleiben erhalten; alle anderen Threads unter „Fertig“ werden archiviert." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be permanently deleted." +msgstr "Experimentkandidaten bleiben erhalten; alle anderen Threads unter „Fertig“ werden dauerhaft gelöscht." + #: src/renderer/i18n/sharedMessages.ts msgid "Experiment diff base must be a full commit hash" msgstr "Die Experiment-Diff-Basis muss ein vollständiger Commit-Hash sein" @@ -10878,6 +10922,16 @@ msgstr "{0} anzeigen" msgid "Show {label} circle in sidebar" msgstr "{label}-Ring in der Seitenleiste anzeigen" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Show a confirmation before deleting a thread together with its worktree." +#~ msgstr "Vor dem gemeinsamen Löschen eines Threads und seines Worktrees eine Bestätigung anzeigen." + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Show a confirmation before permanently deleting a thread." +msgstr "Vor dem endgültigen Löschen eines Threads eine Bestätigung anzeigen." + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Show a projectless Home scope for OS-level agent sessions." @@ -12331,9 +12385,22 @@ msgid "This system-wide shortcut is unavailable. Choose another key combination. msgstr "Diese systemweite Tastenkombination ist nicht verfügbar. Wähle eine andere Tastenkombination." #. placeholder {0}: props.worktreeBranch -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" -msgstr "Dieser Thread verwendet den Worktree <0>{0}. Auch das Worktree-Verzeichnis entfernen?" +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" +#~ msgstr "Dieser Thread verwendet den Worktree <0>{0}. Auch das Worktree-Verzeichnis entfernen?" + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This will permanently delete the thread and its worktree." +#~ msgstr "Dadurch werden der Thread und sein Worktree dauerhaft gelöscht." + +#. placeholder {0}: props.worktreeBranch +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread and remove worktree <0>{0}." +msgstr "Dadurch wird der Thread dauerhaft gelöscht und der Worktree <0>{0} entfernt." + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread." +msgstr "Dadurch wird der Thread dauerhaft gelöscht." #: src/renderer/views/GitHubActionsView/GitHubActionsView.tsx msgid "This workflow cannot be started manually." @@ -12356,10 +12423,10 @@ msgstr "Gedanke" msgid "Thread" msgstr "Thread" -#. Dialog button: delete the thread and remove its worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread + Worktree" -msgstr "Thread + Worktree" +#. Popover button: delete the thread and remove its worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread + Worktree" +#~ msgstr "Thread + Worktree" #: src/mobile/ThreadTitleRow.tsx msgid "Thread actions" @@ -12402,10 +12469,10 @@ msgstr "Optionen der Thread-Liste" msgid "Thread mode" msgstr "Thread-Modus" -#. Dialog button: delete the thread but keep the worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread Only" -msgstr "Nur Thread" +#. Popover button: delete the thread but keep the worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread Only" +#~ msgstr "Nur Thread" #: src/renderer/views/MainView/parts/SidebarHeaderControls.tsx #~ msgid "Thread sort order" diff --git a/src/renderer/locales/en/messages.po b/src/renderer/locales/en/messages.po index 6b66a830f..ab5d699d4 100644 --- a/src/renderer/locales/en/messages.po +++ b/src/renderer/locales/en/messages.po @@ -1242,6 +1242,14 @@ msgstr "All projects" msgid "All sources" msgstr "All sources" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be archived." +msgstr "All threads in Done will be archived." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be permanently deleted." +msgstr "All threads in Done will be permanently deleted." + #: src/renderer/views/MainView/parts/Sidebar/parts/useProjectMenu.tsx #: src/renderer/views/SettingsOverlay/parts/WorkspacesSettings.tsx msgid "All workspaces" @@ -1387,6 +1395,7 @@ msgid "Approved" msgstr "Approved" #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Archive" msgstr "Archive" @@ -1402,11 +1411,19 @@ msgstr "Archive {0}" msgid "Archive All" msgstr "Archive All" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Archive all done threads" +#~ msgstr "Archive all done threads" + #: src/mobile/views/threadActionSurfaces.tsx #: src/mobile/views/threadContextMenus.tsx msgid "Archive all threads" msgstr "Archive all threads" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Archive done threads" +msgstr "Archive done threads" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Archive the current thread" @@ -2023,11 +2040,11 @@ msgstr "Can't load ports" msgid "Can't reach the remote server. Check that it is online, then reconnect it." msgstr "Can't reach the remote server. Check that it is online, then reconnect it." -#. Dialog button: dismiss without deleting #: src/mobile/push/WebPushPermissionPrompt.tsx #: src/mobile/views/DesktopsView.tsx #: src/mobile/views/FilesView.tsx #: src/mobile/views/GitActionSheet.tsx +#: src/renderer/components/common/ConfirmationPopover.tsx #: src/renderer/components/common/ConfirmDialog.tsx #: src/renderer/components/experiment/ExperimentDraftTargets.tsx #: src/renderer/components/mcp/McpServerEditor.tsx @@ -2050,7 +2067,6 @@ msgstr "Can't reach the remote server. Check that it is online, then reconnect i #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx @@ -3007,6 +3023,16 @@ msgstr "Configure the server Poracode will add when supported agents start." msgid "Configured MCP servers" msgstr "Configured MCP servers" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Confirm before deleting threads" +msgstr "Confirm before deleting threads" + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Confirm before deleting worktrees" +#~ msgstr "Confirm before deleting worktrees" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Conflict Resolver" @@ -3883,6 +3909,8 @@ msgstr "Delegate work to other AI agents." #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -3921,10 +3949,18 @@ msgstr "Delete {serverName}" msgid "Delete <0>{0}? This cannot be undone." msgstr "Delete <0>{0}? This cannot be undone." +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Delete all done threads" +#~ msgstr "Delete all done threads" + #: src/renderer/components/common/BranchSelector/BranchSelector.tsx msgid "Delete branch?" msgstr "Delete branch?" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Delete done threads" +msgstr "Delete done threads" + #: src/renderer/components/thread/ChatPane/parts/items/FileChange.tsx msgid "Delete file" msgstr "Delete file" @@ -3970,7 +4006,7 @@ msgstr "Delete thread" msgid "Delete Thread" msgstr "Delete Thread" -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Delete thread?" msgstr "Delete thread?" @@ -4295,7 +4331,7 @@ msgid "Docs" msgstr "Docs" #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Don't ask again" msgstr "Don't ask again" @@ -4827,6 +4863,14 @@ msgstr "Experiment candidate no longer descends from its frozen base commit" msgid "Experiment candidate thread ids must be unique" msgstr "Experiment candidate thread ids must be unique" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be archived." +msgstr "Experiment candidates will remain; all other threads in Done will be archived." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be permanently deleted." +msgstr "Experiment candidates will remain; all other threads in Done will be permanently deleted." + #: src/renderer/i18n/sharedMessages.ts msgid "Experiment diff base must be a full commit hash" msgstr "Experiment diff base must be a full commit hash" @@ -10878,6 +10922,16 @@ msgstr "Show {0}" msgid "Show {label} circle in sidebar" msgstr "Show {label} circle in sidebar" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Show a confirmation before deleting a thread together with its worktree." +#~ msgstr "Show a confirmation before deleting a thread together with its worktree." + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Show a confirmation before permanently deleting a thread." +msgstr "Show a confirmation before permanently deleting a thread." + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Show a projectless Home scope for OS-level agent sessions." @@ -12331,9 +12385,22 @@ msgid "This system-wide shortcut is unavailable. Choose another key combination. msgstr "This system-wide shortcut is unavailable. Choose another key combination." #. placeholder {0}: props.worktreeBranch -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" -msgstr "This thread uses worktree <0>{0}. Also remove the worktree directory?" +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" +#~ msgstr "This thread uses worktree <0>{0}. Also remove the worktree directory?" + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This will permanently delete the thread and its worktree." +#~ msgstr "This will permanently delete the thread and its worktree." + +#. placeholder {0}: props.worktreeBranch +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread and remove worktree <0>{0}." +msgstr "This will permanently delete the thread and remove worktree <0>{0}." + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread." +msgstr "This will permanently delete the thread." #: src/renderer/views/GitHubActionsView/GitHubActionsView.tsx msgid "This workflow cannot be started manually." @@ -12356,10 +12423,10 @@ msgstr "Thought" msgid "Thread" msgstr "Thread" -#. Dialog button: delete the thread and remove its worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread + Worktree" -msgstr "Thread + Worktree" +#. Popover button: delete the thread and remove its worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread + Worktree" +#~ msgstr "Thread + Worktree" #: src/mobile/ThreadTitleRow.tsx msgid "Thread actions" @@ -12402,10 +12469,10 @@ msgstr "Thread list options" msgid "Thread mode" msgstr "Thread mode" -#. Dialog button: delete the thread but keep the worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread Only" -msgstr "Thread Only" +#. Popover button: delete the thread but keep the worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread Only" +#~ msgstr "Thread Only" #: src/renderer/views/MainView/parts/SidebarHeaderControls.tsx #~ msgid "Thread sort order" diff --git a/src/renderer/locales/es/messages.po b/src/renderer/locales/es/messages.po index d8a366944..403026666 100644 --- a/src/renderer/locales/es/messages.po +++ b/src/renderer/locales/es/messages.po @@ -1242,6 +1242,14 @@ msgstr "Todos los proyectos" msgid "All sources" msgstr "Todas las fuentes" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be archived." +msgstr "Todos los hilos de Listo se archivarán." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be permanently deleted." +msgstr "Todos los hilos de Listo se eliminarán permanentemente." + #: src/renderer/views/MainView/parts/Sidebar/parts/useProjectMenu.tsx #: src/renderer/views/SettingsOverlay/parts/WorkspacesSettings.tsx msgid "All workspaces" @@ -1387,6 +1395,7 @@ msgid "Approved" msgstr "Aprobado" #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Archive" msgstr "Archivar" @@ -1402,11 +1411,19 @@ msgstr "Archivar {0}" msgid "Archive All" msgstr "Archivar todo" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Archive all done threads" +#~ msgstr "Archivar todos los hilos completados" + #: src/mobile/views/threadActionSurfaces.tsx #: src/mobile/views/threadContextMenus.tsx msgid "Archive all threads" msgstr "Archivar todos los hilos" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Archive done threads" +msgstr "Archivar hilos completados" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Archivar el hilo actual" @@ -2023,11 +2040,11 @@ msgstr "No se pudieron cargar los puertos" msgid "Can't reach the remote server. Check that it is online, then reconnect it." msgstr "No se puede conectar con el servidor remoto. Comprueba que esté en línea y vuelve a conectarlo." -#. Dialog button: dismiss without deleting #: src/mobile/push/WebPushPermissionPrompt.tsx #: src/mobile/views/DesktopsView.tsx #: src/mobile/views/FilesView.tsx #: src/mobile/views/GitActionSheet.tsx +#: src/renderer/components/common/ConfirmationPopover.tsx #: src/renderer/components/common/ConfirmDialog.tsx #: src/renderer/components/experiment/ExperimentDraftTargets.tsx #: src/renderer/components/mcp/McpServerEditor.tsx @@ -2050,7 +2067,6 @@ msgstr "No se puede conectar con el servidor remoto. Comprueba que esté en lín #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx @@ -3007,6 +3023,16 @@ msgstr "Configura el servidor que Poracode añadirá cuando se inicien agentes c msgid "Configured MCP servers" msgstr "Servidores MCP configurados" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Confirm before deleting threads" +msgstr "Confirmar antes de eliminar hilos" + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Confirm before deleting worktrees" +#~ msgstr "Confirmar antes de eliminar worktrees" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Conflict Resolver" @@ -3883,6 +3909,8 @@ msgstr "Delega trabajo a otros agentes de IA." #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -3921,10 +3949,18 @@ msgstr "Eliminar {serverName}" msgid "Delete <0>{0}? This cannot be undone." msgstr "¿Eliminar <0>{0}? Esta acción no se puede deshacer." +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Delete all done threads" +#~ msgstr "Eliminar todos los hilos completados" + #: src/renderer/components/common/BranchSelector/BranchSelector.tsx msgid "Delete branch?" msgstr "¿Eliminar la rama?" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Delete done threads" +msgstr "Eliminar hilos completados" + #: src/renderer/components/thread/ChatPane/parts/items/FileChange.tsx msgid "Delete file" msgstr "Eliminar archivo" @@ -3970,7 +4006,7 @@ msgstr "Eliminar hilo" msgid "Delete Thread" msgstr "Eliminar hilo" -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Delete thread?" msgstr "¿Eliminar el hilo?" @@ -4295,7 +4331,7 @@ msgid "Docs" msgstr "Documentación" #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Don't ask again" msgstr "No volver a preguntar" @@ -4827,6 +4863,14 @@ msgstr "El candidato del experimento ya no desciende de su commit base inmoviliz msgid "Experiment candidate thread ids must be unique" msgstr "Los identificadores de hilo de los candidatos del experimento deben ser únicos" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be archived." +msgstr "Los candidatos del experimento permanecerán; todos los demás hilos de Listo se archivarán." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be permanently deleted." +msgstr "Los candidatos del experimento permanecerán; todos los demás hilos de Listo se eliminarán permanentemente." + #: src/renderer/i18n/sharedMessages.ts msgid "Experiment diff base must be a full commit hash" msgstr "La base del diff del experimento debe ser un hash de commit completo" @@ -10878,6 +10922,16 @@ msgstr "Mostrar {0}" msgid "Show {label} circle in sidebar" msgstr "Mostrar el círculo de {label} en la barra lateral" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Show a confirmation before deleting a thread together with its worktree." +#~ msgstr "Mostrar una confirmación antes de eliminar un hilo junto con su worktree." + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Show a confirmation before permanently deleting a thread." +msgstr "Mostrar una confirmación antes de eliminar permanentemente un hilo." + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Show a projectless Home scope for OS-level agent sessions." @@ -12331,9 +12385,22 @@ msgid "This system-wide shortcut is unavailable. Choose another key combination. msgstr "Este atajo global no está disponible. Elige otra combinación de teclas." #. placeholder {0}: props.worktreeBranch -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" -msgstr "Este hilo usa el worktree <0>{0}. ¿Eliminar también el directorio del worktree?" +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" +#~ msgstr "Este hilo usa el worktree <0>{0}. ¿Eliminar también el directorio del worktree?" + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This will permanently delete the thread and its worktree." +#~ msgstr "Esto eliminará permanentemente el hilo y su worktree." + +#. placeholder {0}: props.worktreeBranch +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread and remove worktree <0>{0}." +msgstr "Esto eliminará permanentemente el hilo y quitará el worktree <0>{0}." + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread." +msgstr "Esto eliminará permanentemente el hilo." #: src/renderer/views/GitHubActionsView/GitHubActionsView.tsx msgid "This workflow cannot be started manually." @@ -12356,10 +12423,10 @@ msgstr "Pensamiento" msgid "Thread" msgstr "Hilo" -#. Dialog button: delete the thread and remove its worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread + Worktree" -msgstr "Hilo + worktree" +#. Popover button: delete the thread and remove its worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread + Worktree" +#~ msgstr "Hilo + worktree" #: src/mobile/ThreadTitleRow.tsx msgid "Thread actions" @@ -12402,10 +12469,10 @@ msgstr "Opciones de la lista de hilos" msgid "Thread mode" msgstr "Modo del hilo" -#. Dialog button: delete the thread but keep the worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread Only" -msgstr "Solo el hilo" +#. Popover button: delete the thread but keep the worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread Only" +#~ msgstr "Solo el hilo" #: src/renderer/views/MainView/parts/SidebarHeaderControls.tsx #~ msgid "Thread sort order" diff --git a/src/renderer/locales/fr/messages.po b/src/renderer/locales/fr/messages.po index 6ff81e876..b0c20b913 100644 --- a/src/renderer/locales/fr/messages.po +++ b/src/renderer/locales/fr/messages.po @@ -1242,6 +1242,14 @@ msgstr "Tous les projets" msgid "All sources" msgstr "Toutes les sources" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be archived." +msgstr "Tous les fils de la section Terminé seront archivés." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be permanently deleted." +msgstr "Tous les fils de la section Terminé seront définitivement supprimés." + #: src/renderer/views/MainView/parts/Sidebar/parts/useProjectMenu.tsx #: src/renderer/views/SettingsOverlay/parts/WorkspacesSettings.tsx msgid "All workspaces" @@ -1387,6 +1395,7 @@ msgid "Approved" msgstr "Approuvé" #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Archive" msgstr "Archiver" @@ -1402,11 +1411,19 @@ msgstr "Archiver {0}" msgid "Archive All" msgstr "Archiver tout" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Archive all done threads" +#~ msgstr "Archiver tous les fils terminés" + #: src/mobile/views/threadActionSurfaces.tsx #: src/mobile/views/threadContextMenus.tsx msgid "Archive all threads" msgstr "Archiver tous les fils" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Archive done threads" +msgstr "Archiver les fils terminés" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Archiver le fil de discussion actuel" @@ -2023,11 +2040,11 @@ msgstr "Impossible de charger les ports" msgid "Can't reach the remote server. Check that it is online, then reconnect it." msgstr "Serveur distant inaccessible. Vérifiez qu'il est en ligne, puis reconnectez-le." -#. Dialog button: dismiss without deleting #: src/mobile/push/WebPushPermissionPrompt.tsx #: src/mobile/views/DesktopsView.tsx #: src/mobile/views/FilesView.tsx #: src/mobile/views/GitActionSheet.tsx +#: src/renderer/components/common/ConfirmationPopover.tsx #: src/renderer/components/common/ConfirmDialog.tsx #: src/renderer/components/experiment/ExperimentDraftTargets.tsx #: src/renderer/components/mcp/McpServerEditor.tsx @@ -2050,7 +2067,6 @@ msgstr "Serveur distant inaccessible. Vérifiez qu'il est en ligne, puis reconne #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx @@ -3007,6 +3023,16 @@ msgstr "Configurez le serveur que Poracode ajoutera au démarrage des agents com msgid "Configured MCP servers" msgstr "Serveurs MCP configurés" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Confirm before deleting threads" +msgstr "Confirmer avant de supprimer les fils" + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Confirm before deleting worktrees" +#~ msgstr "Confirmer avant de supprimer les worktrees" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Conflict Resolver" @@ -3883,6 +3909,8 @@ msgstr "Déléguez le travail à d’autres agents IA." #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -3921,10 +3949,18 @@ msgstr "Supprimer {serverName}" msgid "Delete <0>{0}? This cannot be undone." msgstr "Supprimer <0>{0} ? Cette action est irréversible." +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Delete all done threads" +#~ msgstr "Supprimer tous les fils terminés" + #: src/renderer/components/common/BranchSelector/BranchSelector.tsx msgid "Delete branch?" msgstr "Supprimer la branche ?" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Delete done threads" +msgstr "Supprimer les fils terminés" + #: src/renderer/components/thread/ChatPane/parts/items/FileChange.tsx msgid "Delete file" msgstr "Supprimer le fichier" @@ -3970,7 +4006,7 @@ msgstr "Supprimer le fil de discussion" msgid "Delete Thread" msgstr "Supprimer le fil de discussion" -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Delete thread?" msgstr "Supprimer le fil ?" @@ -4295,7 +4331,7 @@ msgid "Docs" msgstr "Docs" #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Don't ask again" msgstr "Ne plus demander" @@ -4827,6 +4863,14 @@ msgstr "Le candidat de l'expérience ne descend plus de son commit de base figé msgid "Experiment candidate thread ids must be unique" msgstr "Les identifiants de fil des candidats de l'expérience doivent être uniques" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be archived." +msgstr "Les candidats de l’expérience seront conservés ; tous les autres fils de la section Terminé seront archivés." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be permanently deleted." +msgstr "Les candidats de l’expérience seront conservés ; tous les autres fils de la section Terminé seront définitivement supprimés." + #: src/renderer/i18n/sharedMessages.ts msgid "Experiment diff base must be a full commit hash" msgstr "La base du diff de l'expérience doit être un hash de commit complet" @@ -10877,6 +10921,16 @@ msgstr "Afficher {0}" msgid "Show {label} circle in sidebar" msgstr "Afficher le cercle de {label} dans la barre latérale" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Show a confirmation before deleting a thread together with its worktree." +#~ msgstr "Afficher une confirmation avant de supprimer un fil avec son worktree." + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Show a confirmation before permanently deleting a thread." +msgstr "Afficher une confirmation avant de supprimer définitivement un fil." + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Show a projectless Home scope for OS-level agent sessions." @@ -12330,9 +12384,22 @@ msgid "This system-wide shortcut is unavailable. Choose another key combination. msgstr "Ce raccourci système n’est pas disponible. Choisissez une autre combinaison de touches." #. placeholder {0}: props.worktreeBranch -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" -msgstr "Ce fil de discussion utilise l'arbre de travail <0>{0}. Supprimer également le répertoire de l'arbre de travail ?" +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" +#~ msgstr "Ce fil de discussion utilise l'arbre de travail <0>{0}. Supprimer également le répertoire de l'arbre de travail ?" + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This will permanently delete the thread and its worktree." +#~ msgstr "Cela supprimera définitivement le fil et son worktree." + +#. placeholder {0}: props.worktreeBranch +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread and remove worktree <0>{0}." +msgstr "Cela supprimera définitivement le fil et retirera le worktree <0>{0}." + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread." +msgstr "Cela supprimera définitivement le fil." #: src/renderer/views/GitHubActionsView/GitHubActionsView.tsx msgid "This workflow cannot be started manually." @@ -12355,10 +12422,10 @@ msgstr "Pensée" msgid "Thread" msgstr "Fil de discussion" -#. Dialog button: delete the thread and remove its worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread + Worktree" -msgstr "Fil de discussion + Arbre de travail" +#. Popover button: delete the thread and remove its worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread + Worktree" +#~ msgstr "Fil de discussion + Arbre de travail" #: src/mobile/ThreadTitleRow.tsx msgid "Thread actions" @@ -12401,10 +12468,10 @@ msgstr "Options de la liste des fils" msgid "Thread mode" msgstr "Mode fil de discussion" -#. Dialog button: delete the thread but keep the worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread Only" -msgstr "Fil de discussion uniquement" +#. Popover button: delete the thread but keep the worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread Only" +#~ msgstr "Fil de discussion uniquement" #: src/renderer/views/MainView/parts/SidebarHeaderControls.tsx #~ msgid "Thread sort order" diff --git a/src/renderer/locales/ja/messages.po b/src/renderer/locales/ja/messages.po index 04463b7d9..837ff8673 100644 --- a/src/renderer/locales/ja/messages.po +++ b/src/renderer/locales/ja/messages.po @@ -1241,6 +1241,14 @@ msgstr "すべてのプロジェクト" msgid "All sources" msgstr "すべてのソース" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be archived." +msgstr "「完了」のすべてのスレッドがアーカイブされます。" + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be permanently deleted." +msgstr "「完了」のすべてのスレッドが完全に削除されます。" + #: src/renderer/views/MainView/parts/Sidebar/parts/useProjectMenu.tsx #: src/renderer/views/SettingsOverlay/parts/WorkspacesSettings.tsx msgid "All workspaces" @@ -1386,6 +1394,7 @@ msgid "Approved" msgstr "承認済み" #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Archive" msgstr "アーカイブ" @@ -1401,11 +1410,19 @@ msgstr "アーカイブ{0}" msgid "Archive All" msgstr "すべてをアーカイブする" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Archive all done threads" +#~ msgstr "完了したスレッドをすべてアーカイブ" + #: src/mobile/views/threadActionSurfaces.tsx #: src/mobile/views/threadContextMenus.tsx msgid "Archive all threads" msgstr "すべてのスレッドをアーカイブ" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Archive done threads" +msgstr "完了したスレッドをアーカイブ" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "現在のスレッドをアーカイブ" @@ -2022,11 +2039,11 @@ msgstr "ポートを読み込めません" msgid "Can't reach the remote server. Check that it is online, then reconnect it." msgstr "リモートサーバーに接続できません。オンラインであることを確認してから再接続してください。" -#. Dialog button: dismiss without deleting #: src/mobile/push/WebPushPermissionPrompt.tsx #: src/mobile/views/DesktopsView.tsx #: src/mobile/views/FilesView.tsx #: src/mobile/views/GitActionSheet.tsx +#: src/renderer/components/common/ConfirmationPopover.tsx #: src/renderer/components/common/ConfirmDialog.tsx #: src/renderer/components/experiment/ExperimentDraftTargets.tsx #: src/renderer/components/mcp/McpServerEditor.tsx @@ -2049,7 +2066,6 @@ msgstr "リモートサーバーに接続できません。オンラインであ #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx @@ -3006,6 +3022,16 @@ msgstr "対応エージェントの起動時にPoracodeが追加するサーバ msgid "Configured MCP servers" msgstr "設定済みのMCPサーバー" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Confirm before deleting threads" +msgstr "スレッドを削除する前に確認" + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Confirm before deleting worktrees" +#~ msgstr "ワークツリーを削除する前に確認" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Conflict Resolver" @@ -3882,6 +3908,8 @@ msgstr "他の AI エージェントに作業を委任します。" #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -3920,10 +3948,18 @@ msgstr "{serverName}を削除" msgid "Delete <0>{0}? This cannot be undone." msgstr "<0>{0} を削除しますか?この操作は元に戻せません。" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Delete all done threads" +#~ msgstr "完了したスレッドをすべて削除" + #: src/renderer/components/common/BranchSelector/BranchSelector.tsx msgid "Delete branch?" msgstr "ブランチを削除しますか?" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Delete done threads" +msgstr "完了したスレッドを削除" + #: src/renderer/components/thread/ChatPane/parts/items/FileChange.tsx msgid "Delete file" msgstr "ファイルの削除" @@ -3969,7 +4005,7 @@ msgstr "スレッドの削除" msgid "Delete Thread" msgstr "スレッドの削除" -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Delete thread?" msgstr "スレッドを削除しますか?" @@ -4294,7 +4330,7 @@ msgid "Docs" msgstr "ドキュメント" #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Don't ask again" msgstr "今後表示しない" @@ -4826,6 +4862,14 @@ msgstr "実験候補は固定されたベースコミットの子孫ではなく msgid "Experiment candidate thread ids must be unique" msgstr "実験候補のスレッド ID は一意である必要があります" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be archived." +msgstr "実験候補は残り、「完了」のその他のスレッドはすべてアーカイブされます。" + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be permanently deleted." +msgstr "実験候補は残り、「完了」のその他のスレッドはすべて完全に削除されます。" + #: src/renderer/i18n/sharedMessages.ts msgid "Experiment diff base must be a full commit hash" msgstr "実験の差分ベースには完全なコミットハッシュが必要です" @@ -10876,6 +10920,16 @@ msgstr "{0}を表示" msgid "Show {label} circle in sidebar" msgstr "サイドバーで {label} のリングを表示する" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Show a confirmation before deleting a thread together with its worktree." +#~ msgstr "スレッドとそのワークツリーをまとめて削除する前に確認を表示します。" + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Show a confirmation before permanently deleting a thread." +msgstr "スレッドを完全に削除する前に確認を表示します。" + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Show a projectless Home scope for OS-level agent sessions." @@ -12329,9 +12383,22 @@ msgid "This system-wide shortcut is unavailable. Choose another key combination. msgstr "このシステム全体のショートカットは使用できません。別のキーの組み合わせを選択してください。" #. placeholder {0}: props.worktreeBranch -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" -msgstr "このスレッドはワークツリー <0>{0} を使用します。ワークツリーディレクトリも削除しますか?" +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" +#~ msgstr "このスレッドはワークツリー <0>{0} を使用します。ワークツリーディレクトリも削除しますか?" + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This will permanently delete the thread and its worktree." +#~ msgstr "スレッドとそのワークツリーを完全に削除します。" + +#. placeholder {0}: props.worktreeBranch +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread and remove worktree <0>{0}." +msgstr "スレッドを完全に削除し、ワークツリー <0>{0} を削除します。" + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread." +msgstr "スレッドを完全に削除します。" #: src/renderer/views/GitHubActionsView/GitHubActionsView.tsx msgid "This workflow cannot be started manually." @@ -12354,10 +12421,10 @@ msgstr "思考" msgid "Thread" msgstr "スレッド" -#. Dialog button: delete the thread and remove its worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread + Worktree" -msgstr "スレッド + ワークツリー" +#. Popover button: delete the thread and remove its worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread + Worktree" +#~ msgstr "スレッド + ワークツリー" #: src/mobile/ThreadTitleRow.tsx msgid "Thread actions" @@ -12400,10 +12467,10 @@ msgstr "スレッドリストのオプション" msgid "Thread mode" msgstr "スレッドモード" -#. Dialog button: delete the thread but keep the worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread Only" -msgstr "スレッドのみ" +#. Popover button: delete the thread but keep the worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread Only" +#~ msgstr "スレッドのみ" #: src/renderer/views/MainView/parts/SidebarHeaderControls.tsx #~ msgid "Thread sort order" diff --git a/src/renderer/locales/ko/messages.po b/src/renderer/locales/ko/messages.po index 5bcbd7c69..164ffac54 100644 --- a/src/renderer/locales/ko/messages.po +++ b/src/renderer/locales/ko/messages.po @@ -1242,6 +1242,14 @@ msgstr "모든 프로젝트" msgid "All sources" msgstr "모든 소스" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be archived." +msgstr "완료 섹션의 모든 스레드가 보관됩니다." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be permanently deleted." +msgstr "완료 섹션의 모든 스레드가 영구적으로 삭제됩니다." + #: src/renderer/views/MainView/parts/Sidebar/parts/useProjectMenu.tsx #: src/renderer/views/SettingsOverlay/parts/WorkspacesSettings.tsx msgid "All workspaces" @@ -1387,6 +1395,7 @@ msgid "Approved" msgstr "승인됨" #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Archive" msgstr "아카이브" @@ -1402,11 +1411,19 @@ msgstr "{0} 보관" msgid "Archive All" msgstr "모두 보관" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Archive all done threads" +#~ msgstr "완료된 모든 스레드 보관" + #: src/mobile/views/threadActionSurfaces.tsx #: src/mobile/views/threadContextMenus.tsx msgid "Archive all threads" msgstr "모든 스레드 보관" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Archive done threads" +msgstr "완료된 스레드 보관" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "현재 스레드 보관" @@ -2023,11 +2040,11 @@ msgstr "포트를 불러올 수 없습니다" msgid "Can't reach the remote server. Check that it is online, then reconnect it." msgstr "원격 서버에 연결할 수 없습니다. 온라인 상태인지 확인한 후 다시 연결하세요." -#. Dialog button: dismiss without deleting #: src/mobile/push/WebPushPermissionPrompt.tsx #: src/mobile/views/DesktopsView.tsx #: src/mobile/views/FilesView.tsx #: src/mobile/views/GitActionSheet.tsx +#: src/renderer/components/common/ConfirmationPopover.tsx #: src/renderer/components/common/ConfirmDialog.tsx #: src/renderer/components/experiment/ExperimentDraftTargets.tsx #: src/renderer/components/mcp/McpServerEditor.tsx @@ -2050,7 +2067,6 @@ msgstr "원격 서버에 연결할 수 없습니다. 온라인 상태인지 확 #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx @@ -3007,6 +3023,16 @@ msgstr "지원되는 에이전트가 시작될 때 Poracode에서 추가할 서 msgid "Configured MCP servers" msgstr "구성된 MCP 서버" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Confirm before deleting threads" +msgstr "스레드 삭제 전 확인" + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Confirm before deleting worktrees" +#~ msgstr "워크트리 삭제 전 확인" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Conflict Resolver" @@ -3883,6 +3909,8 @@ msgstr "다른 AI 에이전트에게 작업을 위임합니다." #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -3921,10 +3949,18 @@ msgstr "{serverName} 삭제" msgid "Delete <0>{0}? This cannot be undone." msgstr "<0>{0}을(를) 삭제할까요? 이 작업은 되돌릴 수 없습니다." +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Delete all done threads" +#~ msgstr "완료된 모든 스레드 삭제" + #: src/renderer/components/common/BranchSelector/BranchSelector.tsx msgid "Delete branch?" msgstr "브랜치를 삭제하시겠습니까?" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Delete done threads" +msgstr "완료된 스레드 삭제" + #: src/renderer/components/thread/ChatPane/parts/items/FileChange.tsx msgid "Delete file" msgstr "파일 삭제" @@ -3970,7 +4006,7 @@ msgstr "스레드 삭제" msgid "Delete Thread" msgstr "스레드 삭제" -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Delete thread?" msgstr "스레드를 삭제하시겠습니까?" @@ -4295,7 +4331,7 @@ msgid "Docs" msgstr "문서" #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Don't ask again" msgstr "다시 묻지 마세요" @@ -4827,6 +4863,14 @@ msgstr "실험 후보가 더 이상 고정된 기본 커밋의 하위 항목이 msgid "Experiment candidate thread ids must be unique" msgstr "실험 후보 스레드 ID는 고유해야 합니다" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be archived." +msgstr "실험 후보는 유지되며 완료 섹션의 다른 모든 스레드는 보관됩니다." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be permanently deleted." +msgstr "실험 후보는 유지되며 완료 섹션의 다른 모든 스레드는 영구적으로 삭제됩니다." + #: src/renderer/i18n/sharedMessages.ts msgid "Experiment diff base must be a full commit hash" msgstr "실험 차이점의 기준은 전체 커밋 해시여야 합니다" @@ -10878,6 +10922,16 @@ msgstr "{0} 표시" msgid "Show {label} circle in sidebar" msgstr "사이드바에 {label} 원 표시" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Show a confirmation before deleting a thread together with its worktree." +#~ msgstr "스레드와 해당 워크트리를 함께 삭제하기 전에 확인을 표시합니다." + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Show a confirmation before permanently deleting a thread." +msgstr "스레드를 영구적으로 삭제하기 전에 확인을 표시합니다." + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Show a projectless Home scope for OS-level agent sessions." @@ -12331,9 +12385,22 @@ msgid "This system-wide shortcut is unavailable. Choose another key combination. msgstr "이 시스템 전역 단축키를 사용할 수 없습니다. 다른 키 조합을 선택하세요." #. placeholder {0}: props.worktreeBranch -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" -msgstr "이 스레드는 작업 트리 <0>{0}을 사용합니다. 작업 트리 디렉터리도 제거하시겠습니까?" +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" +#~ msgstr "이 스레드는 작업 트리 <0>{0}을 사용합니다. 작업 트리 디렉터리도 제거하시겠습니까?" + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This will permanently delete the thread and its worktree." +#~ msgstr "스레드와 해당 워크트리가 영구적으로 삭제됩니다." + +#. placeholder {0}: props.worktreeBranch +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread and remove worktree <0>{0}." +msgstr "스레드를 영구적으로 삭제하고 워크트리 <0>{0}을(를) 제거합니다." + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread." +msgstr "스레드가 영구적으로 삭제됩니다." #: src/renderer/views/GitHubActionsView/GitHubActionsView.tsx msgid "This workflow cannot be started manually." @@ -12356,10 +12423,10 @@ msgstr "생각" msgid "Thread" msgstr "스레드" -#. Dialog button: delete the thread and remove its worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread + Worktree" -msgstr "스레드 + 작업 트리" +#. Popover button: delete the thread and remove its worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread + Worktree" +#~ msgstr "스레드 + 작업 트리" #: src/mobile/ThreadTitleRow.tsx msgid "Thread actions" @@ -12402,10 +12469,10 @@ msgstr "스레드 목록 옵션" msgid "Thread mode" msgstr "스레드 모드" -#. Dialog button: delete the thread but keep the worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread Only" -msgstr "스레드만" +#. Popover button: delete the thread but keep the worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread Only" +#~ msgstr "스레드만" #: src/renderer/views/MainView/parts/SidebarHeaderControls.tsx #~ msgid "Thread sort order" diff --git a/src/renderer/locales/pl/messages.po b/src/renderer/locales/pl/messages.po index d4dcde057..59d4c7a39 100644 --- a/src/renderer/locales/pl/messages.po +++ b/src/renderer/locales/pl/messages.po @@ -1242,6 +1242,14 @@ msgstr "Wszystkie projekty" msgid "All sources" msgstr "Wszystkie źródła" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be archived." +msgstr "Wszystkie wątki w sekcji Gotowe zostaną zarchiwizowane." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be permanently deleted." +msgstr "Wszystkie wątki w sekcji Gotowe zostaną trwale usunięte." + #: src/renderer/views/MainView/parts/Sidebar/parts/useProjectMenu.tsx #: src/renderer/views/SettingsOverlay/parts/WorkspacesSettings.tsx msgid "All workspaces" @@ -1387,6 +1395,7 @@ msgid "Approved" msgstr "Zatwierdzone" #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Archive" msgstr "Archiwum" @@ -1402,11 +1411,19 @@ msgstr "Archiwum {0}" msgid "Archive All" msgstr "Archiwizuj wszystko" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Archive all done threads" +#~ msgstr "Zarchiwizuj wszystkie ukończone wątki" + #: src/mobile/views/threadActionSurfaces.tsx #: src/mobile/views/threadContextMenus.tsx msgid "Archive all threads" msgstr "Archiwizuj wszystkie wątki" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Archive done threads" +msgstr "Zarchiwizuj ukończone wątki" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Archiwizuj bieżący wątek" @@ -2023,11 +2040,11 @@ msgstr "Nie można wczytać portów" msgid "Can't reach the remote server. Check that it is online, then reconnect it." msgstr "Nie można połączyć się z serwerem zdalnym. Sprawdź, czy jest online, i połącz ponownie." -#. Dialog button: dismiss without deleting #: src/mobile/push/WebPushPermissionPrompt.tsx #: src/mobile/views/DesktopsView.tsx #: src/mobile/views/FilesView.tsx #: src/mobile/views/GitActionSheet.tsx +#: src/renderer/components/common/ConfirmationPopover.tsx #: src/renderer/components/common/ConfirmDialog.tsx #: src/renderer/components/experiment/ExperimentDraftTargets.tsx #: src/renderer/components/mcp/McpServerEditor.tsx @@ -2050,7 +2067,6 @@ msgstr "Nie można połączyć się z serwerem zdalnym. Sprawdź, czy jest onlin #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx @@ -3007,6 +3023,16 @@ msgstr "Skonfiguruj serwer, który Poracode doda podczas uruchamiania obsługiwa msgid "Configured MCP servers" msgstr "Skonfigurowane serwery MCP" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Confirm before deleting threads" +msgstr "Potwierdzaj przed usunięciem wątków" + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Confirm before deleting worktrees" +#~ msgstr "Potwierdzaj przed usunięciem drzew roboczych" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Conflict Resolver" @@ -3883,6 +3909,8 @@ msgstr "Deleguj zadania innym agentom AI." #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -3921,10 +3949,18 @@ msgstr "Usuń {serverName}" msgid "Delete <0>{0}? This cannot be undone." msgstr "Usunąć <0>{0}? Tej operacji nie można cofnąć." +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Delete all done threads" +#~ msgstr "Usuń wszystkie ukończone wątki" + #: src/renderer/components/common/BranchSelector/BranchSelector.tsx msgid "Delete branch?" msgstr "Usunąć gałąź?" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Delete done threads" +msgstr "Usuń ukończone wątki" + #: src/renderer/components/thread/ChatPane/parts/items/FileChange.tsx msgid "Delete file" msgstr "Usuń plik" @@ -3970,7 +4006,7 @@ msgstr "Usuń wątek" msgid "Delete Thread" msgstr "Usuń wątek" -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Delete thread?" msgstr "Usunąć wątek?" @@ -4295,7 +4331,7 @@ msgid "Docs" msgstr "Dokumentacja" #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Don't ask again" msgstr "Nie pytaj ponownie" @@ -4827,6 +4863,14 @@ msgstr "Kandydat eksperymentu nie pochodzi już od zamrożonego commita bazowego msgid "Experiment candidate thread ids must be unique" msgstr "Identyfikatory wątków kandydatów eksperymentu muszą być unikalne" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be archived." +msgstr "Kandydaci eksperymentu pozostaną; wszystkie pozostałe wątki w sekcji Gotowe zostaną zarchiwizowane." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be permanently deleted." +msgstr "Kandydaci eksperymentu pozostaną; wszystkie pozostałe wątki w sekcji Gotowe zostaną trwale usunięte." + #: src/renderer/i18n/sharedMessages.ts msgid "Experiment diff base must be a full commit hash" msgstr "Baza różnic eksperymentu musi być pełnym skrótem commita" @@ -10878,6 +10922,16 @@ msgstr "Pokaż {0}" msgid "Show {label} circle in sidebar" msgstr "Pokaż krąg {label} na pasku bocznym" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Show a confirmation before deleting a thread together with its worktree." +#~ msgstr "Wyświetl potwierdzenie przed usunięciem wątku wraz z jego drzewem roboczym." + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Show a confirmation before permanently deleting a thread." +msgstr "Wyświetl potwierdzenie przed trwałym usunięciem wątku." + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Show a projectless Home scope for OS-level agent sessions." @@ -12331,9 +12385,22 @@ msgid "This system-wide shortcut is unavailable. Choose another key combination. msgstr "Ten skrót globalny jest niedostępny. Wybierz inną kombinację klawiszy." #. placeholder {0}: props.worktreeBranch -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" -msgstr "W tym wątku używane jest drzewo robocze <0>{0}. Usunąć także katalog drzewa roboczego?" +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" +#~ msgstr "W tym wątku używane jest drzewo robocze <0>{0}. Usunąć także katalog drzewa roboczego?" + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This will permanently delete the thread and its worktree." +#~ msgstr "Spowoduje to trwałe usunięcie wątku i jego drzewa roboczego." + +#. placeholder {0}: props.worktreeBranch +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread and remove worktree <0>{0}." +msgstr "Spowoduje to trwałe usunięcie wątku i drzewa roboczego <0>{0}." + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread." +msgstr "Spowoduje to trwałe usunięcie wątku." #: src/renderer/views/GitHubActionsView/GitHubActionsView.tsx msgid "This workflow cannot be started manually." @@ -12356,10 +12423,10 @@ msgstr "Myśl" msgid "Thread" msgstr "Wątek" -#. Dialog button: delete the thread and remove its worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread + Worktree" -msgstr "Wątek + drzewo robocze" +#. Popover button: delete the thread and remove its worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread + Worktree" +#~ msgstr "Wątek + drzewo robocze" #: src/mobile/ThreadTitleRow.tsx msgid "Thread actions" @@ -12402,10 +12469,10 @@ msgstr "Opcje listy wątków" msgid "Thread mode" msgstr "Tryb wątku" -#. Dialog button: delete the thread but keep the worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread Only" -msgstr "Tylko wątek" +#. Popover button: delete the thread but keep the worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread Only" +#~ msgstr "Tylko wątek" #: src/renderer/views/MainView/parts/SidebarHeaderControls.tsx #~ msgid "Thread sort order" diff --git a/src/renderer/locales/pt-BR/messages.po b/src/renderer/locales/pt-BR/messages.po index 76333874d..516eb9e70 100644 --- a/src/renderer/locales/pt-BR/messages.po +++ b/src/renderer/locales/pt-BR/messages.po @@ -1242,6 +1242,14 @@ msgstr "Todos os projetos" msgid "All sources" msgstr "Todas as fontes" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be archived." +msgstr "Todas as threads em Concluído serão arquivadas." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be permanently deleted." +msgstr "Todas as threads em Concluído serão excluídas permanentemente." + #: src/renderer/views/MainView/parts/Sidebar/parts/useProjectMenu.tsx #: src/renderer/views/SettingsOverlay/parts/WorkspacesSettings.tsx msgid "All workspaces" @@ -1387,6 +1395,7 @@ msgid "Approved" msgstr "Aprovado" #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Archive" msgstr "Arquivar" @@ -1402,11 +1411,19 @@ msgstr "Arquivar {0}" msgid "Archive All" msgstr "Arquivar tudo" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Archive all done threads" +#~ msgstr "Arquivar todas as threads concluídas" + #: src/mobile/views/threadActionSurfaces.tsx #: src/mobile/views/threadContextMenus.tsx msgid "Archive all threads" msgstr "Arquivar todas as threads" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Archive done threads" +msgstr "Arquivar threads concluídas" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Arquivar o tópico atual" @@ -2023,11 +2040,11 @@ msgstr "Não foi possível carregar as portas" msgid "Can't reach the remote server. Check that it is online, then reconnect it." msgstr "Não foi possível acessar o servidor remoto. Verifique se ele está online e reconecte-o." -#. Dialog button: dismiss without deleting #: src/mobile/push/WebPushPermissionPrompt.tsx #: src/mobile/views/DesktopsView.tsx #: src/mobile/views/FilesView.tsx #: src/mobile/views/GitActionSheet.tsx +#: src/renderer/components/common/ConfirmationPopover.tsx #: src/renderer/components/common/ConfirmDialog.tsx #: src/renderer/components/experiment/ExperimentDraftTargets.tsx #: src/renderer/components/mcp/McpServerEditor.tsx @@ -2050,7 +2067,6 @@ msgstr "Não foi possível acessar o servidor remoto. Verifique se ele está onl #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx @@ -3007,6 +3023,16 @@ msgstr "Configure o servidor que o Poracode adicionará quando os agentes compat msgid "Configured MCP servers" msgstr "Servidores MCP configurados" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Confirm before deleting threads" +msgstr "Confirmar antes de excluir threads" + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Confirm before deleting worktrees" +#~ msgstr "Confirmar antes de excluir worktrees" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Conflict Resolver" @@ -3883,6 +3909,8 @@ msgstr "Delegue o trabalho a outros agentes de IA." #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -3921,10 +3949,18 @@ msgstr "Excluir {serverName}" msgid "Delete <0>{0}? This cannot be undone." msgstr "Excluir <0>{0}? Isso não pode ser desfeito." +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Delete all done threads" +#~ msgstr "Excluir todas as threads concluídas" + #: src/renderer/components/common/BranchSelector/BranchSelector.tsx msgid "Delete branch?" msgstr "Excluir branch?" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Delete done threads" +msgstr "Excluir threads concluídas" + #: src/renderer/components/thread/ChatPane/parts/items/FileChange.tsx msgid "Delete file" msgstr "Excluir arquivo" @@ -3970,7 +4006,7 @@ msgstr "Excluir tópico" msgid "Delete Thread" msgstr "Excluir tópico" -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Delete thread?" msgstr "Excluir tópico?" @@ -4295,7 +4331,7 @@ msgid "Docs" msgstr "Documentação" #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Don't ask again" msgstr "Não pergunte novamente" @@ -4827,6 +4863,14 @@ msgstr "O candidato do experimento não descende mais do commit base congelado" msgid "Experiment candidate thread ids must be unique" msgstr "Os IDs dos tópicos dos candidatos do experimento devem ser exclusivos" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be archived." +msgstr "Os candidatos do experimento permanecerão; todas as outras threads em Concluído serão arquivadas." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be permanently deleted." +msgstr "Os candidatos do experimento permanecerão; todas as outras threads em Concluído serão excluídas permanentemente." + #: src/renderer/i18n/sharedMessages.ts msgid "Experiment diff base must be a full commit hash" msgstr "A base do diff do experimento deve ser um hash completo do commit" @@ -10878,6 +10922,16 @@ msgstr "Mostrar {0}" msgid "Show {label} circle in sidebar" msgstr "Mostrar círculo de {label} na barra lateral" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Show a confirmation before deleting a thread together with its worktree." +#~ msgstr "Mostrar uma confirmação antes de excluir uma thread junto com sua worktree." + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Show a confirmation before permanently deleting a thread." +msgstr "Mostrar uma confirmação antes de excluir permanentemente uma thread." + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Show a projectless Home scope for OS-level agent sessions." @@ -12331,9 +12385,22 @@ msgid "This system-wide shortcut is unavailable. Choose another key combination. msgstr "Este atalho global não está disponível. Escolha outra combinação de teclas." #. placeholder {0}: props.worktreeBranch -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" -msgstr "Este tópico usa a árvore de trabalho <0>{0}. Remover também o diretório da árvore de trabalho?" +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" +#~ msgstr "Este tópico usa a árvore de trabalho <0>{0}. Remover também o diretório da árvore de trabalho?" + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This will permanently delete the thread and its worktree." +#~ msgstr "Isso excluirá permanentemente a thread e sua worktree." + +#. placeholder {0}: props.worktreeBranch +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread and remove worktree <0>{0}." +msgstr "Isso excluirá permanentemente a thread e removerá a worktree <0>{0}." + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread." +msgstr "Isso excluirá permanentemente a thread." #: src/renderer/views/GitHubActionsView/GitHubActionsView.tsx msgid "This workflow cannot be started manually." @@ -12356,10 +12423,10 @@ msgstr "Pensamento" msgid "Thread" msgstr "Tópico" -#. Dialog button: delete the thread and remove its worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread + Worktree" -msgstr "Tópico + Árvore de Trabalho" +#. Popover button: delete the thread and remove its worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread + Worktree" +#~ msgstr "Tópico + Árvore de Trabalho" #: src/mobile/ThreadTitleRow.tsx msgid "Thread actions" @@ -12402,10 +12469,10 @@ msgstr "Opções da lista de tópicos" msgid "Thread mode" msgstr "Modo de tópico" -#. Dialog button: delete the thread but keep the worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread Only" -msgstr "Apenas tópico" +#. Popover button: delete the thread but keep the worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread Only" +#~ msgstr "Apenas tópico" #: src/renderer/views/MainView/parts/SidebarHeaderControls.tsx #~ msgid "Thread sort order" diff --git a/src/renderer/locales/ru/messages.po b/src/renderer/locales/ru/messages.po index 26a821a6b..d3d9ddcda 100644 --- a/src/renderer/locales/ru/messages.po +++ b/src/renderer/locales/ru/messages.po @@ -1242,6 +1242,14 @@ msgstr "Все проекты" msgid "All sources" msgstr "Все источники" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be archived." +msgstr "Все потоки в разделе «Готово» будут архивированы." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be permanently deleted." +msgstr "Все потоки в разделе «Готово» будут удалены без возможности восстановления." + #: src/renderer/views/MainView/parts/Sidebar/parts/useProjectMenu.tsx #: src/renderer/views/SettingsOverlay/parts/WorkspacesSettings.tsx msgid "All workspaces" @@ -1387,6 +1395,7 @@ msgid "Approved" msgstr "Одобрено" #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Archive" msgstr "Архивировать" @@ -1402,11 +1411,19 @@ msgstr "Архивировать {0}" msgid "Archive All" msgstr "Архивировать всё" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Archive all done threads" +#~ msgstr "Архивировать все завершенные потоки" + #: src/mobile/views/threadActionSurfaces.tsx #: src/mobile/views/threadContextMenus.tsx msgid "Archive all threads" msgstr "Архивировать все потоки" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Archive done threads" +msgstr "Архивировать завершенные потоки" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Архивировать текущий тред" @@ -2023,11 +2040,11 @@ msgstr "Не удалось загрузить порты" msgid "Can't reach the remote server. Check that it is online, then reconnect it." msgstr "Не удалось связаться с удалённым сервером. Убедитесь, что он в сети, и переподключите его." -#. Dialog button: dismiss without deleting #: src/mobile/push/WebPushPermissionPrompt.tsx #: src/mobile/views/DesktopsView.tsx #: src/mobile/views/FilesView.tsx #: src/mobile/views/GitActionSheet.tsx +#: src/renderer/components/common/ConfirmationPopover.tsx #: src/renderer/components/common/ConfirmDialog.tsx #: src/renderer/components/experiment/ExperimentDraftTargets.tsx #: src/renderer/components/mcp/McpServerEditor.tsx @@ -2050,7 +2067,6 @@ msgstr "Не удалось связаться с удалённым серве #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx @@ -3007,6 +3023,16 @@ msgstr "Настройте сервер, который Poracode будет до msgid "Configured MCP servers" msgstr "Настроенные серверы MCP" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Confirm before deleting threads" +msgstr "Подтверждать удаление потоков" + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Confirm before deleting worktrees" +#~ msgstr "Подтверждать удаление рабочих деревьев" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Conflict Resolver" @@ -3883,6 +3909,8 @@ msgstr "Делегируйте работу другим ИИ-агентам." #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -3921,10 +3949,18 @@ msgstr "Удалить {serverName}" msgid "Delete <0>{0}? This cannot be undone." msgstr "Удалить <0>{0}? Это действие нельзя отменить." +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Delete all done threads" +#~ msgstr "Удалить все завершенные потоки" + #: src/renderer/components/common/BranchSelector/BranchSelector.tsx msgid "Delete branch?" msgstr "Удалить ветку?" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Delete done threads" +msgstr "Удалить завершенные потоки" + #: src/renderer/components/thread/ChatPane/parts/items/FileChange.tsx msgid "Delete file" msgstr "Удалить файл" @@ -3970,7 +4006,7 @@ msgstr "Удалить тред" msgid "Delete Thread" msgstr "Удалить тред" -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Delete thread?" msgstr "Удалить тред?" @@ -4295,7 +4331,7 @@ msgid "Docs" msgstr "Документация" #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Don't ask again" msgstr "Больше не спрашивать" @@ -4827,6 +4863,14 @@ msgstr "Кандидат эксперимента больше не являет msgid "Experiment candidate thread ids must be unique" msgstr "Идентификаторы тредов кандидатов эксперимента должны быть уникальными" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be archived." +msgstr "Кандидаты эксперимента останутся; все остальные потоки в разделе «Готово» будут архивированы." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be permanently deleted." +msgstr "Кандидаты эксперимента останутся; все остальные потоки в разделе «Готово» будут удалены без возможности восстановления." + #: src/renderer/i18n/sharedMessages.ts msgid "Experiment diff base must be a full commit hash" msgstr "База diff эксперимента должна быть полным хешем коммита" @@ -10878,6 +10922,16 @@ msgstr "Показать {0}" msgid "Show {label} circle in sidebar" msgstr "Показать кружок {label} на боковой панели" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Show a confirmation before deleting a thread together with its worktree." +#~ msgstr "Показывать подтверждение перед удалением потока вместе с его рабочим деревом." + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Show a confirmation before permanently deleting a thread." +msgstr "Показывать подтверждение перед безвозвратным удалением потока." + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Show a projectless Home scope for OS-level agent sessions." @@ -12331,9 +12385,22 @@ msgid "This system-wide shortcut is unavailable. Choose another key combination. msgstr "Это общесистемное сочетание клавиш недоступно. Выберите другое сочетание." #. placeholder {0}: props.worktreeBranch -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" -msgstr "Этот тред использует рабочее дерево <0>{0}. Также удалить каталог рабочего дерева?" +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" +#~ msgstr "Этот тред использует рабочее дерево <0>{0}. Также удалить каталог рабочего дерева?" + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This will permanently delete the thread and its worktree." +#~ msgstr "Поток и его рабочее дерево будут удалены без возможности восстановления." + +#. placeholder {0}: props.worktreeBranch +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread and remove worktree <0>{0}." +msgstr "Поток будет удалён без возможности восстановления, а рабочее дерево <0>{0} — удалено." + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread." +msgstr "Поток будет удалён без возможности восстановления." #: src/renderer/views/GitHubActionsView/GitHubActionsView.tsx msgid "This workflow cannot be started manually." @@ -12356,10 +12423,10 @@ msgstr "Мысль" msgid "Thread" msgstr "Тред" -#. Dialog button: delete the thread and remove its worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread + Worktree" -msgstr "Тред + рабочее дерево" +#. Popover button: delete the thread and remove its worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread + Worktree" +#~ msgstr "Тред + рабочее дерево" #: src/mobile/ThreadTitleRow.tsx msgid "Thread actions" @@ -12402,10 +12469,10 @@ msgstr "Параметры списка тредов" msgid "Thread mode" msgstr "Режим треда" -#. Dialog button: delete the thread but keep the worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread Only" -msgstr "Только тред" +#. Popover button: delete the thread but keep the worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread Only" +#~ msgstr "Только тред" #: src/renderer/views/MainView/parts/SidebarHeaderControls.tsx #~ msgid "Thread sort order" diff --git a/src/renderer/locales/tr/messages.po b/src/renderer/locales/tr/messages.po index febd10774..72725b85a 100644 --- a/src/renderer/locales/tr/messages.po +++ b/src/renderer/locales/tr/messages.po @@ -1242,6 +1242,14 @@ msgstr "Tüm projeler" msgid "All sources" msgstr "Tüm kaynaklar" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be archived." +msgstr "Bitti bölümündeki tüm iş parçacıkları arşivlenecek." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be permanently deleted." +msgstr "Bitti bölümündeki tüm iş parçacıkları kalıcı olarak silinecek." + #: src/renderer/views/MainView/parts/Sidebar/parts/useProjectMenu.tsx #: src/renderer/views/SettingsOverlay/parts/WorkspacesSettings.tsx msgid "All workspaces" @@ -1387,6 +1395,7 @@ msgid "Approved" msgstr "Onaylandı" #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Archive" msgstr "Arşiv" @@ -1402,11 +1411,19 @@ msgstr "Arşiv {0}" msgid "Archive All" msgstr "Tümünü Arşivle" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Archive all done threads" +#~ msgstr "Tamamlanan tüm iş parçacıklarını arşivle" + #: src/mobile/views/threadActionSurfaces.tsx #: src/mobile/views/threadContextMenus.tsx msgid "Archive all threads" msgstr "Tüm iş parçacıklarını arşivle" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Archive done threads" +msgstr "Tamamlanan iş parçacıklarını arşivle" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Geçerli konuyu arşivle" @@ -2023,11 +2040,11 @@ msgstr "Portlar yüklenemedi" msgid "Can't reach the remote server. Check that it is online, then reconnect it." msgstr "Uzak sunucuya ulaşılamıyor. Çevrimiçi olduğunu doğrulayıp yeniden bağlanın." -#. Dialog button: dismiss without deleting #: src/mobile/push/WebPushPermissionPrompt.tsx #: src/mobile/views/DesktopsView.tsx #: src/mobile/views/FilesView.tsx #: src/mobile/views/GitActionSheet.tsx +#: src/renderer/components/common/ConfirmationPopover.tsx #: src/renderer/components/common/ConfirmDialog.tsx #: src/renderer/components/experiment/ExperimentDraftTargets.tsx #: src/renderer/components/mcp/McpServerEditor.tsx @@ -2050,7 +2067,6 @@ msgstr "Uzak sunucuya ulaşılamıyor. Çevrimiçi olduğunu doğrulayıp yenide #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx @@ -3007,6 +3023,16 @@ msgstr "Desteklenen aracılar başlatıldığında Poracode'un ekleyeceği sunuc msgid "Configured MCP servers" msgstr "Yapılandırılmış MCP sunucuları" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Confirm before deleting threads" +msgstr "İş parçacıklarını silmeden önce onayla" + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Confirm before deleting worktrees" +#~ msgstr "Çalışma ağaçlarını silmeden önce onayla" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Conflict Resolver" @@ -3883,6 +3909,8 @@ msgstr "İşi diğer yapay zeka aracılarına devredin." #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -3921,10 +3949,18 @@ msgstr "{serverName} sunucusunu sil" msgid "Delete <0>{0}? This cannot be undone." msgstr "<0>{0} silinsin mi? Bu işlem geri alınamaz." +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Delete all done threads" +#~ msgstr "Tamamlanan tüm iş parçacıklarını sil" + #: src/renderer/components/common/BranchSelector/BranchSelector.tsx msgid "Delete branch?" msgstr "Şube silinsin mi?" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Delete done threads" +msgstr "Tamamlanan iş parçacıklarını sil" + #: src/renderer/components/thread/ChatPane/parts/items/FileChange.tsx msgid "Delete file" msgstr "Dosyayı sil" @@ -3970,7 +4006,7 @@ msgstr "Konuyu sil" msgid "Delete Thread" msgstr "Konuyu Sil" -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Delete thread?" msgstr "Konu silinsin mi?" @@ -4295,7 +4331,7 @@ msgid "Docs" msgstr "Dokümanlar" #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Don't ask again" msgstr "Bir daha sorma" @@ -4827,6 +4863,14 @@ msgstr "Deney adayı artık dondurulmuş temel commit'inden türemiyor" msgid "Experiment candidate thread ids must be unique" msgstr "Deney adaylarının konu kimlikleri benzersiz olmalıdır" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be archived." +msgstr "Deney adayları kalacak; Bitti bölümündeki diğer tüm iş parçacıkları arşivlenecek." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be permanently deleted." +msgstr "Deney adayları kalacak; Bitti bölümündeki diğer tüm iş parçacıkları kalıcı olarak silinecek." + #: src/renderer/i18n/sharedMessages.ts msgid "Experiment diff base must be a full commit hash" msgstr "Deney farkı tabanı tam bir commit karması olmalıdır" @@ -10878,6 +10922,16 @@ msgstr "{0} öğesini göster" msgid "Show {label} circle in sidebar" msgstr "{label} dairesini kenar çubuğunda göster" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Show a confirmation before deleting a thread together with its worktree." +#~ msgstr "Bir iş parçacığını çalışma ağacıyla birlikte silmeden önce onay göster." + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Show a confirmation before permanently deleting a thread." +msgstr "Bir iş parçacığını kalıcı olarak silmeden önce onay göster." + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Show a projectless Home scope for OS-level agent sessions." @@ -12331,9 +12385,22 @@ msgid "This system-wide shortcut is unavailable. Choose another key combination. msgstr "Bu sistem genelindeki kısayol kullanılamıyor. Başka bir tuş birleşimi seçin." #. placeholder {0}: props.worktreeBranch -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" -msgstr "Bu iş parçacığı <0>{0} çalışma ağacını kullanıyor. Ayrıca çalışma ağacı dizini de kaldırılsın mı?" +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" +#~ msgstr "Bu iş parçacığı <0>{0} çalışma ağacını kullanıyor. Ayrıca çalışma ağacı dizini de kaldırılsın mı?" + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This will permanently delete the thread and its worktree." +#~ msgstr "Bu işlem iş parçacığını ve çalışma ağacını kalıcı olarak silecek." + +#. placeholder {0}: props.worktreeBranch +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread and remove worktree <0>{0}." +msgstr "Bu işlem iş parçacığını kalıcı olarak silecek ve <0>{0} çalışma ağacını kaldıracak." + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread." +msgstr "Bu işlem iş parçacığını kalıcı olarak silecek." #: src/renderer/views/GitHubActionsView/GitHubActionsView.tsx msgid "This workflow cannot be started manually." @@ -12356,10 +12423,10 @@ msgstr "Düşünce" msgid "Thread" msgstr "Konu" -#. Dialog button: delete the thread and remove its worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread + Worktree" -msgstr "Konu + Çalışma Ağacı" +#. Popover button: delete the thread and remove its worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread + Worktree" +#~ msgstr "Konu + Çalışma Ağacı" #: src/mobile/ThreadTitleRow.tsx msgid "Thread actions" @@ -12402,10 +12469,10 @@ msgstr "Konu listesi seçenekleri" msgid "Thread mode" msgstr "Konu modu" -#. Dialog button: delete the thread but keep the worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread Only" -msgstr "Yalnızca Konu" +#. Popover button: delete the thread but keep the worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread Only" +#~ msgstr "Yalnızca Konu" #: src/renderer/views/MainView/parts/SidebarHeaderControls.tsx #~ msgid "Thread sort order" diff --git a/src/renderer/locales/uk/messages.po b/src/renderer/locales/uk/messages.po index 73a27ffd7..667cb3c6a 100644 --- a/src/renderer/locales/uk/messages.po +++ b/src/renderer/locales/uk/messages.po @@ -1242,6 +1242,14 @@ msgstr "Усі проєкти" msgid "All sources" msgstr "Усі джерела" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be archived." +msgstr "Усі потоки в розділі «Завершено» буде заархівовано." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be permanently deleted." +msgstr "Усі потоки в розділі «Завершено» буде остаточно видалено." + #: src/renderer/views/MainView/parts/Sidebar/parts/useProjectMenu.tsx #: src/renderer/views/SettingsOverlay/parts/WorkspacesSettings.tsx msgid "All workspaces" @@ -1387,6 +1395,7 @@ msgid "Approved" msgstr "Схвалено" #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Archive" msgstr "Архівувати" @@ -1402,11 +1411,19 @@ msgstr "Архівувати {0}" msgid "Archive All" msgstr "Архівувати все" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Archive all done threads" +#~ msgstr "Архівувати всі завершені потоки" + #: src/mobile/views/threadActionSurfaces.tsx #: src/mobile/views/threadContextMenus.tsx msgid "Archive all threads" msgstr "Архівувати всі потоки" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Archive done threads" +msgstr "Архівувати завершені потоки" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Архівувати поточний тред" @@ -2023,11 +2040,11 @@ msgstr "Не вдалося завантажити порти" msgid "Can't reach the remote server. Check that it is online, then reconnect it." msgstr "Не вдалося зв’язатися з віддаленим сервером. Переконайтеся, що він у мережі, і перепідключіть його." -#. Dialog button: dismiss without deleting #: src/mobile/push/WebPushPermissionPrompt.tsx #: src/mobile/views/DesktopsView.tsx #: src/mobile/views/FilesView.tsx #: src/mobile/views/GitActionSheet.tsx +#: src/renderer/components/common/ConfirmationPopover.tsx #: src/renderer/components/common/ConfirmDialog.tsx #: src/renderer/components/experiment/ExperimentDraftTargets.tsx #: src/renderer/components/mcp/McpServerEditor.tsx @@ -2050,7 +2067,6 @@ msgstr "Не вдалося зв’язатися з віддаленим сер #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx @@ -3007,6 +3023,16 @@ msgstr "Налаштуйте сервер, який Poracode додаватим msgid "Configured MCP servers" msgstr "Налаштовані сервери MCP" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Confirm before deleting threads" +msgstr "Підтверджувати видалення потоків" + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Confirm before deleting worktrees" +#~ msgstr "Підтверджувати видалення робочих дерев" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Conflict Resolver" @@ -3883,6 +3909,8 @@ msgstr "Делегуйте роботу іншим ШІ-агентам." #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -3921,10 +3949,18 @@ msgstr "Видалити {serverName}" msgid "Delete <0>{0}? This cannot be undone." msgstr "Видалити <0>{0}? Цю дію не можна скасувати." +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Delete all done threads" +#~ msgstr "Видалити всі завершені потоки" + #: src/renderer/components/common/BranchSelector/BranchSelector.tsx msgid "Delete branch?" msgstr "Видалити гілку?" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Delete done threads" +msgstr "Видалити завершені потоки" + #: src/renderer/components/thread/ChatPane/parts/items/FileChange.tsx msgid "Delete file" msgstr "Видалити файл" @@ -3970,7 +4006,7 @@ msgstr "Видалити тред" msgid "Delete Thread" msgstr "Видалити тред" -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Delete thread?" msgstr "Видалити тред?" @@ -4295,7 +4331,7 @@ msgid "Docs" msgstr "Документація" #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Don't ask again" msgstr "Не питати знову" @@ -4827,6 +4863,14 @@ msgstr "Кандидат експерименту більше не є наща msgid "Experiment candidate thread ids must be unique" msgstr "Ідентифікатори тредів кандидатів експерименту мають бути унікальними" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be archived." +msgstr "Кандидати експерименту залишаться; усі інші потоки в розділі «Завершено» буде заархівовано." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be permanently deleted." +msgstr "Кандидати експерименту залишаться; усі інші потоки в розділі «Завершено» буде остаточно видалено." + #: src/renderer/i18n/sharedMessages.ts msgid "Experiment diff base must be a full commit hash" msgstr "Базою diff експерименту має бути повний хеш коміту" @@ -10878,6 +10922,16 @@ msgstr "Показати {0}" msgid "Show {label} circle in sidebar" msgstr "Показати коло {label} на бічній панелі" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Show a confirmation before deleting a thread together with its worktree." +#~ msgstr "Показувати підтвердження перед видаленням потоку разом із його робочим деревом." + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Show a confirmation before permanently deleting a thread." +msgstr "Показувати підтвердження перед остаточним видаленням потоку." + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Show a projectless Home scope for OS-level agent sessions." @@ -12331,9 +12385,22 @@ msgid "This system-wide shortcut is unavailable. Choose another key combination. msgstr "Це загальносистемне сполучення клавіш недоступне. Виберіть інше сполучення." #. placeholder {0}: props.worktreeBranch -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" -msgstr "Цей тред використовує робоче дерево <0>{0}. Також видалити каталог робочого дерева?" +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" +#~ msgstr "Цей тред використовує робоче дерево <0>{0}. Також видалити каталог робочого дерева?" + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This will permanently delete the thread and its worktree." +#~ msgstr "Потік і його робоче дерево буде остаточно видалено." + +#. placeholder {0}: props.worktreeBranch +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread and remove worktree <0>{0}." +msgstr "Потік буде остаточно видалено, а робоче дерево <0>{0} — вилучено." + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread." +msgstr "Потік буде остаточно видалено." #: src/renderer/views/GitHubActionsView/GitHubActionsView.tsx msgid "This workflow cannot be started manually." @@ -12356,10 +12423,10 @@ msgstr "Думка" msgid "Thread" msgstr "Тред" -#. Dialog button: delete the thread and remove its worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread + Worktree" -msgstr "Тред + робоче дерево" +#. Popover button: delete the thread and remove its worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread + Worktree" +#~ msgstr "Тред + робоче дерево" #: src/mobile/ThreadTitleRow.tsx msgid "Thread actions" @@ -12402,10 +12469,10 @@ msgstr "Параметри списку тредів" msgid "Thread mode" msgstr "Режим треда" -#. Dialog button: delete the thread but keep the worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread Only" -msgstr "Лише тред" +#. Popover button: delete the thread but keep the worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread Only" +#~ msgstr "Лише тред" #: src/renderer/views/MainView/parts/SidebarHeaderControls.tsx #~ msgid "Thread sort order" diff --git a/src/renderer/locales/vi/messages.po b/src/renderer/locales/vi/messages.po index 3c03f3bda..cd1967f7c 100644 --- a/src/renderer/locales/vi/messages.po +++ b/src/renderer/locales/vi/messages.po @@ -1242,6 +1242,14 @@ msgstr "Tất cả dự án" msgid "All sources" msgstr "Tất cả nguồn" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be archived." +msgstr "Tất cả luồng trong mục Xong sẽ được lưu trữ." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be permanently deleted." +msgstr "Tất cả luồng trong mục Xong sẽ bị xóa vĩnh viễn." + #: src/renderer/views/MainView/parts/Sidebar/parts/useProjectMenu.tsx #: src/renderer/views/SettingsOverlay/parts/WorkspacesSettings.tsx msgid "All workspaces" @@ -1387,6 +1395,7 @@ msgid "Approved" msgstr "Đã được phê duyệt" #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Archive" msgstr "Lưu trữ" @@ -1402,11 +1411,19 @@ msgstr "Lưu trữ {0}" msgid "Archive All" msgstr "Lưu trữ tất cả" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Archive all done threads" +#~ msgstr "Lưu trữ tất cả luồng đã xong" + #: src/mobile/views/threadActionSurfaces.tsx #: src/mobile/views/threadContextMenus.tsx msgid "Archive all threads" msgstr "Lưu trữ tất cả luồng" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Archive done threads" +msgstr "Lưu trữ các luồng đã xong" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "Lưu trữ luồng hiện tại" @@ -2023,11 +2040,11 @@ msgstr "Không thể tải danh sách cổng" msgid "Can't reach the remote server. Check that it is online, then reconnect it." msgstr "Không thể kết nối tới máy chủ từ xa. Hãy kiểm tra máy chủ đang trực tuyến rồi kết nối lại." -#. Dialog button: dismiss without deleting #: src/mobile/push/WebPushPermissionPrompt.tsx #: src/mobile/views/DesktopsView.tsx #: src/mobile/views/FilesView.tsx #: src/mobile/views/GitActionSheet.tsx +#: src/renderer/components/common/ConfirmationPopover.tsx #: src/renderer/components/common/ConfirmDialog.tsx #: src/renderer/components/experiment/ExperimentDraftTargets.tsx #: src/renderer/components/mcp/McpServerEditor.tsx @@ -2050,7 +2067,6 @@ msgstr "Không thể kết nối tới máy chủ từ xa. Hãy kiểm tra máy #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx @@ -3007,6 +3023,16 @@ msgstr "Cấu hình máy chủ mà Poracode sẽ thêm khi khởi động các t msgid "Configured MCP servers" msgstr "Máy chủ MCP đã cấu hình" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Confirm before deleting threads" +msgstr "Xác nhận trước khi xóa luồng" + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Confirm before deleting worktrees" +#~ msgstr "Xác nhận trước khi xóa cây làm việc" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Conflict Resolver" @@ -3883,6 +3909,8 @@ msgstr "Giao việc cho các tác nhân AI khác." #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -3921,10 +3949,18 @@ msgstr "Xóa {serverName}" msgid "Delete <0>{0}? This cannot be undone." msgstr "Xóa <0>{0}? Không thể hoàn tác thao tác này." +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Delete all done threads" +#~ msgstr "Xóa tất cả luồng đã xong" + #: src/renderer/components/common/BranchSelector/BranchSelector.tsx msgid "Delete branch?" msgstr "Xóa nhánh?" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Delete done threads" +msgstr "Xóa các luồng đã xong" + #: src/renderer/components/thread/ChatPane/parts/items/FileChange.tsx msgid "Delete file" msgstr "Xóa tập tin" @@ -3970,7 +4006,7 @@ msgstr "Xóa chủ đề" msgid "Delete Thread" msgstr "Xóa chủ đề" -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Delete thread?" msgstr "Xóa chủ đề?" @@ -4295,7 +4331,7 @@ msgid "Docs" msgstr "Tài liệu" #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Don't ask again" msgstr "Đừng hỏi lại" @@ -4827,6 +4863,14 @@ msgstr "Ứng viên thử nghiệm không còn là hậu duệ của commit cơ msgid "Experiment candidate thread ids must be unique" msgstr "ID luồng của các ứng viên thử nghiệm phải là duy nhất" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be archived." +msgstr "Các ứng viên thử nghiệm sẽ được giữ lại; tất cả luồng khác trong mục Xong sẽ được lưu trữ." + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be permanently deleted." +msgstr "Các ứng viên thử nghiệm sẽ được giữ lại; tất cả luồng khác trong mục Xong sẽ bị xóa vĩnh viễn." + #: src/renderer/i18n/sharedMessages.ts msgid "Experiment diff base must be a full commit hash" msgstr "Cơ sở diff của thử nghiệm phải là hàm băm đầy đủ của commit" @@ -10878,6 +10922,16 @@ msgstr "Hiển thị {0}" msgid "Show {label} circle in sidebar" msgstr "Hiển thị vòng tròn {label} ở thanh bên" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Show a confirmation before deleting a thread together with its worktree." +#~ msgstr "Hiển thị xác nhận trước khi xóa một luồng cùng với cây làm việc của luồng đó." + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Show a confirmation before permanently deleting a thread." +msgstr "Hiển thị xác nhận trước khi xóa vĩnh viễn một luồng." + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Show a projectless Home scope for OS-level agent sessions." @@ -12331,9 +12385,22 @@ msgid "This system-wide shortcut is unavailable. Choose another key combination. msgstr "Phím tắt toàn hệ thống này không khả dụng. Hãy chọn tổ hợp phím khác." #. placeholder {0}: props.worktreeBranch -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" -msgstr "Luồng này sử dụng cây làm việc <0>{0}. Cũng xóa thư mục cây làm việc?" +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" +#~ msgstr "Luồng này sử dụng cây làm việc <0>{0}. Cũng xóa thư mục cây làm việc?" + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This will permanently delete the thread and its worktree." +#~ msgstr "Thao tác này sẽ xóa vĩnh viễn luồng và cây làm việc của luồng đó." + +#. placeholder {0}: props.worktreeBranch +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread and remove worktree <0>{0}." +msgstr "Thao tác này sẽ xóa vĩnh viễn luồng và loại bỏ cây làm việc <0>{0}." + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread." +msgstr "Thao tác này sẽ xóa vĩnh viễn luồng." #: src/renderer/views/GitHubActionsView/GitHubActionsView.tsx msgid "This workflow cannot be started manually." @@ -12356,10 +12423,10 @@ msgstr "Suy nghĩ" msgid "Thread" msgstr "luồng" -#. Dialog button: delete the thread and remove its worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread + Worktree" -msgstr "Luồng + Cây làm việc" +#. Popover button: delete the thread and remove its worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread + Worktree" +#~ msgstr "Luồng + Cây làm việc" #: src/mobile/ThreadTitleRow.tsx msgid "Thread actions" @@ -12402,10 +12469,10 @@ msgstr "Tùy chọn danh sách luồng" msgid "Thread mode" msgstr "Chế độ luồng" -#. Dialog button: delete the thread but keep the worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread Only" -msgstr "Chỉ luồng" +#. Popover button: delete the thread but keep the worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread Only" +#~ msgstr "Chỉ luồng" #: src/renderer/views/MainView/parts/SidebarHeaderControls.tsx #~ msgid "Thread sort order" diff --git a/src/renderer/locales/zh-CN/messages.po b/src/renderer/locales/zh-CN/messages.po index a36d44383..f58a724a3 100644 --- a/src/renderer/locales/zh-CN/messages.po +++ b/src/renderer/locales/zh-CN/messages.po @@ -1242,6 +1242,14 @@ msgstr "所有项目" msgid "All sources" msgstr "所有来源" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be archived." +msgstr "“完成”中的所有线程都将归档。" + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "All threads in Done will be permanently deleted." +msgstr "“完成”中的所有线程都将永久删除。" + #: src/renderer/views/MainView/parts/Sidebar/parts/useProjectMenu.tsx #: src/renderer/views/SettingsOverlay/parts/WorkspacesSettings.tsx msgid "All workspaces" @@ -1387,6 +1395,7 @@ msgid "Approved" msgstr "已批准" #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts msgid "Archive" msgstr "存档" @@ -1402,11 +1411,19 @@ msgstr "存档{0}" msgid "Archive All" msgstr "全部存档" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Archive all done threads" +#~ msgstr "归档所有已完成的线程" + #: src/mobile/views/threadActionSurfaces.tsx #: src/mobile/views/threadContextMenus.tsx msgid "Archive all threads" msgstr "归档所有线程" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Archive done threads" +msgstr "归档已完成的线程" + #: src/renderer/commands/registry.ts msgid "Archive the current thread" msgstr "归档当前线程" @@ -2023,11 +2040,11 @@ msgstr "无法加载端口" msgid "Can't reach the remote server. Check that it is online, then reconnect it." msgstr "无法连接远程服务器。请确认其处于在线状态,然后重新连接。" -#. Dialog button: dismiss without deleting #: src/mobile/push/WebPushPermissionPrompt.tsx #: src/mobile/views/DesktopsView.tsx #: src/mobile/views/FilesView.tsx #: src/mobile/views/GitActionSheet.tsx +#: src/renderer/components/common/ConfirmationPopover.tsx #: src/renderer/components/common/ConfirmDialog.tsx #: src/renderer/components/experiment/ExperimentDraftTargets.tsx #: src/renderer/components/mcp/McpServerEditor.tsx @@ -2050,7 +2067,6 @@ msgstr "无法连接远程服务器。请确认其处于在线状态,然后重 #: src/renderer/views/MainView/parts/CreateProject/CloneProjectModal.tsx #: src/renderer/views/MainView/parts/CreateProject/CreateProjectModal.tsx #: src/renderer/views/MainView/parts/PullFromSourceDialog.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx #: src/renderer/views/ProfileOverlay/parts/EditProfileDialog.tsx #: src/renderer/views/PrReviewOverlay/parts/SubmitReviewPopover.tsx #: src/renderer/views/SchedulesView/ScheduleEditor.tsx @@ -3007,6 +3023,16 @@ msgstr "配置 Poracode 在受支持的代理启动时添加的服务器。" msgid "Configured MCP servers" msgstr "已配置的 MCP 服务器" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Confirm before deleting threads" +msgstr "删除线程前确认" + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Confirm before deleting worktrees" +#~ msgstr "删除工作树前确认" + #: src/renderer/views/SettingsOverlay/parts/AISettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Conflict Resolver" @@ -3883,6 +3909,8 @@ msgstr "将工作委派给其他 AI 智能体。" #: src/renderer/views/FileEditorOverlay/parts/ProjectTreeView/parts/TreeEntryRow.tsx #: src/renderer/views/GitReviewOverlay/parts/GitReviewPanel.tsx #: src/renderer/views/MainView/parts/RightPanel/parts/NotesPanel/TodoRow.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx #: src/renderer/views/SchedulesView/SchedulesView.tsx #: src/renderer/views/SettingsOverlay/parts/AcpRegistrySettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsOptions.ts @@ -3921,10 +3949,18 @@ msgstr "删除 {serverName}" msgid "Delete <0>{0}? This cannot be undone." msgstr "删除 <0>{0}?此操作无法撤销。" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +#~ msgid "Delete all done threads" +#~ msgstr "删除所有已完成的线程" + #: src/renderer/components/common/BranchSelector/BranchSelector.tsx msgid "Delete branch?" msgstr "删除分支?" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Delete done threads" +msgstr "删除已完成的线程" + #: src/renderer/components/thread/ChatPane/parts/items/FileChange.tsx msgid "Delete file" msgstr "删除文件" @@ -3970,7 +4006,7 @@ msgstr "删除线程" msgid "Delete Thread" msgstr "删除线程" -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Delete thread?" msgstr "删除线程?" @@ -4295,7 +4331,7 @@ msgid "Docs" msgstr "文档" #: src/renderer/components/thread/ChatPane/parts/CheckpointRevertControls.tsx -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx msgid "Don't ask again" msgstr "不要再问" @@ -4827,6 +4863,14 @@ msgstr "实验候选项不再是其冻结基础提交的后代" msgid "Experiment candidate thread ids must be unique" msgstr "实验候选项的线程 ID 必须唯一" +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be archived." +msgstr "实验候选项将保留;“完成”中的所有其他线程都将归档。" + +#: src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +msgid "Experiment candidates will remain; all other threads in Done will be permanently deleted." +msgstr "实验候选项将保留;“完成”中的所有其他线程都将永久删除。" + #: src/renderer/i18n/sharedMessages.ts msgid "Experiment diff base must be a full commit hash" msgstr "实验差异的基准必须是完整的提交哈希" @@ -10877,6 +10921,16 @@ msgstr "显示 {0}" msgid "Show {label} circle in sidebar" msgstr "在侧边栏中显示 {label} 圆环" +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +#~ msgid "Show a confirmation before deleting a thread together with its worktree." +#~ msgstr "删除线程及其工作树前显示确认。" + +#: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +#: src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +msgid "Show a confirmation before permanently deleting a thread." +msgstr "永久删除线程前显示确认。" + #: src/renderer/views/SettingsOverlay/parts/GeneralSettings.tsx #: src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts msgid "Show a projectless Home scope for OS-level agent sessions." @@ -12330,9 +12384,22 @@ msgid "This system-wide shortcut is unavailable. Choose another key combination. msgstr "此全局快捷键不可用。请选择其他按键组合。" #. placeholder {0}: props.worktreeBranch -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" -msgstr "该线程使用工作树 <0>{0}。还要删除工作树目录吗?" +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This thread uses worktree <0>{0}. Also remove the worktree directory?" +#~ msgstr "该线程使用工作树 <0>{0}。还要删除工作树目录吗?" + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "This will permanently delete the thread and its worktree." +#~ msgstr "这将永久删除该线程及其工作树。" + +#. placeholder {0}: props.worktreeBranch +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread and remove worktree <0>{0}." +msgstr "这将永久删除该线程并移除工作树 <0>{0}。" + +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx +msgid "This will permanently delete the thread." +msgstr "这将永久删除该线程。" #: src/renderer/views/GitHubActionsView/GitHubActionsView.tsx msgid "This workflow cannot be started manually." @@ -12355,10 +12422,10 @@ msgstr "思考" msgid "Thread" msgstr "线程" -#. Dialog button: delete the thread and remove its worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread + Worktree" -msgstr "线程+工作树" +#. Popover button: delete the thread and remove its worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread + Worktree" +#~ msgstr "线程+工作树" #: src/mobile/ThreadTitleRow.tsx msgid "Thread actions" @@ -12401,10 +12468,10 @@ msgstr "线程列表选项" msgid "Thread mode" msgstr "线程模式" -#. Dialog button: delete the thread but keep the worktree directory -#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx -msgid "Thread Only" -msgstr "仅线程" +#. Popover button: delete the thread but keep the worktree directory +#: src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreePopover.tsx +#~ msgid "Thread Only" +#~ msgstr "仅线程" #: src/renderer/views/MainView/parts/SidebarHeaderControls.tsx #~ msgid "Thread sort order" diff --git a/src/renderer/state/threadDeletePreference.ts b/src/renderer/state/threadDeletePreference.ts new file mode 100644 index 000000000..eb4c485d7 --- /dev/null +++ b/src/renderer/state/threadDeletePreference.ts @@ -0,0 +1,15 @@ +// Kept at the historical key so an existing opt-out survives the upgrade from +// the three-way "thread only / thread + worktree" dialog to a single confirm. +const PREF_KEY = "poracode-delete-worktree-pref"; + +export function shouldConfirmThreadDelete(): boolean { + // That older UI also supported "thread-only", which cannot safely migrate to + // deleting without asking — it never authorised worktree removal. So only the + // explicit destructive choice suppresses the confirmation; anything else asks. + return localStorage.getItem(PREF_KEY) !== "thread-and-worktree"; +} + +export function setConfirmThreadDelete(confirm: boolean): void { + if (confirm) localStorage.removeItem(PREF_KEY); + else localStorage.setItem(PREF_KEY, "thread-and-worktree"); +} diff --git a/src/renderer/state/worktreeDeleteStore.ts b/src/renderer/state/worktreeDeleteStore.ts index e954a2416..dcaf8e1bd 100644 --- a/src/renderer/state/worktreeDeleteStore.ts +++ b/src/renderer/state/worktreeDeleteStore.ts @@ -4,9 +4,13 @@ export type WorktreeDeleteDialogState = | { kind: "single-thread"; threadId: string; - projectId: string; - worktreePath: string; - worktreeBranch: string; + projectId?: string; + // Set only when deleting this thread also removes the worktree directory, + // so the confirmation never promises a removal that will not happen. + worktreePath?: string; + worktreeBranch?: string; + anchorPosition: { x: number; y: number }; + returnFocusElement?: HTMLElement; } | { kind: "branch-unmerged"; diff --git a/src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.test.tsx b/src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.test.tsx new file mode 100644 index 000000000..3c86172ae --- /dev/null +++ b/src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.test.tsx @@ -0,0 +1,96 @@ +import { fireEvent, screen } from "@testing-library/react"; +import { useState } from "react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { renderWithI18n as render } from "@/renderer/testUtils/i18n"; +import { shouldConfirmThreadDelete } from "@/renderer/state/threadDeletePreference"; +import { DeleteThreadPopover } from "./DeleteThreadPopover"; + +describe("DeleteThreadPopover", () => { + beforeEach(() => localStorage.clear()); + + it("anchors the confirmation and can remember the destructive choice", () => { + const onClose = vi.fn<() => void>(); + const onDelete = vi.fn<() => void>(); + render( + , + ); + + expect(screen.getByRole("dialog")).toHaveTextContent("feature/popover"); + fireEvent.click(screen.getByRole("checkbox", { name: "Don't ask again" })); + fireEvent.click(screen.getByRole("button", { name: "Delete" })); + + expect(onDelete).toHaveBeenCalledOnce(); + expect(shouldConfirmThreadDelete()).toBe(false); + expect(localStorage.getItem("poracode-delete-worktree-pref")).toBe("thread-and-worktree"); + }); + + it("omits the worktree from the warning when none will be removed", () => { + render( + undefined} + onDelete={() => undefined} + />, + ); + + const dialog = screen.getByRole("dialog"); + expect(dialog).toHaveTextContent("This will permanently delete the thread."); + expect(dialog).not.toHaveTextContent("worktree"); + }); + + it("offers one explicit destructive action", () => { + const onDelete = vi.fn<() => void>(); + render( + undefined} + onDelete={onDelete} + />, + ); + + const destructiveAction = screen.getByRole("button", { name: "Delete" }); + expect(destructiveAction).toHaveClass("button--danger"); + expect(screen.queryByRole("button", { name: "Thread Only" })).not.toBeInTheDocument(); + fireEvent.click(destructiveAction); + + expect(onDelete).toHaveBeenCalledOnce(); + }); + + it("returns focus to the originating delete control after cancellation", async () => { + function Harness() { + const [isOpen, setIsOpen] = useState(true); + const [origin, setOrigin] = useState(null); + return ( + <> + + setIsOpen(false)} + onDelete={() => undefined} + /> + + ); + } + + render(); + const origin = screen.getByText("Delete row").closest("button")!; + origin.focus(); + fireEvent.click(screen.getByRole("button", { name: "Cancel" })); + + await vi.waitFor(() => expect(origin).toHaveFocus()); + }); +}); diff --git a/src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx b/src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx new file mode 100644 index 000000000..e5da470a0 --- /dev/null +++ b/src/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover.tsx @@ -0,0 +1,60 @@ +import { useState } from "react"; +import { Checkbox } from "@heroui/react"; +import { Trans, useLingui } from "@lingui/react/macro"; +import { ConfirmationPopover } from "@/renderer/components/common/ConfirmationPopover"; +import { setConfirmThreadDelete } from "@/renderer/state/threadDeletePreference"; + +export function DeleteThreadPopover(props: { + isOpen: boolean; + anchorPosition: { x: number; y: number }; + /** Set only when confirming also removes the worktree directory. */ + worktreeBranch?: string; + returnFocusElement?: HTMLElement; + onClose: () => void; + onDelete: () => void; +}) { + const { t } = useLingui(); + const [dontAskAgain, setDontAskAgain] = useState(false); + + function handleDelete() { + if (dontAskAgain) setConfirmThreadDelete(false); + props.onDelete(); + } + + return ( + !open && props.onClose()} + anchorPosition={props.anchorPosition} + className="w-80 max-w-[calc(100vw-16px)]" + {...(props.returnFocusElement ? { returnFocusElement: props.returnFocusElement } : {})} + title={t`Delete thread?`} + body={ + props.worktreeBranch ? ( + + This will permanently delete the thread and remove worktree{" "} + {props.worktreeBranch}. + + ) : ( + This will permanently delete the thread. + ) + } + actions={[ + { + label: t`Delete`, + variant: "danger", + onPress: handleDelete, + }, + ]} + > + + + + + + Don't ask again + + + + ); +} diff --git a/src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx b/src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx deleted file mode 100644 index a84ba3b5d..000000000 --- a/src/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { useState } from "react"; -import { AlertDialog, Checkbox } from "@heroui/react"; -import { Trans } from "@lingui/react/macro"; -import { Button } from "@/renderer/components/common/Button"; - -const PREF_KEY = "poracode-delete-worktree-pref"; - -export type WorktreeDeletePref = "thread-only" | "thread-and-worktree"; - -export function readWorktreeDeletePref(): WorktreeDeletePref | null { - const raw = localStorage.getItem(PREF_KEY); - if (raw === "thread-only" || raw === "thread-and-worktree") return raw; - return null; -} - -export function DeleteWorktreeDialog(props: { - isOpen: boolean; - worktreeBranch: string; - onClose: () => void; - onDeleteThreadOnly: (dontAskAgain: boolean) => void; - onDeleteThreadAndWorktree: (dontAskAgain: boolean) => void; -}) { - const [dontAskAgain, setDontAskAgain] = useState(false); - - function handleThreadOnly() { - if (dontAskAgain) localStorage.setItem(PREF_KEY, "thread-only"); - props.onDeleteThreadOnly(dontAskAgain); - } - - function handleThreadAndWorktree() { - if (dontAskAgain) localStorage.setItem(PREF_KEY, "thread-and-worktree"); - props.onDeleteThreadAndWorktree(dontAskAgain); - } - - return ( - !open && props.onClose()}> - - - - - Delete thread? - -

- - This thread uses worktree{" "} - {props.worktreeBranch}. - Also remove the worktree directory? - -

-
- - - - - - - Don't ask again - - - - - - - - -
-
-
- ); -} diff --git a/src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.test.tsx b/src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.test.tsx new file mode 100644 index 000000000..24ab57011 --- /dev/null +++ b/src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.test.tsx @@ -0,0 +1,204 @@ +import { act, fireEvent, screen } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import type { Project, Thread } from "@/shared/contracts"; +import { useAppStore } from "@/renderer/state/appStore"; +import { useSharedSettings } from "@/renderer/state/sharedSettingsStore"; +import { renderWithI18n as render } from "@/renderer/testUtils/i18n"; +import type { SidebarRow } from "./sidebarProjectRows"; +import { SidebarThreadRow } from "./SidebarThreadRow"; + +const threadActions = vi.hoisted(() => ({ + archiveThread: vi.fn<(threadId: string) => void>(), + deleteThread: vi.fn<(threadId: string) => void>(), +})); +const worktreeActions = vi.hoisted(() => ({ + deleteWorktreeGroup: + vi.fn<(projectId: string, worktreePath: string, threadIds: string[]) => void>(), +})); + +vi.mock("@/renderer/actions/threadActions", () => threadActions); +vi.mock("@/renderer/actions/worktreeActions", () => worktreeActions); +vi.mock("./SidebarThreadGroup", () => ({ SidebarThreadGroup: () => null })); +vi.mock("./SidebarWorktreeGroup", () => ({ SidebarWorktreeGroup: () => null })); +vi.mock("./SortableThreadItem/SortableThreadItem", () => ({ SortableThreadItem: () => null })); + +const project = { + id: "project-1", + name: "Poracode", + location: { kind: "windows", path: "C:\\repo" }, + createdAt: "2026-08-21T00:00:00.000Z", +} satisfies Project; + +function makeThread(id: string, overrides: Partial = {}): Thread { + return { + id, + projectId: project.id, + title: id, + agentKind: "codex", + config: { model: "gpt-5.4" }, + status: "idle", + attention: "none", + canResumeWithConfig: false, + archived: false, + done: true, + starred: false, + createdAt: "2026-08-21T00:00:00.000Z", + updatedAt: "2026-08-21T00:00:00.000Z", + ...overrides, + }; +} + +function renderDoneRow(options?: { + hasProtectedDoneThreads?: boolean; + doneThreads?: Thread[]; + allThreads?: Thread[]; +}) { + const doneThreads = options?.doneThreads ?? [makeThread("done-1"), makeThread("done-2")]; + const row: Extract = { + kind: "section-label", + key: "done-label", + label: { id: "Done", message: "Done" }, + doneThreads, + hasProtectedDoneThreads: options?.hasProtectedDoneThreads ?? false, + }; + useAppStore.setState({ threads: options?.allThreads ?? doneThreads }); + render( + undefined} + />, + ); +} + +describe("SidebarThreadRow Done section action", () => { + beforeEach(() => { + threadActions.archiveThread.mockReset(); + threadActions.deleteThread.mockReset(); + worktreeActions.deleteWorktreeGroup.mockReset(); + useSharedSettings.setState({ threadRemoveAction: "archive" }); + }); + + it("confirms and archives every done thread", () => { + renderDoneRow(); + + const trigger = screen.getByRole("button", { name: "Archive done threads" }); + expect(trigger).toHaveClass( + "opacity-0", + "group-hover:opacity-100", + "focus-visible:opacity-100", + ); + fireEvent.click(trigger); + expect(screen.getByText("All threads in Done will be archived.")).toBeInTheDocument(); + + fireEvent.click(screen.getByRole("button", { name: "Cancel" })); + expect(screen.queryByText("All threads in Done will be archived.")).not.toBeInTheDocument(); + expect(threadActions.archiveThread).not.toHaveBeenCalled(); + + fireEvent.click(trigger); + fireEvent.click(screen.getByRole("button", { name: "Archive" })); + expect(threadActions.archiveThread.mock.calls).toEqual([["done-1"], ["done-2"]]); + expect(threadActions.deleteThread).not.toHaveBeenCalled(); + }); + + it("confirms and permanently deletes every done thread", () => { + useSharedSettings.setState({ threadRemoveAction: "delete" }); + renderDoneRow(); + + fireEvent.click(screen.getByRole("button", { name: "Delete done threads" })); + expect( + screen.getByText("All threads in Done will be permanently deleted."), + ).toBeInTheDocument(); + + fireEvent.click(screen.getByRole("button", { name: "Delete" })); + expect(threadActions.deleteThread.mock.calls).toEqual([["done-1"], ["done-2"]]); + expect(threadActions.archiveThread).not.toHaveBeenCalled(); + }); + + it("removes a worktree owned only by one done thread", () => { + useSharedSettings.setState({ threadRemoveAction: "delete" }); + const thread = makeThread("done-1", { + worktreePath: "C:\\repo\\.poracode\\worktrees\\feature", + }); + renderDoneRow({ doneThreads: [thread] }); + + fireEvent.click(screen.getByRole("button", { name: "Delete done threads" })); + fireEvent.click(screen.getByRole("button", { name: "Delete" })); + + expect(worktreeActions.deleteWorktreeGroup).toHaveBeenCalledWith( + project.id, + thread.worktreePath, + [thread.id], + ); + expect(threadActions.deleteThread).not.toHaveBeenCalled(); + }); + + it("removes a worktree when every sibling is done", () => { + useSharedSettings.setState({ threadRemoveAction: "delete" }); + const worktreePath = "C:\\repo\\.poracode\\worktrees\\feature"; + const threads = [ + makeThread("done-1", { worktreePath }), + makeThread("done-2", { worktreePath }), + ]; + renderDoneRow({ doneThreads: threads }); + + fireEvent.click(screen.getByRole("button", { name: "Delete done threads" })); + fireEvent.click(screen.getByRole("button", { name: "Delete" })); + + expect(worktreeActions.deleteWorktreeGroup).toHaveBeenCalledWith(project.id, worktreePath, [ + "done-1", + "done-2", + ]); + expect(threadActions.deleteThread).not.toHaveBeenCalled(); + }); + + it("preserves a worktree that still has a retained sibling", () => { + useSharedSettings.setState({ threadRemoveAction: "delete" }); + const worktreePath = "C:\\repo\\.poracode\\worktrees\\feature"; + const doneThread = makeThread("done-1", { worktreePath }); + const activeThread = makeThread("active-1", { worktreePath, done: false }); + renderDoneRow({ doneThreads: [doneThread], allThreads: [doneThread, activeThread] }); + + fireEvent.click(screen.getByRole("button", { name: "Delete done threads" })); + fireEvent.click(screen.getByRole("button", { name: "Delete" })); + + expect(threadActions.deleteThread).toHaveBeenCalledWith(doneThread.id); + expect(worktreeActions.deleteWorktreeGroup).not.toHaveBeenCalled(); + }); + + it("uses one visible keyboard trigger and restores focus after Escape", async () => { + renderDoneRow(); + + const triggers = screen.getAllByRole("button", { name: "Archive done threads" }); + expect(triggers).toHaveLength(1); + const trigger = triggers[0]!; + act(() => trigger.focus()); + expect(trigger).toHaveFocus(); + fireEvent.keyDown(trigger, { key: "Enter", code: "Enter" }); + fireEvent.keyUp(trigger, { key: "Enter", code: "Enter" }); + + expect(await screen.findByRole("dialog")).toBeInTheDocument(); + fireEvent.keyDown(screen.getByRole("dialog"), { key: "Escape", code: "Escape" }); + + await vi.waitFor(() => expect(screen.queryByRole("dialog")).not.toBeInTheDocument()); + await vi.waitFor(() => expect(trigger).toHaveFocus()); + }); + + it("explains that experiment candidates remain outside the batch", () => { + renderDoneRow({ hasProtectedDoneThreads: true }); + + fireEvent.click(screen.getByRole("button", { name: "Archive done threads" })); + expect( + screen.getByText( + "Experiment candidates will remain; all other threads in Done will be archived.", + ), + ).toBeInTheDocument(); + }); + + it("hides the action when Done contains only protected experiment candidates", () => { + renderDoneRow({ hasProtectedDoneThreads: true, doneThreads: [] }); + + expect(screen.queryByRole("button")).not.toBeInTheDocument(); + }); +}); diff --git a/src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx b/src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx index 7e5c42c20..0e5e37883 100644 --- a/src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx +++ b/src/renderer/views/MainView/parts/Sidebar/parts/SidebarThreadRow.tsx @@ -1,8 +1,15 @@ +import { useState } from "react"; import { useLingui } from "@lingui/react/macro"; -import { ChevronDown } from "lucide-react"; -import type { Project } from "@/shared/contracts"; +import { Archive, ChevronDown, Trash2 } from "lucide-react"; +import type { Project, Thread } from "@/shared/contracts"; +import { archiveThread, deleteThread } from "@/renderer/actions/threadActions"; +import { deleteWorktreeGroup } from "@/renderer/actions/worktreeActions"; +import { Button } from "@/renderer/components/common/Button"; +import { ConfirmationPopover } from "@/renderer/components/common/ConfirmationPopover"; import { SidebarButton } from "@/renderer/components/common/SidebarButton"; import { chatRowRailClass } from "@/renderer/components/thread/ChatPane/parts/items/chatRow"; +import { useAppStore } from "@/renderer/state/appStore"; +import { useSharedSettings } from "@/renderer/state/sharedSettingsStore"; import type { SidebarRow } from "./sidebarProjectRows"; import { SidebarThreadGroup } from "./SidebarThreadGroup"; import { SidebarWorktreeGroup } from "./SidebarWorktreeGroup"; @@ -20,6 +27,94 @@ export function SeeMoreThreadsButton(props: { onPress: () => void }) { ); } +function deleteDoneThreads(doneThreads: Thread[]): void { + const doneThreadIds = new Set(doneThreads.map((thread) => thread.id)); + const allThreads = useAppStore.getState().threads; + const deletedWorktrees = new Set(); + + for (const thread of doneThreads) { + if (!thread.worktreePath) { + deleteThread(thread.id); + continue; + } + + const worktreeKey = `${thread.projectId}\0${thread.worktreePath}`; + if (deletedWorktrees.has(worktreeKey)) continue; + + const siblings = allThreads.filter( + (candidate) => + candidate.projectId === thread.projectId && candidate.worktreePath === thread.worktreePath, + ); + if (siblings.every((candidate) => doneThreadIds.has(candidate.id))) { + deletedWorktrees.add(worktreeKey); + deleteWorktreeGroup( + thread.projectId, + thread.worktreePath, + siblings.map((candidate) => candidate.id), + ); + } else { + deleteThread(thread.id); + } + } +} + +function DoneSectionLabel(props: { row: Extract }) { + const { row } = props; + const { t } = useLingui(); + const [isOpen, setIsOpen] = useState(false); + const threadRemoveAction = useSharedSettings((state) => state.threadRemoveAction); + const isArchive = threadRemoveAction === "archive"; + const actionLabel = isArchive ? t`Archive done threads` : t`Delete done threads`; + + const removeDoneThreads = () => { + for (const thread of row.doneThreads) { + if (isArchive) archiveThread(thread.id); + } + if (!isArchive) deleteDoneThreads(row.doneThreads); + setIsOpen(false); + }; + + return ( +
+ {t(row.label)} + {row.doneThreads.length > 0 ? ( + + {isArchive ? : } + + } + /> + ) : null} +
+ ); +} + /** * Renders one prebuilt sidebar row (thread, group, or section label). Shared by * the per-project list and the flat cross-project list — the caller resolves @@ -34,7 +129,6 @@ export function SidebarThreadRow(props: { projectTag?: React.ReactNode; }) { const { row, project, editingThreadId, setEditingThreadId, projectTag } = props; - const { t } = useLingui(); if (row.kind === "thread") { const item = ( @@ -84,9 +178,7 @@ export function SidebarThreadRow(props: { {...(projectTag !== undefined ? { projectTag } : {})} /> ) : ( -
- {t(row.label)} -
+ )} ); diff --git a/src/renderer/views/MainView/parts/Sidebar/parts/SortableThreadItem/parts/ThreadItemSuffix.tsx b/src/renderer/views/MainView/parts/Sidebar/parts/SortableThreadItem/parts/ThreadItemSuffix.tsx index 8a6266a79..e6e2951e1 100644 --- a/src/renderer/views/MainView/parts/Sidebar/parts/SortableThreadItem/parts/ThreadItemSuffix.tsx +++ b/src/renderer/views/MainView/parts/Sidebar/parts/SortableThreadItem/parts/ThreadItemSuffix.tsx @@ -6,7 +6,11 @@ import { usePrState } from "@/renderer/state/gitSelectors"; import { handleKeyActivate } from "@/renderer/utils/a11y"; import { GitBadge } from "@/renderer/views/MainView/parts/Sidebar/parts/GitBadge"; import { SyncBadge } from "@/renderer/views/MainView/parts/Sidebar/parts/SyncBadge"; -import { archiveThread, deleteThread, markThreadDone } from "@/renderer/actions/threadActions"; +import { + archiveThread, + markThreadDone, + requestDeleteThread, +} from "@/renderer/actions/threadActions"; import { openFilesPanel, openGitReview } from "@/renderer/actions/panelActions"; import { openTerminal, openWorktreeTerminal } from "@/renderer/actions/terminalActions"; import { AnimatedTerminalIcon } from "@/renderer/components/common/AnimatedTerminalIcon"; @@ -200,11 +204,22 @@ function ThreadItemRemovalTime( const { thread, isExperimentCandidate, compact = false } = props; const { t } = useLingui(); const threadRemoveAction = useSharedSettings((s) => s.threadRemoveAction); - const removeThread = () => { + const removeThread = (anchorElement?: HTMLElement) => { if (threadRemoveAction === "archive") { archiveThread(thread.id); } else { - deleteThread(thread.id, thread.worktreePath, thread.projectId); + const rect = anchorElement?.getBoundingClientRect(); + requestDeleteThread(thread.id, thread.worktreePath, thread.projectId, { + ...(anchorElement ? { returnFocusElement: anchorElement } : {}), + ...(rect + ? { + anchorPosition: { + x: rect.right, + y: rect.top + rect.height / 2, + }, + } + : {}), + }); } }; const removeLabel = @@ -228,12 +243,16 @@ function ThreadItemRemovalTime( role="button" tabIndex={0} aria-label={removeLabel} - className={`absolute inset-0 flex items-center justify-center rounded text-muted/55 opacity-0 transition group-hover:opacity-100 ${threadRemoveAction === "archive" ? "hover:bg-[var(--row-hover)] hover:text-warning" : "hover:bg-[var(--row-hover)] hover:text-danger"}`} + className={`absolute inset-0 flex items-center justify-center rounded text-muted/55 opacity-0 transition group-hover:opacity-100 focus-visible:opacity-100 ${threadRemoveAction === "archive" ? "hover:bg-[var(--row-hover)] hover:text-warning" : "hover:bg-[var(--row-hover)] hover:text-danger"}`} onClick={(event) => { event.stopPropagation(); - removeThread(); + removeThread(event.currentTarget); }} - onKeyDown={(event) => handleKeyActivate(event, removeThread, { stopPropagation: true })} + onKeyDown={(event) => + handleKeyActivate(event, () => removeThread(event.currentTarget), { + stopPropagation: true, + }) + } > {removeIcon} @@ -253,15 +272,15 @@ function ThreadItemRemovalTime( role="button" tabIndex={0} aria-label={removeLabel} - className={`absolute inset-0 flex items-center justify-center rounded text-muted/55 opacity-0 transition group-hover:opacity-100 ${threadRemoveAction === "archive" ? "hover:text-warning" : "hover:text-danger"}`} + className={`absolute inset-0 flex items-center justify-center rounded text-muted/55 opacity-0 transition group-hover:opacity-100 focus-visible:opacity-100 ${threadRemoveAction === "archive" ? "hover:text-warning" : "hover:text-danger"}`} onClick={(event) => { event.stopPropagation(); - removeThread(); + removeThread(event.currentTarget); }} onKeyDown={(event) => { if (event.key === "Enter" || event.key === " ") { event.stopPropagation(); - removeThread(); + removeThread(event.currentTarget); } }} > diff --git a/src/renderer/views/MainView/parts/Sidebar/parts/ThreadContextMenu.tsx b/src/renderer/views/MainView/parts/Sidebar/parts/ThreadContextMenu.tsx index 801745531..54a05b4ff 100644 --- a/src/renderer/views/MainView/parts/Sidebar/parts/ThreadContextMenu.tsx +++ b/src/renderer/views/MainView/parts/Sidebar/parts/ThreadContextMenu.tsx @@ -50,7 +50,7 @@ import { unloadThread, toggleMarkThreadDone, toggleStarThread, - deleteThread, + requestDeleteThread, continueInProvider, openNewThreadInWorktree, } from "@/renderer/actions/threadActions"; @@ -295,7 +295,7 @@ export function ThreadContextMenu(props: { ] : []), ]} - onAction={(key) => { + onAction={(key, anchorPosition, returnFocusElement) => { if (key === "new-thread-in-worktree" && thread.worktreePath) openNewThreadInWorktree({ projectId: thread.projectId, @@ -378,7 +378,10 @@ export function ThreadContextMenu(props: { if (key === "mark-done") toggleMarkThreadDone(thread.id); if (key === "toggle-star") toggleStarThread(thread.id); if (key === "delete" && !isExperimentCandidate) - deleteThread(thread.id, thread.worktreePath, thread.projectId); + requestDeleteThread(thread.id, thread.worktreePath, thread.projectId, { + ...(anchorPosition ? { anchorPosition } : {}), + ...(returnFocusElement ? { returnFocusElement } : {}), + }); if (key.startsWith("action:")) { runProjectAction(project.id, key.slice("action:".length), thread.worktreePath); } diff --git a/src/renderer/views/MainView/parts/Sidebar/parts/sidebarProjectRows.test.ts b/src/renderer/views/MainView/parts/Sidebar/parts/sidebarProjectRows.test.ts index 4df3c44f8..2112caa45 100644 --- a/src/renderer/views/MainView/parts/Sidebar/parts/sidebarProjectRows.test.ts +++ b/src/renderer/views/MainView/parts/Sidebar/parts/sidebarProjectRows.test.ts @@ -205,9 +205,34 @@ describe("buildSidebarProjectRows — See more cap (date sort)", () => { const visibleIds = threadRows(rows).map((r) => r.thread.id); expect(visibleIds).toHaveLength(10); expect(seeMore(rows)).toMatchObject({ hiddenCount: 3 }); + expect( + rows.find((row) => row.kind === "section-label")?.doneThreads.map((thread) => thread.id), + ).toEqual(["done-0", "done-1", "done-2", "done-3", "done-4"]); for (let i = 0; i < 8; i++) expect(visibleIds).toContain(`live-${i}`); }); + it("excludes experiment candidates from the Done batch action", () => { + const rows = buildSidebarProjectRows({ + projectId: "project-1", + projectThreads: [ + makeThread({ id: "ordinary", done: true }), + makeThread({ id: "candidate-1", done: true, groupId: "experiment-1" }), + makeThread({ id: "candidate-2", done: true, groupId: "experiment-1" }), + ], + sortMode: "updated", + collapsedWorktrees: {}, + visibleLimit: 10, + experimentCandidateOrder: new Map([ + ["candidate-1", 0], + ["candidate-2", 1], + ]), + }); + + const label = rows.find((row) => row.kind === "section-label"); + expect(label?.doneThreads.map((thread) => thread.id)).toEqual(["ordinary"]); + expect(label?.hasProtectedDoneThreads).toBe(true); + }); + it("hides candidate rows when the experiment group collapse key is set", () => { const groupedThreads = [ makeThread({ id: "candidate-1", groupId: "experiment-1", groupName: "Experiment" }), diff --git a/src/renderer/views/MainView/parts/Sidebar/parts/sidebarProjectRows.ts b/src/renderer/views/MainView/parts/Sidebar/parts/sidebarProjectRows.ts index 4443fd43a..80613bd19 100644 --- a/src/renderer/views/MainView/parts/Sidebar/parts/sidebarProjectRows.ts +++ b/src/renderer/views/MainView/parts/Sidebar/parts/sidebarProjectRows.ts @@ -38,7 +38,13 @@ export type SidebarRow = key: string; entry: Extract; } - | { kind: "section-label"; key: string; label: MessageDescriptor } + | { + kind: "section-label"; + key: string; + label: MessageDescriptor; + doneThreads: Thread[]; + hasProtectedDoneThreads: boolean; + } | { kind: "see-more"; key: string; hiddenCount: number }; /** Default number of list items shown per project before the "See more" row. */ @@ -325,7 +331,20 @@ export function buildSidebarProjectRows(input: { pushList(starredVisible); pushList(activeVisible, starredVisible.length); if (doneVisible.length > 0) { - rows.push({ kind: "section-label", key: "done-label", label: msg`Done` }); + const allDoneThreads = doneEntries.flatMap((entry) => + entry.kind === "thread" ? [entry.thread] : entry.group.threads, + ); + const candidateOrder = input.experimentCandidateOrder; + const doneThreads = candidateOrder + ? allDoneThreads.filter((thread) => !candidateOrder.has(thread.id)) + : allDoneThreads; + rows.push({ + kind: "section-label", + key: "done-label", + label: msg`Done`, + doneThreads, + hasProtectedDoneThreads: doneThreads.length < allDoneThreads.length, + }); } pushList(doneVisible, starredVisible.length + activeVisible.length); if (hiddenCount > 0) rows.push({ kind: "see-more", key: "see-more", hiddenCount }); diff --git a/src/renderer/views/MainView/parts/WorktreeDeleteDialogs.test.tsx b/src/renderer/views/MainView/parts/WorktreeDeleteDialogs.test.tsx index 7cb1b4010..5a5ca67f9 100644 --- a/src/renderer/views/MainView/parts/WorktreeDeleteDialogs.test.tsx +++ b/src/renderer/views/MainView/parts/WorktreeDeleteDialogs.test.tsx @@ -1,29 +1,47 @@ import { fireEvent, screen } from "@testing-library/react"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { renderWithI18n as render } from "@/renderer/testUtils/i18n"; -import type { Project } from "@/shared/contracts"; +import type { Project, Thread } from "@/shared/contracts"; import { useAppStore } from "@/renderer/state/appStore"; import { useWorktreeDeleteStore } from "@/renderer/state/worktreeDeleteStore"; import { WorktreeDeleteDialogs } from "./WorktreeDeleteDialogs"; -const { bridge, toast } = vi.hoisted(() => ({ +const { bridge, toast, deleteThread } = vi.hoisted(() => ({ bridge: { + closeThread: vi.fn<() => Promise>(), gitDeleteBranch: vi.fn<() => Promise>(), gitListBranches: vi.fn<() => Promise>(), }, toast: { danger: vi.fn<(message: string) => void>(), }, + deleteThread: vi.fn<(threadId: string, worktreePath?: string, projectId?: string) => void>(), })); +vi.mock("@/renderer/actions/threadActions", () => ({ deleteThread })); + vi.mock("@heroui/react", () => ({ toast })); vi.mock("@/renderer/bridge", () => ({ readBridge: () => bridge, })); -vi.mock("@/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog", () => ({ - DeleteWorktreeDialog: () => null, +vi.mock("@/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover", () => ({ + DeleteThreadPopover: (props: { + anchorPosition: { x: number; y: number }; + worktreeBranch?: string; + onDelete: () => void; + }) => ( +
+ + {props.anchorPosition.x},{props.anchorPosition.y} + + {props.worktreeBranch ?? "none"} + +
+ ), })); vi.mock("@/renderer/views/MainView/parts/Sidebar/parts/ForceDeleteBranchDialog", () => ({ @@ -49,9 +67,11 @@ const project: Project = { describe("WorktreeDeleteDialogs", () => { beforeEach(() => { + bridge.closeThread.mockReset().mockResolvedValue(undefined); bridge.gitDeleteBranch.mockReset().mockResolvedValue(undefined); bridge.gitListBranches.mockReset().mockResolvedValue([]); toast.danger.mockReset(); + deleteThread.mockReset(); useAppStore.setState({ projects: [project] }); useWorktreeDeleteStore.getState().setDialog({ kind: "branch-unmerged", @@ -61,6 +81,68 @@ describe("WorktreeDeleteDialogs", () => { }); }); + const worktreeThread: Thread = { + id: "thread-1", + projectId: project.id, + title: "Thread", + agentKind: "codex", + config: { model: "gpt-5.4" }, + status: "idle", + attention: "none", + canResumeWithConfig: false, + archived: false, + done: false, + starred: false, + createdAt: "2026-08-22T00:00:00.000Z", + updatedAt: "2026-08-22T00:00:00.000Z", + worktreePath: "/repo/.worktrees/feature", + worktreeBranch: "feature/popover", + }; + + it("anchors the confirmation and hands the worktree context to the delete action", () => { + useAppStore.setState({ threads: [worktreeThread] }); + useWorktreeDeleteStore.getState().setDialog({ + kind: "single-thread", + threadId: worktreeThread.id, + projectId: project.id, + worktreePath: worktreeThread.worktreePath!, + worktreeBranch: worktreeThread.worktreeBranch!, + anchorPosition: { x: 320, y: 140 }, + }); + render(); + + expect(screen.getByTestId("delete-anchor")).toHaveTextContent("320,140"); + expect(screen.getByTestId("delete-branch")).toHaveTextContent("feature/popover"); + fireEvent.click(screen.getByRole("button", { name: "delete" })); + + expect(deleteThread).toHaveBeenCalledWith( + worktreeThread.id, + worktreeThread.worktreePath, + project.id, + ); + expect(useWorktreeDeleteStore.getState().dialog).toBeNull(); + }); + + it("confirms a thread with no worktree to remove", () => { + const thread: Thread = { ...worktreeThread }; + delete thread.worktreePath; + delete thread.worktreeBranch; + useAppStore.setState({ threads: [thread] }); + useWorktreeDeleteStore.getState().setDialog({ + kind: "single-thread", + threadId: thread.id, + projectId: project.id, + anchorPosition: { x: 320, y: 140 }, + }); + render(); + + expect(screen.getByTestId("delete-branch")).toHaveTextContent("none"); + fireEvent.click(screen.getByRole("button", { name: "delete" })); + + expect(deleteThread).toHaveBeenCalledWith(thread.id, undefined, project.id); + expect(useWorktreeDeleteStore.getState().dialog).toBeNull(); + }); + it("keeps the force-delete dialog open when the remote command fails", async () => { bridge.gitDeleteBranch.mockRejectedValueOnce(new Error("remote server offline")); render(); diff --git a/src/renderer/views/MainView/parts/WorktreeDeleteDialogs.tsx b/src/renderer/views/MainView/parts/WorktreeDeleteDialogs.tsx index da36b8598..f2ffe0113 100644 --- a/src/renderer/views/MainView/parts/WorktreeDeleteDialogs.tsx +++ b/src/renderer/views/MainView/parts/WorktreeDeleteDialogs.tsx @@ -1,11 +1,10 @@ -import { DeleteWorktreeDialog } from "@/renderer/views/MainView/parts/Sidebar/parts/DeleteWorktreeDialog"; +import { DeleteThreadPopover } from "@/renderer/views/MainView/parts/Sidebar/parts/DeleteThreadPopover"; import { ForceDeleteBranchDialog } from "@/renderer/views/MainView/parts/Sidebar/parts/ForceDeleteBranchDialog"; -import { useAppStore } from "@/renderer/state/appStore"; import { useWorktreeDeleteStore } from "@/renderer/state/worktreeDeleteStore"; import { deleteThread } from "@/renderer/actions/threadActions"; -import { deleteWorktreeGroup, forceDeleteBranch } from "@/renderer/actions/worktreeActions"; +import { forceDeleteBranch } from "@/renderer/actions/worktreeActions"; export type { WorktreeDeleteDialogState } from "@/renderer/state/worktreeDeleteStore"; @@ -16,27 +15,24 @@ export function WorktreeDeleteDialogs() { return ( <> {worktreeDeleteDialog?.kind === "single-thread" && ( - { - deleteThread(worktreeDeleteDialog.threadId); - closeDialog(); - }} - onDeleteThreadAndWorktree={() => { - // Delete this thread + all siblings sharing the worktree - const siblings = useAppStore - .getState() - .threads.filter( - (t) => - t.worktreePath === worktreeDeleteDialog.worktreePath && - t.id !== worktreeDeleteDialog.threadId, - ); - deleteWorktreeGroup(worktreeDeleteDialog.projectId, worktreeDeleteDialog.worktreePath, [ + onDelete={() => { + // Re-resolved against the live store: `deleteThread` keeps the + // worktree if a sibling thread appeared while this was open. + deleteThread( worktreeDeleteDialog.threadId, - ...siblings.map((thread) => thread.id), - ]); + worktreeDeleteDialog.worktreePath, + worktreeDeleteDialog.projectId, + ); closeDialog(); }} /> diff --git a/src/renderer/views/SettingsOverlay/parts/ThreadSettings.test.tsx b/src/renderer/views/SettingsOverlay/parts/ThreadSettings.test.tsx index 6d05ca253..97567db3a 100644 --- a/src/renderer/views/SettingsOverlay/parts/ThreadSettings.test.tsx +++ b/src/renderer/views/SettingsOverlay/parts/ThreadSettings.test.tsx @@ -1,6 +1,10 @@ -import { screen } from "@testing-library/react"; +import { fireEvent, screen } from "@testing-library/react"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { renderWithI18n as render } from "@/renderer/testUtils/i18n"; +import { + setConfirmThreadDelete, + shouldConfirmThreadDelete, +} from "@/renderer/state/threadDeletePreference"; const bridgeMock = vi.hoisted(() => ({ isRemoteSession: vi.fn<() => boolean>(() => false), @@ -15,6 +19,7 @@ import { ThreadSettings } from "./ThreadSettings"; describe("ThreadSettings", () => { beforeEach(() => { bridgeMock.isRemoteSession.mockReturnValue(false); + localStorage.clear(); }); it("shows desktop thread lifecycle controls in local sessions", () => { @@ -23,6 +28,7 @@ describe("ThreadSettings", () => { expect(screen.getByText("Unload idle threads after")).toBeInTheDocument(); expect(screen.getByText("Auto-archive done threads after")).toBeInTheDocument(); expect(screen.getByText("Default thread removal")).toBeInTheDocument(); + expect(screen.getByText("Confirm before deleting threads")).toBeInTheDocument(); }); it("hides desktop thread lifecycle controls in remote sessions", () => { @@ -33,5 +39,21 @@ describe("ThreadSettings", () => { expect(screen.queryByText("Unload idle threads after")).not.toBeInTheDocument(); expect(screen.queryByText("Auto-archive done threads after")).not.toBeInTheDocument(); expect(screen.queryByText("Default thread removal")).not.toBeInTheDocument(); + expect(screen.queryByText("Confirm before deleting threads")).not.toBeInTheDocument(); + }); + + it("lets users restore the delete confirmation", () => { + setConfirmThreadDelete(false); + render(); + + const confirmation = screen.getByRole("switch", { + name: "Confirm before deleting threads", + }); + expect(confirmation).not.toBeChecked(); + + fireEvent.click(confirmation); + + expect(confirmation).toBeChecked(); + expect(shouldConfirmThreadDelete()).toBe(true); }); }); diff --git a/src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx b/src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx index d50367cc0..b1dc4aea3 100644 --- a/src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx +++ b/src/renderer/views/SettingsOverlay/parts/ThreadSettings.tsx @@ -1,9 +1,13 @@ -import { startTransition } from "react"; +import { startTransition, useState } from "react"; import { NumberField } from "@heroui/react"; import { Trans, useLingui } from "@lingui/react/macro"; import type { ThreadRemoveAction } from "@/shared/contracts"; import { isRemoteSession } from "@/renderer/bridge"; import { useSharedSettings } from "@/renderer/state/sharedSettingsStore"; +import { + setConfirmThreadDelete, + shouldConfirmThreadDelete, +} from "@/renderer/state/threadDeletePreference"; import { Select, ToggleSwitch } from "@/renderer/components/common"; import { SettingRow, SettingsPage } from "./SettingsForm"; import { threadRemoveActionOptions, useLocalizedOptions } from "./settingsOptions"; @@ -22,6 +26,7 @@ export function ThreadSettings() { const setThreadRemoveAction = useSharedSettings((state) => state.setThreadRemoveAction); const autoMarkDoneOnPrMerge = useSharedSettings((state) => state.autoMarkDoneOnPrMerge); const setAutoMarkDoneOnPrMerge = useSharedSettings((state) => state.setAutoMarkDoneOnPrMerge); + const [confirmThreadDelete, setConfirmThreadDeleteState] = useState(shouldConfirmThreadDelete); // Idle unloading and launch-time auto-archive run on the desktop; a remote // session's copy of these values is never read, so hide the rows there. const remote = isRemoteSession(); @@ -138,6 +143,23 @@ export function ThreadSettings() { /> )} + + {!remote && ( + Show a confirmation before permanently deleting a thread.} + > + { + setConfirmThreadDelete(selected); + setConfirmThreadDeleteState(selected); + }} + /> + + )} ); } diff --git a/src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.test.ts b/src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.test.ts index 863216362..4e636b931 100644 --- a/src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.test.ts +++ b/src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.test.ts @@ -133,6 +133,9 @@ describe("searchSettings", () => { expect( searchSettings("quick remove", t, { remoteSession: true }).map((r) => r.anchor), ).not.toContain("threads.defaultThreadRemoval"); + expect( + searchSettings("confirm delete", t, { remoteSession: true }).map((r) => r.anchor), + ).not.toContain("threads.confirmThreadDelete"); expect(searchSettings("panel", t, { remoteSession: true }).map((r) => r.anchor)).not.toContain( "terminal.terminalPosition", ); diff --git a/src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts b/src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts index 318eacbbc..0ea085c99 100644 --- a/src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts +++ b/src/renderer/views/SettingsOverlay/parts/settingsSearchIndex.ts @@ -323,6 +323,14 @@ export const SETTINGS_SEARCH_INDEX: readonly SettingsSearchEntry[] = [ keywords: "default thread removal delete archive quick remove sidebar", desktopOnly: true, }, + { + section: "threads", + anchor: "threads.confirmThreadDelete", + title: msg`Confirm before deleting threads`, + description: msg`Show a confirmation before permanently deleting a thread.`, + keywords: "confirm delete thread worktree remove ask warning", + desktopOnly: true, + }, // Git {