From babd7cd3254497943c753c458a197d444b38b1eb Mon Sep 17 00:00:00 2001 From: Bruno Bergher Date: Fri, 23 Jan 2026 16:31:01 +0000 Subject: [PATCH 01/11] Delete modal --- src/package.json | 14 ++++++- webview-ui/src/components/ui/dialog.tsx | 6 +-- .../worktrees/DeleteWorktreeModal.tsx | 42 ++++++++----------- webview-ui/src/i18n/locales/en/worktrees.json | 5 +-- webview-ui/src/index.css | 2 +- 5 files changed, 36 insertions(+), 33 deletions(-) diff --git a/src/package.json b/src/package.json index fe9c4fe6d16..727f3d232ad 100644 --- a/src/package.json +++ b/src/package.json @@ -244,9 +244,14 @@ "when": "view == roo-cline.SidebarProvider" }, { - "command": "roo-cline.popoutButtonClicked", + "command": "roo-cline.worktreesButtonClicked", "group": "overflow@2", "when": "view == roo-cline.SidebarProvider" + }, + { + "command": "roo-cline.popoutButtonClicked", + "group": "overflow@3", + "when": "view == roo-cline.SidebarProvider" } ], "editor/title": [ @@ -276,9 +281,14 @@ "when": "activeWebviewPanelId == roo-cline.TabPanelProvider" }, { - "command": "roo-cline.popoutButtonClicked", + "command": "roo-cline.worktreesButtonClicked", "group": "overflow@2", "when": "activeWebviewPanelId == roo-cline.TabPanelProvider" + }, + { + "command": "roo-cline.popoutButtonClicked", + "group": "overflow@3", + "when": "activeWebviewPanelId == roo-cline.TabPanelProvider" } ] }, diff --git a/webview-ui/src/components/ui/dialog.tsx b/webview-ui/src/components/ui/dialog.tsx index 83efd07e9ee..72e638d0c9c 100644 --- a/webview-ui/src/components/ui/dialog.tsx +++ b/webview-ui/src/components/ui/dialog.tsx @@ -40,12 +40,12 @@ function DialogContent({ className, children, ...props }: React.ComponentProps {children} - + Close @@ -68,7 +68,7 @@ function DialogFooter({ className, ...props }: React.ComponentProps<"div">) { return (
) diff --git a/webview-ui/src/components/worktrees/DeleteWorktreeModal.tsx b/webview-ui/src/components/worktrees/DeleteWorktreeModal.tsx index 0df8541e111..9e4fbcda2ac 100644 --- a/webview-ui/src/components/worktrees/DeleteWorktreeModal.tsx +++ b/webview-ui/src/components/worktrees/DeleteWorktreeModal.tsx @@ -4,16 +4,8 @@ import type { Worktree } from "@roo-code/types" import { vscode } from "@/utils/vscode" import { useAppTranslation } from "@/i18n/TranslationContext" -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, - Button, - Checkbox, -} from "@/components/ui" +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, Button, Checkbox } from "@/components/ui" +import { Folder, GitBranch, TriangleAlert } from "lucide-react" interface DeleteWorktreeModalProps { open: boolean @@ -63,33 +55,35 @@ export const DeleteWorktreeModal = ({ open, onClose, worktree, onSuccess }: Dele !isOpen && onClose()}> -
- - {t("worktrees:deleteWorktree")} -
- {t("worktrees:deleteWorktreeDescription")} + {t("worktrees:deleteWorktree")}
{/* Worktree info */} -
-
- - +
+

+ + {worktree.branch || (worktree.isDetached ? t("worktrees:detachedHead") : t("worktrees:noBranch"))} -

-
{worktree.path}
+

+ +

+ + + {worktree.path} + +

{/* Warning message */} -
- +
+

{t("worktrees:deleteWarning")}

    -
  • • {t("worktrees:deleteWarningBranch", { branch: worktree.branch || "HEAD" })}
  • +
  • • {t("worktrees:deleteWarningBranch")}
  • • {t("worktrees:deleteWarningFiles")}
diff --git a/webview-ui/src/i18n/locales/en/worktrees.json b/webview-ui/src/i18n/locales/en/worktrees.json index 9ab0f9dfc41..820818ccc50 100644 --- a/webview-ui/src/i18n/locales/en/worktrees.json +++ b/webview-ui/src/i18n/locales/en/worktrees.json @@ -47,9 +47,8 @@ "cancel": "Cancel", "deleteWorktree": "Delete Worktree", - "deleteWorktreeDescription": "This will remove the worktree and all its files.", - "deleteWarning": "This action cannot be undone. The following will be deleted:", - "deleteWarningBranch": "The branch '{{branch}}' and all uncommitted changes", + "deleteWarning": "This can't be undone. It will delete:", + "deleteWarningBranch": "The branch and any uncommitted changes", "deleteWarningFiles": "All files in the worktree directory", "forceDelete": "Force delete", "worktreeIsLocked": "worktree is locked", diff --git a/webview-ui/src/index.css b/webview-ui/src/index.css index 28dbf06aef1..2395b69f57e 100644 --- a/webview-ui/src/index.css +++ b/webview-ui/src/index.css @@ -163,7 +163,7 @@ --accent: var(--vscode-list-hoverBackground); --accent-foreground: var(--vscode-list-hoverForeground); --destructive: var(--vscode-errorForeground); - --destructive-foreground: var(--vscode-button-foreground); + --destructive-foreground: var(--vscode-editor-background); --border: var(--vscode-input-border, transparent); /* --border gets theme value or transparent fallback */ --input: var(--vscode-input-background); --ring: var(--vscode-input-border); From 204b8cc7c045fc415924a36d197bb27dbaa550b3 Mon Sep 17 00:00:00 2001 From: Bruno Bergher Date: Sat, 24 Jan 2026 11:21:44 +0000 Subject: [PATCH 02/11] Restructured --- webview-ui/src/App.tsx | 5 +- webview-ui/src/components/chat/ChatView.tsx | 3 + .../src/components/chat/WorktreeSelector.tsx | 173 ++++++++ .../chat/__tests__/WorktreeSelector.spec.tsx | 310 ++++++++++++++ .../src/components/settings/SettingsView.tsx | 9 +- webview-ui/src/components/ui/button.tsx | 2 +- .../worktrees/DeleteWorktreeModal.tsx | 15 +- .../components/worktrees/MergeResultModal.tsx | 89 ++++ .../worktrees/MergeWorktreeModal.tsx | 89 ++++ .../components/worktrees/WorktreesView.tsx | 394 +++++++----------- webview-ui/src/i18n/locales/en/settings.json | 1 + webview-ui/src/i18n/locales/en/worktrees.json | 20 +- 12 files changed, 837 insertions(+), 273 deletions(-) create mode 100644 webview-ui/src/components/chat/WorktreeSelector.tsx create mode 100644 webview-ui/src/components/chat/__tests__/WorktreeSelector.spec.tsx create mode 100644 webview-ui/src/components/worktrees/MergeResultModal.tsx create mode 100644 webview-ui/src/components/worktrees/MergeWorktreeModal.tsx diff --git a/webview-ui/src/App.tsx b/webview-ui/src/App.tsx index b5de22978ba..cccb0422ca8 100644 --- a/webview-ui/src/App.tsx +++ b/webview-ui/src/App.tsx @@ -20,12 +20,11 @@ import { CheckpointRestoreDialog } from "./components/chat/CheckpointRestoreDial import { DeleteMessageDialog, EditMessageDialog } from "./components/chat/MessageModificationConfirmationDialog" import ErrorBoundary from "./components/ErrorBoundary" import { CloudView } from "./components/cloud/CloudView" -import { WorktreesView } from "./components/worktrees" import { useAddNonInteractiveClickListener } from "./components/ui/hooks/useNonInteractiveClick" import { TooltipProvider } from "./components/ui/tooltip" import { STANDARD_TOOLTIP_DELAY } from "./components/ui/standard-tooltip" -type Tab = "settings" | "history" | "chat" | "marketplace" | "cloud" | "worktrees" +type Tab = "settings" | "history" | "chat" | "marketplace" | "cloud" interface DeleteMessageDialogState { isOpen: boolean @@ -51,7 +50,6 @@ const tabsByMessageAction: Partial { @@ -247,7 +245,6 @@ const App = () => { organizations={cloudOrganizations} /> )} - {tab === "worktrees" && switchTab("chat")} />} } {/* Everyone should see their task history if any */} {taskHistory.length > 0 && } + {/* Worktree selector for quick switching between worktrees */} +
{/* Logged out users should see a one-time upsell, but not for brand new users */} {!cloudIsAuthenticated && taskHistory.length >= 6 && ( diff --git a/webview-ui/src/components/chat/WorktreeSelector.tsx b/webview-ui/src/components/chat/WorktreeSelector.tsx new file mode 100644 index 00000000000..37d12983c95 --- /dev/null +++ b/webview-ui/src/components/chat/WorktreeSelector.tsx @@ -0,0 +1,173 @@ +import React, { useState, useCallback, useEffect, useMemo } from "react" +import { GitBranch, Check } from "lucide-react" + +import type { Worktree, WorktreeListResponse } from "@roo-code/types" + +import { cn } from "@/lib/utils" +import { useRooPortal } from "@/components/ui/hooks/useRooPortal" +import { Popover, PopoverContent, PopoverTrigger, StandardTooltip } from "@/components/ui" +import { useAppTranslation } from "@/i18n/TranslationContext" +import { vscode } from "@/utils/vscode" + +import { IconButton } from "./IconButton" + +interface WorktreeSelectorProps { + disabled?: boolean +} + +export const WorktreeSelector = ({ disabled = false }: WorktreeSelectorProps) => { + const { t } = useAppTranslation() + const [open, setOpen] = useState(false) + const [worktrees, setWorktrees] = useState([]) + const [isGitRepo, setIsGitRepo] = useState(true) + const portalContainer = useRooPortal("roo-portal") + + // Find current worktree + const currentWorktree = useMemo(() => worktrees.find((w) => w.isCurrent), [worktrees]) + + // Fetch worktrees when popover opens + const fetchWorktrees = useCallback(() => { + vscode.postMessage({ type: "listWorktrees" }) + }, []) + + // Handle messages from extension + useEffect(() => { + const handleMessage = (event: MessageEvent) => { + const message = event.data + if (message.type === "worktreeList") { + const response: WorktreeListResponse = message + setWorktrees(response.worktrees || []) + setIsGitRepo(response.isGitRepo) + } + } + + window.addEventListener("message", handleMessage) + return () => window.removeEventListener("message", handleMessage) + }, []) + + // Initial fetch and refresh on open + useEffect(() => { + fetchWorktrees() + }, [fetchWorktrees]) + + useEffect(() => { + if (open) { + fetchWorktrees() + } + }, [open, fetchWorktrees]) + + const handleSelect = useCallback((worktreePath: string) => { + vscode.postMessage({ + type: "switchWorktree", + worktreePath: worktreePath, + worktreeNewWindow: false, + }) + setOpen(false) + }, []) + + const handleSettingsClick = useCallback(() => { + vscode.postMessage({ + type: "switchTab", + tab: "settings", + values: { section: "worktrees" }, + }) + setOpen(false) + }, []) + + // Don't render if not a git repo or only one worktree + if (!isGitRepo || worktrees.length <= 1) { + return null + } + + const title = t("worktrees:selector.tooltip") + const instructionText = t("worktrees:selector.description") + + return ( + + + + + {currentWorktree?.branch || t("worktrees:noBranch")} + + + +
+ {/* Info blurb */} +
+

{instructionText}

+
+ + {/* Worktree list */} +
+ {worktrees.map((worktree) => { + const isSelected = worktree.isCurrent + return ( +
!isSelected && handleSelect(worktree.path)} + data-testid="worktree-selector-item" + className={cn( + "px-3 py-1.5 text-sm cursor-pointer flex items-center", + "hover:bg-vscode-list-hoverBackground", + isSelected && + "bg-vscode-list-activeSelectionBackground text-vscode-list-activeSelectionForeground", + )}> +
+
+ + + {worktree.branch || t("worktrees:noBranch")} + + {worktree.isBare && ( + {t("worktrees:primary")} + )} +
+
+ {worktree.path} +
+
+ {isSelected && } +
+ ) + })} +
+ + {/* Bottom bar with settings cog and title */} +
+
+ +
+ + {/* Info icon and title on the right */} +
+ + + +

+ {t("worktrees:selector.title")} +

+
+
+
+
+
+ ) +} diff --git a/webview-ui/src/components/chat/__tests__/WorktreeSelector.spec.tsx b/webview-ui/src/components/chat/__tests__/WorktreeSelector.spec.tsx new file mode 100644 index 00000000000..74edf196871 --- /dev/null +++ b/webview-ui/src/components/chat/__tests__/WorktreeSelector.spec.tsx @@ -0,0 +1,310 @@ +import { render, screen, fireEvent, act } from "@/utils/test-utils" + +import type { Worktree, WorktreeListResponse } from "@roo-code/types" + +import { WorktreeSelector } from "../WorktreeSelector" + +const mockPostMessage = vi.fn() + +vi.mock("@/utils/vscode", () => ({ + vscode: { + postMessage: (...args: unknown[]) => mockPostMessage(...args), + }, +})) + +vi.mock("@/i18n/TranslationContext", () => ({ + useAppTranslation: () => ({ + t: (key: string) => key, + }), +})) + +vi.mock("@/components/ui/hooks/useRooPortal", () => ({ + useRooPortal: () => document.body, +})) + +const mockWorktrees: Worktree[] = [ + { + path: "/path/to/main", + branch: "main", + commitHash: "abc123", + isCurrent: true, + isBare: true, + isDetached: false, + isLocked: false, + }, + { + path: "/path/to/feature-branch", + branch: "feature-branch", + commitHash: "def456", + isCurrent: false, + isBare: false, + isDetached: false, + isLocked: false, + }, + { + path: "/path/to/another-branch", + branch: "another-branch", + commitHash: "ghi789", + isCurrent: false, + isBare: false, + isDetached: false, + isLocked: false, + }, +] + +const simulateWorktreeListMessage = (worktrees: Worktree[], isGitRepo: boolean = true) => { + const message: Partial & { type: string } = { + type: "worktreeList", + worktrees, + isGitRepo, + isMultiRoot: false, + isSubfolder: false, + gitRootPath: "/path/to/repo", + } + + act(() => { + window.dispatchEvent(new MessageEvent("message", { data: message })) + }) +} + +describe("WorktreeSelector", () => { + beforeEach(() => { + mockPostMessage.mockClear() + }) + + test("requests worktrees on mount", () => { + render() + + expect(mockPostMessage).toHaveBeenCalledWith({ type: "listWorktrees" }) + }) + + test("does not render when not a git repo", () => { + const { container } = render() + + simulateWorktreeListMessage([], false) + + expect(container.querySelector('[data-testid="worktree-selector-trigger"]')).not.toBeInTheDocument() + }) + + test("does not render when only one worktree exists", () => { + const { container } = render() + + simulateWorktreeListMessage([mockWorktrees[0]]) + + expect(container.querySelector('[data-testid="worktree-selector-trigger"]')).not.toBeInTheDocument() + }) + + test("renders trigger when multiple worktrees exist", () => { + render() + + simulateWorktreeListMessage(mockWorktrees) + + expect(screen.getByTestId("worktree-selector-trigger")).toBeInTheDocument() + }) + + test("shows current branch name on trigger", () => { + render() + + simulateWorktreeListMessage(mockWorktrees) + + const trigger = screen.getByTestId("worktree-selector-trigger") + expect(trigger).toHaveTextContent("main") + }) + + test("opens popover and shows all worktrees when clicked", () => { + render() + + simulateWorktreeListMessage(mockWorktrees) + + fireEvent.click(screen.getByTestId("worktree-selector-trigger")) + + // Should show all worktree items + const items = screen.getAllByTestId("worktree-selector-item") + expect(items).toHaveLength(3) + }) + + test("shows worktree branch names and paths in popover", () => { + render() + + simulateWorktreeListMessage(mockWorktrees) + + fireEvent.click(screen.getByTestId("worktree-selector-trigger")) + + // "main" appears twice: once in trigger and once in popover list + expect(screen.getAllByText("main").length).toBeGreaterThanOrEqual(2) + expect(screen.getByText("feature-branch")).toBeInTheDocument() + expect(screen.getByText("another-branch")).toBeInTheDocument() + expect(screen.getByText("/path/to/main")).toBeInTheDocument() + expect(screen.getByText("/path/to/feature-branch")).toBeInTheDocument() + }) + + test("shows primary badge on primary worktree", () => { + render() + + simulateWorktreeListMessage(mockWorktrees) + + fireEvent.click(screen.getByTestId("worktree-selector-trigger")) + + expect(screen.getByText("worktrees:primary")).toBeInTheDocument() + }) + + test("sends switch message when selecting a different worktree", () => { + render() + + simulateWorktreeListMessage(mockWorktrees) + + fireEvent.click(screen.getByTestId("worktree-selector-trigger")) + + // Click on feature-branch worktree + const items = screen.getAllByTestId("worktree-selector-item") + fireEvent.click(items[1]) // Second item is feature-branch + + expect(mockPostMessage).toHaveBeenCalledWith({ + type: "switchWorktree", + worktreePath: "/path/to/feature-branch", + worktreeNewWindow: false, + }) + }) + + test("does not send switch message when selecting current worktree", () => { + render() + + simulateWorktreeListMessage(mockWorktrees) + + fireEvent.click(screen.getByTestId("worktree-selector-trigger")) + + mockPostMessage.mockClear() + + // Click on current worktree (main) + const items = screen.getAllByTestId("worktree-selector-item") + fireEvent.click(items[0]) + + expect(mockPostMessage).not.toHaveBeenCalledWith( + expect.objectContaining({ + type: "switchWorktree", + }), + ) + }) + + test("shows settings button in footer", () => { + render() + + simulateWorktreeListMessage(mockWorktrees) + + fireEvent.click(screen.getByTestId("worktree-selector-trigger")) + + // Check for settings gear icon button + const settingsButton = document.querySelector(".codicon-settings-gear") + expect(settingsButton).toBeInTheDocument() + }) + + test("navigates to worktree settings when settings button clicked", () => { + render() + + simulateWorktreeListMessage(mockWorktrees) + + fireEvent.click(screen.getByTestId("worktree-selector-trigger")) + + // Find and click the settings button + const settingsButton = document.querySelector(".codicon-settings-gear") + expect(settingsButton).toBeInTheDocument() + + fireEvent.click(settingsButton!.closest("button")!) + + expect(mockPostMessage).toHaveBeenCalledWith({ + type: "switchTab", + tab: "settings", + values: { section: "worktrees" }, + }) + }) + + test("shows info icon with tooltip in footer", () => { + render() + + simulateWorktreeListMessage(mockWorktrees) + + fireEvent.click(screen.getByTestId("worktree-selector-trigger")) + + const infoIcon = document.querySelector(".codicon-info") + expect(infoIcon).toBeInTheDocument() + }) + + test("shows title in footer", () => { + render() + + simulateWorktreeListMessage(mockWorktrees) + + fireEvent.click(screen.getByTestId("worktree-selector-trigger")) + + expect(screen.getByText("worktrees:selector.title")).toBeInTheDocument() + }) + + test("shows description in popover", () => { + render() + + simulateWorktreeListMessage(mockWorktrees) + + fireEvent.click(screen.getByTestId("worktree-selector-trigger")) + + expect(screen.getByText("worktrees:selector.description")).toBeInTheDocument() + }) + + test("is disabled when disabled prop is true", () => { + render() + + simulateWorktreeListMessage(mockWorktrees) + + const trigger = screen.getByTestId("worktree-selector-trigger") + expect(trigger).toBeDisabled() + }) + + test("refreshes worktrees when popover opens", () => { + render() + + simulateWorktreeListMessage(mockWorktrees) + + mockPostMessage.mockClear() + + fireEvent.click(screen.getByTestId("worktree-selector-trigger")) + + expect(mockPostMessage).toHaveBeenCalledWith({ type: "listWorktrees" }) + }) + + test("shows check mark on current worktree", () => { + render() + + simulateWorktreeListMessage(mockWorktrees) + + fireEvent.click(screen.getByTestId("worktree-selector-trigger")) + + // The current worktree should have Check component (Check from lucide-react) + const items = screen.getAllByTestId("worktree-selector-item") + const currentItem = items[0] // main is current + const checkIcon = currentItem.querySelector("svg.lucide-check") + expect(checkIcon).toBeInTheDocument() + }) + + test("handles worktree with no branch (detached HEAD)", () => { + const worktreesWithDetached: Worktree[] = [ + ...mockWorktrees, + { + path: "/path/to/detached", + branch: "", + commitHash: "xyz999", + isCurrent: false, + isBare: false, + isDetached: true, + isLocked: false, + }, + ] + + render() + + simulateWorktreeListMessage(worktreesWithDetached) + + fireEvent.click(screen.getByTestId("worktree-selector-trigger")) + + // Should show "worktrees:noBranch" translation key for detached HEAD + expect(screen.getByText("worktrees:noBranch")).toBeInTheDocument() + }) +}) diff --git a/webview-ui/src/components/settings/SettingsView.tsx b/webview-ui/src/components/settings/SettingsView.tsx index 792e23bf611..8e9d6103297 100644 --- a/webview-ui/src/components/settings/SettingsView.tsx +++ b/webview-ui/src/components/settings/SettingsView.tsx @@ -13,6 +13,7 @@ import { CheckCheck, SquareMousePointer, GitBranch, + History, Bell, Database, SquareTerminal, @@ -79,6 +80,7 @@ import { SlashCommandsSettings } from "./SlashCommandsSettings" import { UISettings } from "./UISettings" import ModesView from "../modes/ModesView" import McpView from "../mcp/McpView" +import { WorktreesView } from "../worktrees/WorktreesView" import { SettingsSearch } from "./SettingsSearch" import { useSearchIndexRegistry, SearchIndexProvider } from "./useSettingsSearch" @@ -104,6 +106,7 @@ export const sectionNames = [ "terminal", "modes", "mcp", + "worktrees", "prompts", "ui", "experimental", @@ -519,10 +522,11 @@ const SettingsView = forwardRef(({ onDone, t { id: "providers", icon: Plug }, { id: "modes", icon: Users2 }, { id: "mcp", icon: Server }, + { id: "worktrees", icon: GitBranch }, { id: "autoApprove", icon: CheckCheck }, { id: "slashCommands", icon: SquareSlash }, { id: "browser", icon: SquareMousePointer }, - { id: "checkpoints", icon: GitBranch }, + { id: "checkpoints", icon: History }, { id: "notifications", icon: Bell }, { id: "contextManagement", icon: Database }, { id: "terminal", icon: SquareTerminal }, @@ -893,6 +897,9 @@ const SettingsView = forwardRef(({ onDone, t {/* MCP Section */} {renderTab === "mcp" && } + {/* Worktrees Section */} + {renderTab === "worktrees" && } + {/* Prompts Section */} {renderTab === "prompts" && ( {/* Worktree info */} -
+

@@ -69,23 +69,24 @@ export const DeleteWorktreeModal = ({ open, onClose, worktree, onSuccess }: Dele

-

+

- + {worktree.path}

{/* Warning message */} -
+
-
-

{t("worktrees:deleteWarning")}

-
    +
    +

    {t("worktrees:deleteWarning")}

    +
    • • {t("worktrees:deleteWarningBranch")}
    • • {t("worktrees:deleteWarningFiles")}
    +

    {t("worktrees:deleteNoticeLarge")}

diff --git a/webview-ui/src/components/worktrees/MergeResultModal.tsx b/webview-ui/src/components/worktrees/MergeResultModal.tsx new file mode 100644 index 00000000000..7e82705b917 --- /dev/null +++ b/webview-ui/src/components/worktrees/MergeResultModal.tsx @@ -0,0 +1,89 @@ +import type { MergeWorktreeResult } from "@roo-code/types" + +import { useAppTranslation } from "@/i18n/TranslationContext" +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, Button } from "@/components/ui" +import { Check, TriangleAlert, XCircle } from "lucide-react" + +interface MergeResultModalProps { + open: boolean + onClose: () => void + result: MergeWorktreeResult + onAskRooResolve: () => void +} + +export const MergeResultModal = ({ open, onClose, result, onAskRooResolve }: MergeResultModalProps) => { + const { t } = useAppTranslation() + + // Determine the title and icon based on result state + const getResultDisplay = () => { + if (result.success) { + return { + title: t("worktrees:mergeSuccess"), + icon: , + } + } + if (result.hasConflicts) { + return { + title: t("worktrees:mergeConflicts"), + icon: , + } + } + return { + title: t("worktrees:mergeFailed"), + icon: , + } + } + + const { title, icon } = getResultDisplay() + + return ( + !isOpen && onClose()}> + + + + {icon} + {title} + + + +
+ {result.success ? ( +

{result.message}

+ ) : result.hasConflicts ? ( + <> +

+ {t("worktrees:conflictsDescription")} +

+ + {/* Conflicting files list */} +
+ {result.conflictingFiles.map((file) => ( +
+ {file} +
+ ))} +
+ + ) : ( +

{result.message}

+ )} +
+ + + {result.success ? ( + + ) : result.hasConflicts ? ( + <> + + + + ) : ( + + )} + +
+
+ ) +} diff --git a/webview-ui/src/components/worktrees/MergeWorktreeModal.tsx b/webview-ui/src/components/worktrees/MergeWorktreeModal.tsx new file mode 100644 index 00000000000..2d8e964d2cd --- /dev/null +++ b/webview-ui/src/components/worktrees/MergeWorktreeModal.tsx @@ -0,0 +1,89 @@ +import type { Worktree } from "@roo-code/types" + +import { useAppTranslation } from "@/i18n/TranslationContext" +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, Button, Checkbox } from "@/components/ui" +import { ArrowBigRightDash, GitBranch } from "lucide-react" + +interface MergeWorktreeModalProps { + open: boolean + onClose: () => void + worktree: Worktree + targetBranch: string + deleteAfterMerge: boolean + onDeleteAfterMergeChange: (checked: boolean) => void + isMerging: boolean + onMerge: () => void +} + +export const MergeWorktreeModal = ({ + open, + onClose, + worktree, + targetBranch, + deleteAfterMerge, + onDeleteAfterMergeChange, + isMerging, + onMerge, +}: MergeWorktreeModalProps) => { + const { t } = useAppTranslation() + + return ( + !isOpen && onClose()}> + + + {t("worktrees:mergeBranch")} + + +
+ {/* Merge info */} +
+
+ + {worktree.branch} +
+ +
+ +
+ +
+ + {targetBranch} +
+
+ + {/* Delete after merge option */} +
+ onDeleteAfterMergeChange(checked === true)} + /> + +
+
+ + + + + +
+
+ ) +} diff --git a/webview-ui/src/components/worktrees/WorktreesView.tsx b/webview-ui/src/components/worktrees/WorktreesView.tsx index f435969b0dc..74ff15762ea 100644 --- a/webview-ui/src/components/worktrees/WorktreesView.tsx +++ b/webview-ui/src/components/worktrees/WorktreesView.tsx @@ -6,16 +6,15 @@ import { Badge, Button, StandardTooltip } from "@/components/ui" import { useAppTranslation } from "@/i18n/TranslationContext" import { vscode } from "@/utils/vscode" -import { Tab, TabContent, TabHeader } from "../common/Tab" +import { SectionHeader } from "../settings/SectionHeader" import { CreateWorktreeModal } from "./CreateWorktreeModal" import { DeleteWorktreeModal } from "./DeleteWorktreeModal" +import { MergeWorktreeModal } from "./MergeWorktreeModal" +import { MergeResultModal } from "./MergeResultModal" +import { Folder, GitBranch, GitMerge, Lock, Plus, SquareArrowOutUpRight, Trash } from "lucide-react" -type WorktreesViewProps = { - onDone: () => void -} - -export const WorktreesView = ({ onDone }: WorktreesViewProps) => { +export const WorktreesView = () => { const { t } = useAppTranslation() // State @@ -174,56 +173,41 @@ export const WorktreesView = ({ onDone }: WorktreesViewProps) => { // Render error states if (!isGitRepo) { return ( - - -

{t("worktrees:title")}

- -
- -
- -

{t("worktrees:notGitRepo")}

-
-
-
+
+ {t("worktrees:title")} +
+ +

{t("worktrees:notGitRepo")}

+
+
) } if (isMultiRoot) { return ( - - -

{t("worktrees:title")}

- -
- -
- -

{t("worktrees:multiRootNotSupported")}

-
-
-
+
+ {t("worktrees:title")} +
+ +

{t("worktrees:multiRootNotSupported")}

+
+
) } if (isSubfolder) { return ( - - -

{t("worktrees:title")}

- -
- -
- -

{t("worktrees:subfolderNotSupported")}

-

- {t("worktrees:gitRoot")}:{" "} - {gitRootPath} -

-
-
-
+
+ {t("worktrees:title")} +
+ +

{t("worktrees:subfolderNotSupported")}

+

+ {t("worktrees:gitRoot")}:{" "} + {gitRootPath} +

+
+
) } @@ -231,46 +215,23 @@ export const WorktreesView = ({ onDone }: WorktreesViewProps) => { const primaryWorktree = worktrees.find((w) => w.isBare || worktrees.indexOf(w) === 0) return ( - - -
-

{t("worktrees:title")}

- +
+ {/* Fixed Header */} +
+ {t("worktrees:title")} +
+

{t("worktrees:description")}

+ + {/* New Worktree button */} +
-

{t("worktrees:description")}

- - {/* Worktree include status */} - {includeStatus && ( -
- {includeStatus.exists ? ( - <> - - - {t("worktrees:includeFileExists")} - - - ) : ( - <> - - - {t("worktrees:noIncludeFile")} - - {includeStatus.hasGitignore && ( - - )} - - )} -
- )} - +
- + {/* Scrollable List Area */} +
{isLoading ? (
@@ -281,61 +242,60 @@ export const WorktreesView = ({ onDone }: WorktreesViewProps) => {

{error}

) : ( -
+
{worktrees.map((worktree) => (
-
-
-
- + ? " bg-vscode-list-activeSelectionBackground border-vscode-list-activeSelectionForeground/20" + : "cursor-pointer" + }`} + onClick={ + worktree.isCurrent ? undefined : () => handleSwitchWorktree(worktree.path, false) + }> +
+
+ {/* Info */} +
+ {worktree.branch || (worktree.isDetached ? t("worktrees:detachedHead") : t("worktrees:noBranch"))} - {worktree.isBare && {t("worktrees:primary")}} - {worktree.isCurrent && ( - {t("worktrees:current")} + {worktree.isBare && ( + + {t("worktrees:primary")} + )} {worktree.isLocked && ( - + )}
-
- {worktree.path} +
+ + {worktree.path}
-
- {!worktree.isCurrent && ( - <> - - - - - - - - )} + {/* Actions */} +
+ + + {!worktree.isBare && worktree.branch && primaryWorktree && @@ -343,38 +303,58 @@ export const WorktreesView = ({ onDone }: WorktreesViewProps) => { )} - {!worktree.isBare && !worktree.isCurrent && ( - - - - )} + + + +
))} - - {/* New Worktree button */} -
)} - +
+ + {/* Fixed Footer - Worktree include status */} + {includeStatus && ( +
+ {includeStatus.exists ? ( + {t("worktrees:includeFileExists")} + ) : ( + <> + {t("worktrees:noIncludeFile")} + {includeStatus.hasGitignore && ( + + )} + + )} +
+ )} {/* Create Modal */} {showCreateModal && ( @@ -403,124 +383,30 @@ export const WorktreesView = ({ onDone }: WorktreesViewProps) => { {/* Merge Modal */} {mergeWorktree && !mergeResult && ( -
-
-

- {t("worktrees:mergeBranch")} -

-

- {t("worktrees:mergeDescription", { - source: mergeWorktree.branch, - target: mergeTargetBranch, - })} -

- -
- -
- -
- - -
-
-
+ setMergeWorktree(null)} + worktree={mergeWorktree} + targetBranch={mergeTargetBranch} + deleteAfterMerge={mergeDeleteAfter} + onDeleteAfterMergeChange={setMergeDeleteAfter} + isMerging={isMerging} + onMerge={handleMerge} + /> )} {/* Merge Result Modal */} {mergeResult && ( -
-
- {mergeResult.success ? ( - <> -
- -

- {t("worktrees:mergeSuccess")} -

-
-

{mergeResult.message}

-
- -
- - ) : mergeResult.hasConflicts ? ( - <> -
- -

- {t("worktrees:mergeConflicts")} -

-
-

- {t("worktrees:conflictsDescription")} -

-
- {mergeResult.conflictingFiles.map((file) => ( -
- {file} -
- ))} -
-
- - -
- - ) : ( - <> -
- -

- {t("worktrees:mergeFailed")} -

-
-

{mergeResult.message}

-
- -
- - )} -
-
+ { + setMergeWorktree(null) + setMergeResult(null) + }} + result={mergeResult} + onAskRooResolve={handleAskRooResolve} + /> )} - +
) } diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 9bf14366066..62734f9b04f 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -29,6 +29,7 @@ "providers": "Providers", "modes": "Modes", "mcp": "MCP Servers", + "worktrees": "Worktrees", "autoApprove": "Auto-Approve", "browser": "Browser", "checkpoints": "Checkpoints", diff --git a/webview-ui/src/i18n/locales/en/worktrees.json b/webview-ui/src/i18n/locales/en/worktrees.json index 820818ccc50..3a7570d8fa1 100644 --- a/webview-ui/src/i18n/locales/en/worktrees.json +++ b/webview-ui/src/i18n/locales/en/worktrees.json @@ -1,14 +1,14 @@ { "title": "Worktrees", "done": "Done", - "description": "Git worktrees allow you to work on multiple branches simultaneously in separate directories. Each worktree gets its own VS Code window with Roo Code.", + "description": "Git worktrees are great for agentic coding, because they allow you to work on multiple branches of a repo at the same time, by keeping them in different directories. Each worktree gets its own VS Code window with Roo Code.", "notGitRepo": "This workspace is not a Git repository. Worktrees require a Git repository to function.", "multiRootNotSupported": "Worktrees are not supported in multi-root workspaces. Please open a single folder to use worktrees.", "subfolderNotSupported": "This workspace is a subfolder of a Git repository. Please open the repository root to use worktrees.", "gitRoot": "Git root", - "includeFileExists": ".worktreeinclude file found - files will be copied to new worktrees", + "includeFileExists": ".worktreeinclude file found. Files will be copied to new worktrees.", "noIncludeFile": "No .worktreeinclude file found", "createFromGitignore": "Create from .gitignore", @@ -18,7 +18,7 @@ "detachedHead": "Detached HEAD", "noBranch": "No branch", - "openInCurrentWindow": "Open in current window", + "switchInThisWindow": "Switch to worktree", "openInNewWindow": "Open in new window", "merge": "Merge", "delete": "Delete", @@ -50,13 +50,13 @@ "deleteWarning": "This can't be undone. It will delete:", "deleteWarningBranch": "The branch and any uncommitted changes", "deleteWarningFiles": "All files in the worktree directory", + "deleteNoticeLarge": "If this is a large repository, it may take a little while.", "forceDelete": "Force delete", "worktreeIsLocked": "worktree is locked", "deleting": "Deleting...", "mergeBranch": "Merge Branch", - "mergeDescription": "Merge '{{source}}' into '{{target}}'", - "deleteAfterMerge": "Delete worktree after successful merge", + "deleteAfterMerge": "Delete worktree after merging", "merging": "Merging...", "mergeSuccess": "Merge Successful", "mergeConflicts": "Merge Conflicts", @@ -64,5 +64,13 @@ "mergeFailed": "Merge Failed", "resolveManually": "I'll Resolve Manually", "askRooResolve": "Ask Roo to Resolve", - "close": "Close" + "close": "Close", + + "selector": { + "title": "Worktrees", + "tooltip": "Switch between worktrees", + "description": "Git worktrees let you work on multiple branches simultaneously. Click to switch workspace.", + "settings": "Worktree Settings", + "info": "Git worktrees allow you to have multiple working directories attached to the same repository." + } } From afb1a4969a82cb902b1f7e9c4139b5517d7f9f34 Mon Sep 17 00:00:00 2001 From: Bruno Bergher Date: Sat, 24 Jan 2026 12:03:33 +0000 Subject: [PATCH 03/11] Much more prominent --- webview-ui/src/components/chat/ChatView.tsx | 4 +- .../src/components/chat/WorktreeSelector.tsx | 78 ++++++++++++------- .../components/worktrees/WorktreesView.tsx | 10 +-- webview-ui/src/i18n/locales/en/worktrees.json | 3 +- 4 files changed, 55 insertions(+), 40 deletions(-) diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 52574e15dcb..66e8f5baf27 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -1522,8 +1522,6 @@ const ChatViewComponent: React.ForwardRefRenderFunction} {/* Everyone should see their task history if any */} {taskHistory.length > 0 && } - {/* Worktree selector for quick switching between worktrees */} -
{/* Logged out users should see a one-time upsell, but not for brand new users */} {!cloudIsAuthenticated && taskHistory.length >= 6 && ( @@ -1545,6 +1543,8 @@ const ChatViewComponent: React.ForwardRefRenderFunction )} + {!task && } + {task && ( <>
diff --git a/webview-ui/src/components/chat/WorktreeSelector.tsx b/webview-ui/src/components/chat/WorktreeSelector.tsx index 37d12983c95..f7e75ccdb30 100644 --- a/webview-ui/src/components/chat/WorktreeSelector.tsx +++ b/webview-ui/src/components/chat/WorktreeSelector.tsx @@ -1,14 +1,15 @@ import React, { useState, useCallback, useEffect, useMemo } from "react" -import { GitBranch, Check } from "lucide-react" +import { GitBranch, Check, ChevronDown, Plus } from "lucide-react" import type { Worktree, WorktreeListResponse } from "@roo-code/types" import { cn } from "@/lib/utils" import { useRooPortal } from "@/components/ui/hooks/useRooPortal" -import { Popover, PopoverContent, PopoverTrigger, StandardTooltip } from "@/components/ui" +import { Popover, PopoverContent, PopoverTrigger, StandardTooltip, Button } from "@/components/ui" import { useAppTranslation } from "@/i18n/TranslationContext" import { vscode } from "@/utils/vscode" +import { CreateWorktreeModal } from "../worktrees/CreateWorktreeModal" import { IconButton } from "./IconButton" interface WorktreeSelectorProps { @@ -20,6 +21,7 @@ export const WorktreeSelector = ({ disabled = false }: WorktreeSelectorProps) => const [open, setOpen] = useState(false) const [worktrees, setWorktrees] = useState([]) const [isGitRepo, setIsGitRepo] = useState(true) + const [showCreateModal, setShowCreateModal] = useState(false) const portalContainer = useRooPortal("roo-portal") // Find current worktree @@ -75,12 +77,11 @@ export const WorktreeSelector = ({ disabled = false }: WorktreeSelectorProps) => }, []) // Don't render if not a git repo or only one worktree - if (!isGitRepo || worktrees.length <= 1) { + if (!isGitRepo) { return null } const title = t("worktrees:selector.tooltip") - const instructionText = t("worktrees:selector.description") return ( @@ -89,15 +90,17 @@ export const WorktreeSelector = ({ disabled = false }: WorktreeSelectorProps) => disabled={disabled} data-testid="worktree-selector-trigger" className={cn( - "inline-flex items-center relative whitespace-nowrap px-1.5 py-1 text-xs", - "bg-transparent border border-[rgba(255,255,255,0.08)] rounded-md text-vscode-foreground", + "inline-flex gap-1 mx-2 mb-1 items-center relative whitespace-nowrap px-3 py-2", + "bg-transparent rounded-full text-vscode-foreground text-left", "transition-all duration-150 focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder focus-visible:ring-inset", disabled ? "opacity-50 cursor-not-allowed" : "opacity-90 hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)] cursor-pointer", )}> - + {t("worktrees:selector.worktree")}: + {currentWorktree?.branch || t("worktrees:noBranch")} + container={portalContainer} className="p-0 overflow-hidden min-w-80 max-w-9/10">
- {/* Info blurb */} -
-

{instructionText}

+ {/* Bottom bar with settings cog and title */} +
+
+

{t("worktrees:selector.title")}

+ +
+

+ {t("worktrees:selector.description")} +

{/* Worktree list */} @@ -146,28 +159,35 @@ export const WorktreeSelector = ({ disabled = false }: WorktreeSelectorProps) => })}
- {/* Bottom bar with settings cog and title */} -
-
- -
- - {/* Info icon and title on the right */} -
- - - -

- {t("worktrees:selector.title")} -

-
+ {/* New worktree button */} +
+
+ + {/* Create Worktree Modal */} + {showCreateModal && ( + setShowCreateModal(false)} + openAfterCreate={true} + onSuccess={() => { + setShowCreateModal(false) + fetchWorktrees() + }} + /> + )} ) } diff --git a/webview-ui/src/components/worktrees/WorktreesView.tsx b/webview-ui/src/components/worktrees/WorktreesView.tsx index 39e56bb6f57..1608c069913 100644 --- a/webview-ui/src/components/worktrees/WorktreesView.tsx +++ b/webview-ui/src/components/worktrees/WorktreesView.tsx @@ -125,10 +125,7 @@ export const WorktreesView = () => { return (
{t("worktrees:title")} -
- -

{t("worktrees:notGitRepo")}

-
+
{t("worktrees:notGitRepo")}
) } @@ -137,10 +134,7 @@ export const WorktreesView = () => { return (
{t("worktrees:title")} -
- -

{t("worktrees:multiRootNotSupported")}

-
+
{t("worktrees:multiRootNotSupported")}
) } diff --git a/webview-ui/src/i18n/locales/en/worktrees.json b/webview-ui/src/i18n/locales/en/worktrees.json index 4da045858c5..f238ef68b21 100644 --- a/webview-ui/src/i18n/locales/en/worktrees.json +++ b/webview-ui/src/i18n/locales/en/worktrees.json @@ -57,10 +57,11 @@ "close": "Close", "selector": { + "worktree": "Worktree", "title": "Worktrees", "tooltip": "Switch between worktrees", "description": "Git worktrees let you work on multiple branches simultaneously. Click to switch workspace.", - "settings": "Worktree Settings", + "settings": "Manage Worktrees", "info": "Git worktrees allow you to have multiple working directories attached to the same repository." } } From dfdda804cb87daee317f1faaea61a2fc45f00272 Mon Sep 17 00:00:00 2001 From: Bruno Bergher Date: Sat, 24 Jan 2026 17:20:12 +0000 Subject: [PATCH 04/11] UI --- packages/types/src/global-settings.ts | 5 ++ packages/types/src/vscode-extension-host.ts | 5 ++ src/core/webview/webviewMessageHandler.ts | 28 ++++++ webview-ui/src/components/chat/ChatView.tsx | 3 +- .../src/components/chat/WorktreeSelector.tsx | 4 +- .../chat/__tests__/WorktreeSelector.spec.tsx | 13 +-- .../src/components/settings/SettingsView.tsx | 6 +- webview-ui/src/components/ui/input.tsx | 2 +- .../src/components/ui/toggle-switch.tsx | 8 +- .../worktrees/CreateWorktreeModal.tsx | 58 ++++++------ .../components/worktrees/WorktreesView.tsx | 89 ++++++++++++------- .../src/context/ExtensionStateContext.tsx | 5 ++ webview-ui/src/i18n/locales/ca/worktrees.json | 4 +- webview-ui/src/i18n/locales/de/worktrees.json | 4 +- webview-ui/src/i18n/locales/en/worktrees.json | 18 ++-- webview-ui/src/i18n/locales/es/worktrees.json | 4 +- webview-ui/src/i18n/locales/fr/worktrees.json | 4 +- webview-ui/src/i18n/locales/hi/worktrees.json | 4 +- webview-ui/src/i18n/locales/id/worktrees.json | 4 +- webview-ui/src/i18n/locales/it/worktrees.json | 4 +- webview-ui/src/i18n/locales/ja/worktrees.json | 4 +- webview-ui/src/i18n/locales/ko/worktrees.json | 4 +- webview-ui/src/i18n/locales/nl/worktrees.json | 4 +- webview-ui/src/i18n/locales/pl/worktrees.json | 4 +- .../src/i18n/locales/pt-BR/worktrees.json | 4 +- webview-ui/src/i18n/locales/ru/worktrees.json | 4 +- webview-ui/src/i18n/locales/tr/worktrees.json | 4 +- webview-ui/src/i18n/locales/vi/worktrees.json | 4 +- .../src/i18n/locales/zh-CN/worktrees.json | 4 +- .../src/i18n/locales/zh-TW/worktrees.json | 4 +- 30 files changed, 206 insertions(+), 106 deletions(-) diff --git a/packages/types/src/global-settings.ts b/packages/types/src/global-settings.ts index 383678059e9..0f75e1d6107 100644 --- a/packages/types/src/global-settings.ts +++ b/packages/types/src/global-settings.ts @@ -203,6 +203,11 @@ export const globalSettingsSchema = z.object({ * Used by the worktree feature to open the Roo Code sidebar in a new window. */ worktreeAutoOpenPath: z.string().optional(), + /** + * Whether to show the worktree selector in the home screen. + * @default true + */ + showWorktreesInHomeScreen: z.boolean().optional(), }) export type GlobalSettings = z.infer diff --git a/packages/types/src/vscode-extension-host.ts b/packages/types/src/vscode-extension-host.ts index a03b6419c2a..49f9687f009 100644 --- a/packages/types/src/vscode-extension-host.ts +++ b/packages/types/src/vscode-extension-host.ts @@ -107,6 +107,7 @@ export interface ExtensionMessage { | "worktreeDefaults" | "worktreeIncludeStatus" | "branchWorktreeIncludeResult" + | "folderSelected" text?: string payload?: any // eslint-disable-line @typescript-eslint/no-explicit-any checkpointWarning?: { @@ -256,6 +257,8 @@ export interface ExtensionMessage { copyProgressBytesCopied?: number copyProgressTotalBytes?: number copyProgressItemName?: string + // folderSelected + path?: string } export interface OpenAiCodexRateLimitsMessage { @@ -331,6 +334,7 @@ export type ExtensionState = Pick< | "includeCurrentCost" | "maxGitStatusFiles" | "requestDelaySeconds" + | "showWorktreesInHomeScreen" > & { version: string clineMessages: ClineMessage[] @@ -599,6 +603,7 @@ export interface WebviewMessage { | "checkBranchWorktreeInclude" | "createWorktreeInclude" | "checkoutBranch" + | "browseForWorktreePath" text?: string editedMessageContent?: string tab?: "settings" | "history" | "mcp" | "modes" | "chat" | "marketplace" | "cloud" diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index 700710acf4b..2dc77d05027 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -3556,6 +3556,34 @@ export const webviewMessageHandler = async ( break } + case "browseForWorktreePath": { + try { + const options: vscode.OpenDialogOptions = { + canSelectFiles: false, + canSelectFolders: true, + canSelectMany: false, + openLabel: t("worktrees:selectWorktreeLocation"), + title: t("worktrees:selectFolderForWorktree"), + defaultUri: vscode.workspace.workspaceFolders?.[0]?.uri + ? vscode.Uri.joinPath(vscode.workspace.workspaceFolders[0].uri, "..") + : undefined, + } + + const result = await vscode.window.showOpenDialog(options) + if (result && result[0]) { + await provider.postMessageToWebview({ + type: "folderSelected", + path: result[0].fsPath, + }) + } + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error) + provider.log(`Error opening folder picker: ${errorMessage}`) + } + + break + } + default: { // console.log(`Unhandled message type: ${message.type}`) // diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 66e8f5baf27..c370cf29f45 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -96,6 +96,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction )} - {!task && } + {!task && showWorktreesInHomeScreen && } {task && ( <> diff --git a/webview-ui/src/components/chat/WorktreeSelector.tsx b/webview-ui/src/components/chat/WorktreeSelector.tsx index f7e75ccdb30..938fa2cec75 100644 --- a/webview-ui/src/components/chat/WorktreeSelector.tsx +++ b/webview-ui/src/components/chat/WorktreeSelector.tsx @@ -77,7 +77,7 @@ export const WorktreeSelector = ({ disabled = false }: WorktreeSelectorProps) => }, []) // Don't render if not a git repo or only one worktree - if (!isGitRepo) { + if (!isGitRepo || worktrees.length <= 1) { return null } @@ -91,7 +91,7 @@ export const WorktreeSelector = ({ disabled = false }: WorktreeSelectorProps) => data-testid="worktree-selector-trigger" className={cn( "inline-flex gap-1 mx-2 mb-1 items-center relative whitespace-nowrap px-3 py-2", - "bg-transparent rounded-full text-vscode-foreground text-left", + "bg-transparent rounded-full text-vscode-foreground text-left text-sm", "transition-all duration-150 focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder focus-visible:ring-inset", disabled ? "opacity-50 cursor-not-allowed" diff --git a/webview-ui/src/components/chat/__tests__/WorktreeSelector.spec.tsx b/webview-ui/src/components/chat/__tests__/WorktreeSelector.spec.tsx index 74edf196871..106e23ad0f3 100644 --- a/webview-ui/src/components/chat/__tests__/WorktreeSelector.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/WorktreeSelector.spec.tsx @@ -218,18 +218,7 @@ describe("WorktreeSelector", () => { }) }) - test("shows info icon with tooltip in footer", () => { - render() - - simulateWorktreeListMessage(mockWorktrees) - - fireEvent.click(screen.getByTestId("worktree-selector-trigger")) - - const infoIcon = document.querySelector(".codicon-info") - expect(infoIcon).toBeInTheDocument() - }) - - test("shows title in footer", () => { + test("shows title in header", () => { render() simulateWorktreeListMessage(mockWorktrees) diff --git a/webview-ui/src/components/settings/SettingsView.tsx b/webview-ui/src/components/settings/SettingsView.tsx index b4b44eba2a5..bd58db79e6d 100644 --- a/webview-ui/src/components/settings/SettingsView.tsx +++ b/webview-ui/src/components/settings/SettingsView.tsx @@ -13,7 +13,6 @@ import { CheckCheck, SquareMousePointer, GitBranch, - History, Bell, Database, SquareTerminal, @@ -29,6 +28,7 @@ import { Server, Users2, ArrowLeft, + GitCommitVertical, } from "lucide-react" import { @@ -518,15 +518,15 @@ const SettingsView = forwardRef(({ onDone, t { id: "providers", icon: Plug }, { id: "modes", icon: Users2 }, { id: "mcp", icon: Server }, - { id: "worktrees", icon: GitBranch }, { id: "autoApprove", icon: CheckCheck }, { id: "slashCommands", icon: SquareSlash }, { id: "browser", icon: SquareMousePointer }, - { id: "checkpoints", icon: History }, + { id: "checkpoints", icon: GitCommitVertical }, { id: "notifications", icon: Bell }, { id: "contextManagement", icon: Database }, { id: "terminal", icon: SquareTerminal }, { id: "prompts", icon: MessageSquare }, + { id: "worktrees", icon: GitBranch }, { id: "ui", icon: Glasses }, { id: "experimental", icon: FlaskConical }, { id: "language", icon: Globe }, diff --git a/webview-ui/src/components/ui/input.tsx b/webview-ui/src/components/ui/input.tsx index 77bea85dad6..bc84ad60dfb 100644 --- a/webview-ui/src/components/ui/input.tsx +++ b/webview-ui/src/components/ui/input.tsx @@ -8,7 +8,7 @@ const Input = React.forwardRef>( = ({ "aria-label": ariaLabel, "data-testid": dataTestId, }) => { - const dimensions = size === "small" ? { width: 16, height: 8, dotSize: 4 } : { width: 20, height: 10, dotSize: 6 } + const dimensions = size === "small" ? { width: 20, height: 10, dotSize: 8 } : { width: 26, height: 10, dotSize: 6 } const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Enter" || e.key === " ") { @@ -40,12 +40,12 @@ export const ToggleSwitch: React.FC = ({ height: `${dimensions.height}px`, backgroundColor: checked ? "var(--vscode-button-background)" - : "var(--vscode-titleBar-inactiveForeground)", + : "var(--vscode-button-secondaryBackground)", borderRadius: `${dimensions.height / 2}px`, position: "relative", cursor: disabled ? "not-allowed" : "pointer", transition: "background-color 0.2s", - opacity: disabled ? 0.4 : checked ? 0.8 : 0.6, + opacity: disabled ? 0.6 : 1, }} onClick={disabled ? undefined : onChange} onKeyDown={handleKeyDown}> @@ -53,7 +53,7 @@ export const ToggleSwitch: React.FC = ({ style={{ width: `${dimensions.dotSize}px`, height: `${dimensions.dotSize}px`, - backgroundColor: "var(--vscode-titleBar-activeForeground)", + backgroundColor: "var(--vscode-foreground)", borderRadius: "50%", position: "absolute", top: `${(dimensions.height - dimensions.dotSize) / 2}px`, diff --git a/webview-ui/src/components/worktrees/CreateWorktreeModal.tsx b/webview-ui/src/components/worktrees/CreateWorktreeModal.tsx index 93ed2ed60e2..84743c16503 100644 --- a/webview-ui/src/components/worktrees/CreateWorktreeModal.tsx +++ b/webview-ui/src/components/worktrees/CreateWorktreeModal.tsx @@ -5,17 +5,9 @@ import type { WorktreeDefaultsResponse, BranchInfo, WorktreeIncludeStatus } from import { vscode } from "@/utils/vscode" import { useAppTranslation } from "@/i18n/TranslationContext" -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, - Button, - Input, -} from "@/components/ui" +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, Button, Input } from "@/components/ui" import { SearchableSelect, type SearchableSelectOption } from "@/components/ui/searchable-select" +import { CornerDownRight, Folder, FolderSearch, Info } from "lucide-react" interface CreateWorktreeModalProps { open: boolean @@ -81,6 +73,12 @@ export const CreateWorktreeModal = ({ setIncludeStatus(message.worktreeIncludeStatus) break } + case "folderSelected": { + if (message.path) { + setWorktreePath(message.path) + } + break + } case "worktreeCopyProgress": { setCopyProgress({ bytesCopied: message.copyProgressBytesCopied ?? 0, @@ -152,14 +150,13 @@ export const CreateWorktreeModal = ({ {t("worktrees:createWorktree")} - {t("worktrees:createWorktreeDescription")}
{/* No .worktreeinclude warning - shows when the current worktree doesn't have .worktreeinclude */} {includeStatus?.exists === false && (
- + {t("worktrees:noIncludeFileWarning")} {" — "} @@ -170,17 +167,6 @@ export const CreateWorktreeModal = ({
)} - {/* Branch name */} -
- - setBranchName(e.target.value)} - placeholder={defaults?.suggestedBranch || "worktree/feature-name"} - className="rounded-full" - /> -
- {/* Base branch selector */}
@@ -201,16 +187,32 @@ export const CreateWorktreeModal = ({ )}
+ {/* Branch name */} +
+ + + setBranchName(e.target.value)} + placeholder={defaults?.suggestedBranch || "worktree/feature-name"} + className="rounded-full" + /> +
+ {/* Worktree path */} -
- +
+ + setWorktreePath(e.target.value)} placeholder={defaults?.suggestedPath || "/path/to/worktree"} - className="rounded-full" + className="rounded-full flex-1 pr-9" + /> + vscode.postMessage({ type: "browseForWorktreePath" })} /> -

{t("worktrees:pathHint")}

{/* Error message */} @@ -244,7 +246,7 @@ export const CreateWorktreeModal = ({ - @@ -258,27 +284,30 @@ export const WorktreesView = () => { )}
- {/* Fixed Footer - Worktree include status */} - {includeStatus && ( -
- {includeStatus.exists ? ( - {t("worktrees:includeFileExists")} - ) : ( - <> - {t("worktrees:noIncludeFile")} - {includeStatus.hasGitignore && ( - - )} - - )} -
- )} + {/* Fixed Footer - Settings */} +
+ {/* Worktree include status */} + {includeStatus && ( +
+ {includeStatus.exists ? ( + {t("worktrees:includeFileExists")} + ) : ( + <> + {t("worktrees:noIncludeFile")} + {includeStatus.hasGitignore && ( + + )} + + )} +
+ )} +
{/* Create Modal */} {showCreateModal && ( diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index a783eb50124..26b3851c1be 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -161,6 +161,8 @@ export interface ExtensionStateContextType extends ExtensionState { setIncludeCurrentTime: (value: boolean) => void includeCurrentCost?: boolean setIncludeCurrentCost: (value: boolean) => void + showWorktreesInHomeScreen: boolean + setShowWorktreesInHomeScreen: (value: boolean) => void } export const ExtensionStateContext = createContext(undefined) @@ -621,6 +623,9 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode setIncludeCurrentTime, includeCurrentCost, setIncludeCurrentCost, + showWorktreesInHomeScreen: state.showWorktreesInHomeScreen ?? true, + setShowWorktreesInHomeScreen: (value) => + setState((prevState) => ({ ...prevState, showWorktreesInHomeScreen: value })), } return {children} diff --git a/webview-ui/src/i18n/locales/ca/worktrees.json b/webview-ui/src/i18n/locales/ca/worktrees.json index 973e6ddf198..a3596c36e27 100644 --- a/webview-ui/src/i18n/locales/ca/worktrees.json +++ b/webview-ui/src/i18n/locales/ca/worktrees.json @@ -54,5 +54,7 @@ "worktreeIsLocked": "el worktree està bloquejat", "deleting": "S'està suprimint...", - "close": "Tanca" + "close": "Tanca", + + "showInHomeScreen": "Mostra worktrees a la pantalla d'inici" } diff --git a/webview-ui/src/i18n/locales/de/worktrees.json b/webview-ui/src/i18n/locales/de/worktrees.json index af0aa34b23d..89e128ebc03 100644 --- a/webview-ui/src/i18n/locales/de/worktrees.json +++ b/webview-ui/src/i18n/locales/de/worktrees.json @@ -54,5 +54,7 @@ "worktreeIsLocked": "Worktree ist gesperrt", "deleting": "Wird gelöscht...", - "close": "Schließen" + "close": "Schließen", + + "showInHomeScreen": "Worktrees auf dem Startbildschirm anzeigen" } diff --git a/webview-ui/src/i18n/locales/en/worktrees.json b/webview-ui/src/i18n/locales/en/worktrees.json index f238ef68b21..a9c901ede01 100644 --- a/webview-ui/src/i18n/locales/en/worktrees.json +++ b/webview-ui/src/i18n/locales/en/worktrees.json @@ -3,7 +3,7 @@ "done": "Done", "description": "Git worktrees are great for agentic coding, because they allow you to work on multiple branches of a repo at the same time, by keeping them in different directories. Each worktree gets its own VS Code window with Roo Code.", - "notGitRepo": "This workspace is not a Git repository. Worktrees require a Git repository to function.", + "notGitRepo": "This workspace is not a Git repository. Open a workspace with a Git repository to set up worktrees.", "multiRootNotSupported": "Worktrees are not supported in multi-root workspaces. Please open a single folder to use worktrees.", "subfolderNotSupported": "This workspace is a subfolder of a Git repository. Please open the repository root to use worktrees.", "gitRoot": "Git root", @@ -21,24 +21,24 @@ "switchInThisWindow": "Switch to worktree", "openInNewWindow": "Open in new window", "delete": "Delete", - "newWorktree": "New Worktree", + "newWorktree": "Create worktree", "createWorktree": "Create Worktree", - "createWorktreeDescription": "Create a new worktree to work on a separate branch in its own directory.", - "branchName": "Branch name", + "branchName": "New branch", "createNewBranch": "Create new branch", "checkoutExisting": "Checkout existing branch", - "baseBranch": "Base branch", + "baseBranch": "From base branch", "loadingBranches": "Loading branches...", "selectBranch": "Select branch", "searchBranch": "Search branches...", "noBranchFound": "No branch found", "localBranches": "Local branches", "remoteBranches": "Remote branches", - "worktreePath": "Worktree path", - "pathHint": "The path where the worktree will be created", + "worktreePath": "In", + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree", "noIncludeFileWarning": "No .worktreeinclude file", - "noIncludeFileHint": "Without a .worktreeinclude file, files like node_modules won't be copied to the new worktree. You may need to run npm install after creating it.", + "noIncludeFileHint": "Worktrees are created with just the files from their branch. If you want to copy over local files like .env and node_modules, include them in a .worktreeinclude file at the root of the repository.", "create": "Create", "creating": "Creating...", "copyingFiles": "Copying files...", @@ -56,6 +56,8 @@ "close": "Close", + "showInHomeScreen": "Show worktrees in home screen", + "selector": { "worktree": "Worktree", "title": "Worktrees", diff --git a/webview-ui/src/i18n/locales/es/worktrees.json b/webview-ui/src/i18n/locales/es/worktrees.json index 9d2f4b871b5..ac8716c3ea8 100644 --- a/webview-ui/src/i18n/locales/es/worktrees.json +++ b/webview-ui/src/i18n/locales/es/worktrees.json @@ -54,5 +54,7 @@ "worktreeIsLocked": "el worktree está bloqueado", "deleting": "Eliminando...", - "close": "Cerrar" + "close": "Cerrar", + + "showInHomeScreen": "Mostrar worktrees en la pantalla de inicio" } diff --git a/webview-ui/src/i18n/locales/fr/worktrees.json b/webview-ui/src/i18n/locales/fr/worktrees.json index 21591834b8e..6d08809467d 100644 --- a/webview-ui/src/i18n/locales/fr/worktrees.json +++ b/webview-ui/src/i18n/locales/fr/worktrees.json @@ -54,5 +54,7 @@ "worktreeIsLocked": "le worktree est verrouillé", "deleting": "Suppression...", - "close": "Fermer" + "close": "Fermer", + + "showInHomeScreen": "Afficher les worktrees sur l'écran d'accueil" } diff --git a/webview-ui/src/i18n/locales/hi/worktrees.json b/webview-ui/src/i18n/locales/hi/worktrees.json index ae6dac2ca1c..71dead28b99 100644 --- a/webview-ui/src/i18n/locales/hi/worktrees.json +++ b/webview-ui/src/i18n/locales/hi/worktrees.json @@ -54,5 +54,7 @@ "worktreeIsLocked": "worktree लॉक्ड है", "deleting": "हटाया जा रहा है...", - "close": "बंद करें" + "close": "बंद करें", + + "showInHomeScreen": "होम स्क्रीन में worktrees दिखाएँ" } diff --git a/webview-ui/src/i18n/locales/id/worktrees.json b/webview-ui/src/i18n/locales/id/worktrees.json index e927171b546..d6218887309 100644 --- a/webview-ui/src/i18n/locales/id/worktrees.json +++ b/webview-ui/src/i18n/locales/id/worktrees.json @@ -54,5 +54,7 @@ "worktreeIsLocked": "worktree terkunci", "deleting": "Menghapus...", - "close": "Tutup" + "close": "Tutup", + + "showInHomeScreen": "Tampilkan worktrees di layar beranda" } diff --git a/webview-ui/src/i18n/locales/it/worktrees.json b/webview-ui/src/i18n/locales/it/worktrees.json index 9051efc4ce4..6a3835719b2 100644 --- a/webview-ui/src/i18n/locales/it/worktrees.json +++ b/webview-ui/src/i18n/locales/it/worktrees.json @@ -54,5 +54,7 @@ "worktreeIsLocked": "il worktree è bloccato", "deleting": "Eliminazione...", - "close": "Chiudi" + "close": "Chiudi", + + "showInHomeScreen": "Mostra worktrees nella schermata iniziale" } diff --git a/webview-ui/src/i18n/locales/ja/worktrees.json b/webview-ui/src/i18n/locales/ja/worktrees.json index 3666bbd658f..535088b94ed 100644 --- a/webview-ui/src/i18n/locales/ja/worktrees.json +++ b/webview-ui/src/i18n/locales/ja/worktrees.json @@ -54,5 +54,7 @@ "worktreeIsLocked": "worktree がロックされています", "deleting": "削除中...", - "close": "閉じる" + "close": "閉じる", + + "showInHomeScreen": "ホーム画面に worktrees を表示" } diff --git a/webview-ui/src/i18n/locales/ko/worktrees.json b/webview-ui/src/i18n/locales/ko/worktrees.json index 74e3f0ebde6..04c8f18b7bf 100644 --- a/webview-ui/src/i18n/locales/ko/worktrees.json +++ b/webview-ui/src/i18n/locales/ko/worktrees.json @@ -54,5 +54,7 @@ "worktreeIsLocked": "worktree가 잠겨 있습니다", "deleting": "삭제 중...", - "close": "닫기" + "close": "닫기", + + "showInHomeScreen": "홈 화면에 worktrees 표시" } diff --git a/webview-ui/src/i18n/locales/nl/worktrees.json b/webview-ui/src/i18n/locales/nl/worktrees.json index d897c7aaf73..f3d0436520a 100644 --- a/webview-ui/src/i18n/locales/nl/worktrees.json +++ b/webview-ui/src/i18n/locales/nl/worktrees.json @@ -54,5 +54,7 @@ "worktreeIsLocked": "worktree is vergrendeld", "deleting": "Bezig met verwijderen...", - "close": "Sluiten" + "close": "Sluiten", + + "showInHomeScreen": "Worktrees weergeven op startscherm" } diff --git a/webview-ui/src/i18n/locales/pl/worktrees.json b/webview-ui/src/i18n/locales/pl/worktrees.json index 8b45fda6244..dd76e124f4a 100644 --- a/webview-ui/src/i18n/locales/pl/worktrees.json +++ b/webview-ui/src/i18n/locales/pl/worktrees.json @@ -54,5 +54,7 @@ "worktreeIsLocked": "worktree jest zablokowany", "deleting": "Usuwanie...", - "close": "Zamknij" + "close": "Zamknij", + + "showInHomeScreen": "Pokaż worktrees na ekranie głównym" } diff --git a/webview-ui/src/i18n/locales/pt-BR/worktrees.json b/webview-ui/src/i18n/locales/pt-BR/worktrees.json index 6795857a8cf..72c32034132 100644 --- a/webview-ui/src/i18n/locales/pt-BR/worktrees.json +++ b/webview-ui/src/i18n/locales/pt-BR/worktrees.json @@ -54,5 +54,7 @@ "worktreeIsLocked": "worktree está bloqueado", "deleting": "Excluindo...", - "close": "Fechar" + "close": "Fechar", + + "showInHomeScreen": "Mostrar worktrees na tela inicial" } diff --git a/webview-ui/src/i18n/locales/ru/worktrees.json b/webview-ui/src/i18n/locales/ru/worktrees.json index 28fe4861e6d..85c36390fb0 100644 --- a/webview-ui/src/i18n/locales/ru/worktrees.json +++ b/webview-ui/src/i18n/locales/ru/worktrees.json @@ -54,5 +54,7 @@ "worktreeIsLocked": "worktree заблокирован", "deleting": "Удаление...", - "close": "Закрыть" + "close": "Закрыть", + + "showInHomeScreen": "Показывать worktrees на главном экране" } diff --git a/webview-ui/src/i18n/locales/tr/worktrees.json b/webview-ui/src/i18n/locales/tr/worktrees.json index f3fd3dfa3e1..e7bfa3866ae 100644 --- a/webview-ui/src/i18n/locales/tr/worktrees.json +++ b/webview-ui/src/i18n/locales/tr/worktrees.json @@ -54,5 +54,7 @@ "worktreeIsLocked": "worktree kilitli", "deleting": "Siliniyor...", - "close": "Kapat" + "close": "Kapat", + + "showInHomeScreen": "Ana ekranda worktrees göster" } diff --git a/webview-ui/src/i18n/locales/vi/worktrees.json b/webview-ui/src/i18n/locales/vi/worktrees.json index 7b22e88f3ef..3897007f903 100644 --- a/webview-ui/src/i18n/locales/vi/worktrees.json +++ b/webview-ui/src/i18n/locales/vi/worktrees.json @@ -54,5 +54,7 @@ "worktreeIsLocked": "worktree đang bị khóa", "deleting": "Đang xóa...", - "close": "Đóng" + "close": "Đóng", + + "showInHomeScreen": "Hiển thị worktrees trên màn hình chính" } diff --git a/webview-ui/src/i18n/locales/zh-CN/worktrees.json b/webview-ui/src/i18n/locales/zh-CN/worktrees.json index 8b8f71cd471..8ebcf0e04f4 100644 --- a/webview-ui/src/i18n/locales/zh-CN/worktrees.json +++ b/webview-ui/src/i18n/locales/zh-CN/worktrees.json @@ -54,5 +54,7 @@ "worktreeIsLocked": "worktree 已锁定", "deleting": "正在删除...", - "close": "关闭" + "close": "关闭", + + "showInHomeScreen": "在主屏幕显示 worktrees" } diff --git a/webview-ui/src/i18n/locales/zh-TW/worktrees.json b/webview-ui/src/i18n/locales/zh-TW/worktrees.json index a42476b2553..8a4abc47446 100644 --- a/webview-ui/src/i18n/locales/zh-TW/worktrees.json +++ b/webview-ui/src/i18n/locales/zh-TW/worktrees.json @@ -54,5 +54,7 @@ "worktreeIsLocked": "worktree 已鎖定", "deleting": "正在刪除...", - "close": "關閉" + "close": "關閉", + + "showInHomeScreen": "在主畫面顯示 worktrees" } From 09d5f1045c66d67ae536144f78eab31f990e3cfd Mon Sep 17 00:00:00 2001 From: Bruno Bergher Date: Sat, 24 Jan 2026 17:30:14 +0000 Subject: [PATCH 05/11] i18n --- webview-ui/src/i18n/locales/ca/worktrees.json | 23 +++++++++++++------ webview-ui/src/i18n/locales/de/worktrees.json | 23 +++++++++++++------ webview-ui/src/i18n/locales/es/worktrees.json | 23 +++++++++++++------ webview-ui/src/i18n/locales/fr/worktrees.json | 23 +++++++++++++------ webview-ui/src/i18n/locales/hi/worktrees.json | 23 +++++++++++++------ webview-ui/src/i18n/locales/id/worktrees.json | 23 +++++++++++++------ webview-ui/src/i18n/locales/it/worktrees.json | 23 +++++++++++++------ webview-ui/src/i18n/locales/ja/worktrees.json | 23 +++++++++++++------ webview-ui/src/i18n/locales/ko/worktrees.json | 23 +++++++++++++------ webview-ui/src/i18n/locales/nl/worktrees.json | 23 +++++++++++++------ webview-ui/src/i18n/locales/pl/worktrees.json | 23 +++++++++++++------ .../src/i18n/locales/pt-BR/worktrees.json | 23 +++++++++++++------ webview-ui/src/i18n/locales/ru/worktrees.json | 23 +++++++++++++------ webview-ui/src/i18n/locales/tr/worktrees.json | 23 +++++++++++++------ webview-ui/src/i18n/locales/vi/worktrees.json | 23 +++++++++++++------ .../src/i18n/locales/zh-CN/worktrees.json | 23 +++++++++++++------ .../src/i18n/locales/zh-TW/worktrees.json | 23 +++++++++++++------ 17 files changed, 272 insertions(+), 119 deletions(-) diff --git a/webview-ui/src/i18n/locales/ca/worktrees.json b/webview-ui/src/i18n/locales/ca/worktrees.json index a3596c36e27..e84c8a716bf 100644 --- a/webview-ui/src/i18n/locales/ca/worktrees.json +++ b/webview-ui/src/i18n/locales/ca/worktrees.json @@ -18,13 +18,12 @@ "detachedHead": "HEAD separat", "noBranch": "Sense branca", - "openInCurrentWindow": "Obre a la finestra actual", + "switchInThisWindow": "Canvia a worktree", "openInNewWindow": "Obre en una finestra nova", "delete": "Suprimeix", "newWorktree": "Worktree nou", "createWorktree": "Crea worktree", - "createWorktreeDescription": "Crea un worktree nou per treballar en una branca diferent dins del seu propi directori.", "branchName": "Nom de la branca", "createNewBranch": "Crea una branca nova", "checkoutExisting": "Fes checkout d'una branca existent", @@ -35,8 +34,9 @@ "noBranchFound": "No s'ha trobat cap branca", "localBranches": "Branques locals", "remoteBranches": "Branques remotes", - "worktreePath": "Camí del worktree", - "pathHint": "El camí on es crearà el worktree", + "worktreePath": "En", + "selectWorktreeLocation": "Selecciona la ubicació del Worktree", + "selectFolderForWorktree": "Selecciona carpeta per al worktree nou", "noIncludeFileWarning": "No hi ha cap fitxer .worktreeinclude", "noIncludeFileHint": "Sense un fitxer .worktreeinclude, fitxers com node_modules no es copiaran al worktree nou. Potser hauràs d'executar npm install després de crear-lo.", "create": "Crea", @@ -46,15 +46,24 @@ "cancel": "Cancel·la", "deleteWorktree": "Suprimeix worktree", - "deleteWorktreeDescription": "Això eliminarà el worktree i tots els seus fitxers.", "deleteWarning": "Aquesta acció no es pot desfer. S'eliminarà:", - "deleteWarningBranch": "La branca '{{branch}}' i tots els canvis sense confirmar", + "deleteWarningBranch": "La branca i qualsevol canvi sense confirmar", "deleteWarningFiles": "Tots els fitxers del directori del worktree", + "deleteNoticeLarge": "Si és un gran repositori, podria trigar una mica.", "forceDelete": "Força la supressió", "worktreeIsLocked": "el worktree està bloquejat", "deleting": "S'està suprimint...", "close": "Tanca", - "showInHomeScreen": "Mostra worktrees a la pantalla d'inici" + "showInHomeScreen": "Mostra worktrees a la pantalla d'inici", + + "selector": { + "worktree": "Worktree", + "title": "Worktrees", + "tooltip": "Canvia entre worktrees", + "description": "Els worktrees de Git et permeten treballar en diverses branques simultàniament. Fes clic per canviar l'espai de treball.", + "settings": "Gestiona Worktrees", + "info": "Els worktrees de Git et permeten tenir diversos directoris de treball adjunts al mateix repositori." + } } diff --git a/webview-ui/src/i18n/locales/de/worktrees.json b/webview-ui/src/i18n/locales/de/worktrees.json index 89e128ebc03..eed464fd5ee 100644 --- a/webview-ui/src/i18n/locales/de/worktrees.json +++ b/webview-ui/src/i18n/locales/de/worktrees.json @@ -18,13 +18,12 @@ "detachedHead": "Detached HEAD", "noBranch": "Kein Branch", - "openInCurrentWindow": "Im aktuellen Fenster öffnen", + "switchInThisWindow": "Zu Worktree wechseln", "openInNewWindow": "In neuem Fenster öffnen", "delete": "Löschen", "newWorktree": "Neuer Worktree", "createWorktree": "Worktree erstellen", - "createWorktreeDescription": "Erstelle einen neuen Worktree, um in einem eigenen Verzeichnis an einem separaten Branch zu arbeiten.", "branchName": "Branch-Name", "createNewBranch": "Neuen Branch erstellen", "checkoutExisting": "Vorhandenen Branch auschecken", @@ -35,8 +34,9 @@ "noBranchFound": "Kein Branch gefunden", "localBranches": "Lokale Branches", "remoteBranches": "Remote-Branches", - "worktreePath": "Worktree-Pfad", - "pathHint": "Der Pfad, in dem der Worktree erstellt wird", + "worktreePath": "In", + "selectWorktreeLocation": "Worktree-Speicherort auswählen", + "selectFolderForWorktree": "Ordner für neuen Worktree auswählen", "noIncludeFileWarning": "Keine .worktreeinclude-Datei", "noIncludeFileHint": "Ohne eine .worktreeinclude-Datei werden Dateien wie node_modules nicht in den neuen Worktree kopiert. Möglicherweise musst du nach dem Erstellen npm install ausführen.", "create": "Erstellen", @@ -46,15 +46,24 @@ "cancel": "Abbrechen", "deleteWorktree": "Worktree löschen", - "deleteWorktreeDescription": "Dadurch wird der Worktree und alle seine Dateien entfernt.", "deleteWarning": "Diese Aktion kann nicht rückgängig gemacht werden. Folgendes wird gelöscht:", - "deleteWarningBranch": "Der Branch '{{branch}}' und alle nicht committeten Änderungen", + "deleteWarningBranch": "Der Branch und alle nicht committeten Änderungen", "deleteWarningFiles": "Alle Dateien im Worktree-Verzeichnis", + "deleteNoticeLarge": "Bei großen Repositorys kann dies eine Weile dauern.", "forceDelete": "Löschen erzwingen", "worktreeIsLocked": "Worktree ist gesperrt", "deleting": "Wird gelöscht...", "close": "Schließen", - "showInHomeScreen": "Worktrees auf dem Startbildschirm anzeigen" + "showInHomeScreen": "Worktrees auf dem Startbildschirm anzeigen", + + "selector": { + "worktree": "Worktree", + "title": "Worktrees", + "tooltip": "Zwischen Worktrees wechseln", + "description": "Git Worktrees ermöglichen dir, gleichzeitig an mehreren Branches zu arbeiten. Klicke hier, um den Workspace zu wechseln.", + "settings": "Worktrees verwalten", + "info": "Git Worktrees ermöglichen dir, mehrere Arbeitsverzeichnisse mit demselben Repository zu verbinden." + } } diff --git a/webview-ui/src/i18n/locales/es/worktrees.json b/webview-ui/src/i18n/locales/es/worktrees.json index ac8716c3ea8..f78203d06db 100644 --- a/webview-ui/src/i18n/locales/es/worktrees.json +++ b/webview-ui/src/i18n/locales/es/worktrees.json @@ -18,13 +18,12 @@ "detachedHead": "HEAD separado", "noBranch": "Sin rama", - "openInCurrentWindow": "Abrir en la ventana actual", + "switchInThisWindow": "Cambiar a worktree", "openInNewWindow": "Abrir en una ventana nueva", "delete": "Eliminar", "newWorktree": "Nuevo Worktree", "createWorktree": "Crear Worktree", - "createWorktreeDescription": "Crea un worktree nuevo para trabajar en una rama separada en su propio directorio.", "branchName": "Nombre de la rama", "createNewBranch": "Crear rama nueva", "checkoutExisting": "Hacer checkout de una rama existente", @@ -35,8 +34,9 @@ "noBranchFound": "No se encontró ninguna rama", "localBranches": "Ramas locales", "remoteBranches": "Ramas remotas", - "worktreePath": "Ruta del worktree", - "pathHint": "La ruta donde se creará el worktree", + "worktreePath": "En", + "selectWorktreeLocation": "Seleccionar ubicación del Worktree", + "selectFolderForWorktree": "Seleccionar carpeta para el worktree nuevo", "noIncludeFileWarning": "No hay archivo .worktreeinclude", "noIncludeFileHint": "Sin un archivo .worktreeinclude, archivos como node_modules no se copiarán al worktree nuevo. Puede que tengas que ejecutar npm install después de crearlo.", "create": "Crear", @@ -46,15 +46,24 @@ "cancel": "Cancelar", "deleteWorktree": "Eliminar Worktree", - "deleteWorktreeDescription": "Esto eliminará el worktree y todos sus archivos.", "deleteWarning": "Esta acción no se puede deshacer. Se eliminará lo siguiente:", - "deleteWarningBranch": "La rama '{{branch}}' y todos los cambios sin confirmar", + "deleteWarningBranch": "La rama y todos los cambios sin confirmar", "deleteWarningFiles": "Todos los archivos del directorio del worktree", + "deleteNoticeLarge": "Si es un repositorio grande, podría tomar un tiempo.", "forceDelete": "Forzar eliminación", "worktreeIsLocked": "el worktree está bloqueado", "deleting": "Eliminando...", "close": "Cerrar", - "showInHomeScreen": "Mostrar worktrees en la pantalla de inicio" + "showInHomeScreen": "Mostrar worktrees en la pantalla de inicio", + + "selector": { + "worktree": "Worktree", + "title": "Worktrees", + "tooltip": "Cambiar entre worktrees", + "description": "Los worktrees de Git te permiten trabajar en varias ramas simultáneamente. Haz clic para cambiar el espacio de trabajo.", + "settings": "Gestionar Worktrees", + "info": "Los worktrees de Git te permiten tener varios directorios de trabajo adjuntos al mismo repositorio." + } } diff --git a/webview-ui/src/i18n/locales/fr/worktrees.json b/webview-ui/src/i18n/locales/fr/worktrees.json index 6d08809467d..2cc8bfca0dd 100644 --- a/webview-ui/src/i18n/locales/fr/worktrees.json +++ b/webview-ui/src/i18n/locales/fr/worktrees.json @@ -18,13 +18,12 @@ "detachedHead": "HEAD détachée", "noBranch": "Aucune branche", - "openInCurrentWindow": "Ouvrir dans la fenêtre actuelle", + "switchInThisWindow": "Changer vers worktree", "openInNewWindow": "Ouvrir dans une nouvelle fenêtre", "delete": "Supprimer", "newWorktree": "Nouveau Worktree", "createWorktree": "Créer un worktree", - "createWorktreeDescription": "Crée un worktree pour travailler sur une autre branche dans son propre répertoire.", "branchName": "Nom de la branche", "createNewBranch": "Créer une nouvelle branche", "checkoutExisting": "Checkout d'une branche existante", @@ -35,8 +34,9 @@ "noBranchFound": "Aucune branche trouvée", "localBranches": "Branches locales", "remoteBranches": "Branches distantes", - "worktreePath": "Chemin du worktree", - "pathHint": "Le chemin où le worktree sera créé", + "worktreePath": "En", + "selectWorktreeLocation": "Sélectionner l'emplacement du Worktree", + "selectFolderForWorktree": "Sélectionner le dossier pour le nouveau worktree", "noIncludeFileWarning": "Aucun fichier .worktreeinclude", "noIncludeFileHint": "Sans fichier .worktreeinclude, des fichiers comme node_modules ne seront pas copiés dans le nouveau worktree. Tu devras peut-être exécuter npm install après l'avoir créé.", "create": "Créer", @@ -46,15 +46,24 @@ "cancel": "Annuler", "deleteWorktree": "Supprimer le worktree", - "deleteWorktreeDescription": "Cela supprimera le worktree et tous ses fichiers.", "deleteWarning": "Cette action est irréversible. Les éléments suivants seront supprimés :", - "deleteWarningBranch": "La branche '{{branch}}' et toutes les modifications non validées", + "deleteWarningBranch": "La branche et toutes les modifications non validées", "deleteWarningFiles": "Tous les fichiers dans le répertoire du worktree", + "deleteNoticeLarge": "Si c'est un grand dépôt, cela peut prendre un peu de temps.", "forceDelete": "Forcer la suppression", "worktreeIsLocked": "le worktree est verrouillé", "deleting": "Suppression...", "close": "Fermer", - "showInHomeScreen": "Afficher les worktrees sur l'écran d'accueil" + "showInHomeScreen": "Afficher les worktrees sur l'écran d'accueil", + + "selector": { + "worktree": "Worktree", + "title": "Worktrees", + "tooltip": "Changer entre les worktrees", + "description": "Les worktrees Git te permettent de travailler sur plusieurs branches en même temps. Clique pour changer d'espace de travail.", + "settings": "Gérer les Worktrees", + "info": "Les worktrees Git te permettent d'avoir plusieurs répertoires de travail attachés au même dépôt." + } } diff --git a/webview-ui/src/i18n/locales/hi/worktrees.json b/webview-ui/src/i18n/locales/hi/worktrees.json index 71dead28b99..e568c3844d7 100644 --- a/webview-ui/src/i18n/locales/hi/worktrees.json +++ b/webview-ui/src/i18n/locales/hi/worktrees.json @@ -18,13 +18,12 @@ "detachedHead": "Detached HEAD", "noBranch": "कोई ब्रांच नहीं", - "openInCurrentWindow": "वर्तमान विंडो में खोलें", + "switchInThisWindow": "Worktree पर स्विच करें", "openInNewWindow": "नई विंडो में खोलें", "delete": "हटाएँ", "newWorktree": "नया Worktree", "createWorktree": "Worktree बनाएँ", - "createWorktreeDescription": "अपने अलग डायरेक्टरी में किसी अलग ब्रांच पर काम करने के लिए नया worktree बनाएँ।", "branchName": "ब्रांच नाम", "createNewBranch": "नई ब्रांच बनाएँ", "checkoutExisting": "मौजूदा ब्रांच checkout करें", @@ -35,8 +34,9 @@ "noBranchFound": "कोई ब्रांच नहीं मिली", "localBranches": "लोकल ब्रांच", "remoteBranches": "रिमोट ब्रांच", - "worktreePath": "Worktree पाथ", - "pathHint": "वह पाथ जहाँ worktree बनाया जाएगा", + "worktreePath": "में", + "selectWorktreeLocation": "Worktree स्थान चुनें", + "selectFolderForWorktree": "नए worktree के लिए फ़ोल्डर चुनें", "noIncludeFileWarning": ".worktreeinclude फ़ाइल नहीं है", "noIncludeFileHint": ".worktreeinclude फ़ाइल के बिना, node_modules जैसी फ़ाइलें नए worktree में कॉपी नहीं होंगी। इसे बनाने के बाद आपको npm install चलाना पड़ सकता है।", "create": "बनाएँ", @@ -46,15 +46,24 @@ "cancel": "रद्द करें", "deleteWorktree": "Worktree हटाएँ", - "deleteWorktreeDescription": "यह worktree और उसकी सभी फ़ाइलें हटा देगा।", "deleteWarning": "यह कार्रवाई वापस नहीं ली जा सकती। निम्नलिखित हटाया जाएगा:", - "deleteWarningBranch": "ब्रांच '{{branch}}' और सभी uncommitted बदलाव", + "deleteWarningBranch": "ब्रांच और सभी uncommitted बदलाव", "deleteWarningFiles": "worktree डायरेक्टरी की सभी फ़ाइलें", + "deleteNoticeLarge": "अगर यह एक बड़ी रिपोज़िटरी है तो यह कुछ समय ले सकता है।", "forceDelete": "जबरन हटाएँ", "worktreeIsLocked": "worktree लॉक्ड है", "deleting": "हटाया जा रहा है...", "close": "बंद करें", - "showInHomeScreen": "होम स्क्रीन में worktrees दिखाएँ" + "showInHomeScreen": "होम स्क्रीन में worktrees दिखाएँ", + + "selector": { + "worktree": "Worktree", + "title": "Worktrees", + "tooltip": "Worktrees के बीच स्विच करें", + "description": "Git worktrees आपको एक साथ कई ब्रांच पर काम करने देते हैं। workspace स्विच करने के लिए क्लिक करें।", + "settings": "Worktrees को प्रबंधित करें", + "info": "Git worktrees आपको एक ही रिपोज़िटरी से जुड़ी कई working directories रखने देते हैं।" + } } diff --git a/webview-ui/src/i18n/locales/id/worktrees.json b/webview-ui/src/i18n/locales/id/worktrees.json index d6218887309..f3dc9449160 100644 --- a/webview-ui/src/i18n/locales/id/worktrees.json +++ b/webview-ui/src/i18n/locales/id/worktrees.json @@ -18,13 +18,12 @@ "detachedHead": "Detached HEAD", "noBranch": "Tidak ada branch", - "openInCurrentWindow": "Buka di jendela saat ini", + "switchInThisWindow": "Beralih ke worktree", "openInNewWindow": "Buka di jendela baru", "delete": "Hapus", "newWorktree": "Worktree Baru", "createWorktree": "Buat Worktree", - "createWorktreeDescription": "Buat worktree baru untuk bekerja pada branch terpisah di direktori sendiri.", "branchName": "Nama branch", "createNewBranch": "Buat branch baru", "checkoutExisting": "Checkout branch yang sudah ada", @@ -35,8 +34,9 @@ "noBranchFound": "Branch tidak ditemukan", "localBranches": "Branch lokal", "remoteBranches": "Branch remote", - "worktreePath": "Path worktree", - "pathHint": "Path tempat worktree akan dibuat", + "worktreePath": "Di", + "selectWorktreeLocation": "Pilih Lokasi Worktree", + "selectFolderForWorktree": "Pilih folder untuk worktree baru", "noIncludeFileWarning": "Tidak ada file .worktreeinclude", "noIncludeFileHint": "Tanpa file .worktreeinclude, file seperti node_modules tidak akan disalin ke worktree baru. Kamu mungkin perlu menjalankan npm install setelah membuatnya.", "create": "Buat", @@ -46,15 +46,24 @@ "cancel": "Batal", "deleteWorktree": "Hapus Worktree", - "deleteWorktreeDescription": "Ini akan menghapus worktree dan semua filenya.", "deleteWarning": "Tindakan ini tidak dapat dibatalkan. Yang berikut akan dihapus:", - "deleteWarningBranch": "Branch '{{branch}}' dan semua perubahan yang belum di-commit", + "deleteWarningBranch": "Branch dan semua perubahan yang belum di-commit", "deleteWarningFiles": "Semua file di direktori worktree", + "deleteNoticeLarge": "Jika ini adalah repositori besar, mungkin memerlukan waktu beberapa saat.", "forceDelete": "Paksa hapus", "worktreeIsLocked": "worktree terkunci", "deleting": "Menghapus...", "close": "Tutup", - "showInHomeScreen": "Tampilkan worktrees di layar beranda" + "showInHomeScreen": "Tampilkan worktrees di layar beranda", + + "selector": { + "worktree": "Worktree", + "title": "Worktrees", + "tooltip": "Beralih antar worktrees", + "description": "Git worktrees memungkinkan kamu bekerja di beberapa branch secara bersamaan. Klik untuk beralih workspace.", + "settings": "Kelola Worktrees", + "info": "Git worktrees memungkinkan kamu memiliki beberapa direktori kerja yang terhubung ke repositori yang sama." + } } diff --git a/webview-ui/src/i18n/locales/it/worktrees.json b/webview-ui/src/i18n/locales/it/worktrees.json index 6a3835719b2..dda88fa53c1 100644 --- a/webview-ui/src/i18n/locales/it/worktrees.json +++ b/webview-ui/src/i18n/locales/it/worktrees.json @@ -18,13 +18,12 @@ "detachedHead": "HEAD staccata", "noBranch": "Nessun branch", - "openInCurrentWindow": "Apri nella finestra corrente", + "switchInThisWindow": "Passa a worktree", "openInNewWindow": "Apri in una nuova finestra", "delete": "Elimina", "newWorktree": "Nuovo Worktree", "createWorktree": "Crea Worktree", - "createWorktreeDescription": "Crea un nuovo worktree per lavorare su un branch separato nella sua directory.", "branchName": "Nome del branch", "createNewBranch": "Crea nuovo branch", "checkoutExisting": "Fai checkout di un branch esistente", @@ -35,8 +34,9 @@ "noBranchFound": "Nessun branch trovato", "localBranches": "Branch locali", "remoteBranches": "Branch remoti", - "worktreePath": "Percorso del worktree", - "pathHint": "Il percorso in cui verrà creato il worktree", + "worktreePath": "In", + "selectWorktreeLocation": "Seleziona posizione Worktree", + "selectFolderForWorktree": "Seleziona cartella per il nuovo worktree", "noIncludeFileWarning": "Nessun file .worktreeinclude", "noIncludeFileHint": "Senza un file .worktreeinclude, file come node_modules non verranno copiati nel nuovo worktree. Potresti dover eseguire npm install dopo averlo creato.", "create": "Crea", @@ -46,15 +46,24 @@ "cancel": "Annulla", "deleteWorktree": "Elimina Worktree", - "deleteWorktreeDescription": "Questo rimuoverà il worktree e tutti i suoi file.", "deleteWarning": "Questa azione non può essere annullata. Verrà eliminato quanto segue:", - "deleteWarningBranch": "Il branch '{{branch}}' e tutte le modifiche non committate", + "deleteWarningBranch": "Il branch e tutte le modifiche non committate", "deleteWarningFiles": "Tutti i file nella directory del worktree", + "deleteNoticeLarge": "Se è un repository grande, potrebbe volerci un po'.", "forceDelete": "Forza eliminazione", "worktreeIsLocked": "il worktree è bloccato", "deleting": "Eliminazione...", "close": "Chiudi", - "showInHomeScreen": "Mostra worktrees nella schermata iniziale" + "showInHomeScreen": "Mostra worktrees nella schermata iniziale", + + "selector": { + "worktree": "Worktree", + "title": "Worktrees", + "tooltip": "Passa tra i worktrees", + "description": "I worktree di Git ti permettono di lavorare su più branch contemporaneamente. Fai clic per cambiare workspace.", + "settings": "Gestisci Worktrees", + "info": "I worktree di Git ti permettono di avere più directory di lavoro collegate allo stesso repository." + } } diff --git a/webview-ui/src/i18n/locales/ja/worktrees.json b/webview-ui/src/i18n/locales/ja/worktrees.json index 535088b94ed..f07bd3ea48c 100644 --- a/webview-ui/src/i18n/locales/ja/worktrees.json +++ b/webview-ui/src/i18n/locales/ja/worktrees.json @@ -18,13 +18,12 @@ "detachedHead": "Detached HEAD", "noBranch": "ブランチなし", - "openInCurrentWindow": "現在のウィンドウで開く", + "switchInThisWindow": "Worktree に切り替え", "openInNewWindow": "新しいウィンドウで開く", "delete": "削除", "newWorktree": "新しい Worktree", "createWorktree": "Worktree を作成", - "createWorktreeDescription": "別のブランチで作業するために、専用ディレクトリに新しい worktree を作成します。", "branchName": "ブランチ名", "createNewBranch": "新しいブランチを作成", "checkoutExisting": "既存のブランチをチェックアウト", @@ -35,8 +34,9 @@ "noBranchFound": "ブランチが見つかりません", "localBranches": "ローカルブランチ", "remoteBranches": "リモートブランチ", - "worktreePath": "Worktree のパス", - "pathHint": "worktree を作成するパス", + "worktreePath": "In", + "selectWorktreeLocation": "Worktree の場所を選択", + "selectFolderForWorktree": "新しい worktree のフォルダーを選択", "noIncludeFileWarning": ".worktreeinclude ファイルなし", "noIncludeFileHint": ".worktreeinclude ファイルがない場合、node_modules などのファイルは新しい worktree にコピーされません。作成後に npm install を実行する必要があるかもしれません。", "create": "作成", @@ -46,15 +46,24 @@ "cancel": "キャンセル", "deleteWorktree": "Worktree を削除", - "deleteWorktreeDescription": "これにより worktree とそのファイルがすべて削除されます。", "deleteWarning": "この操作は元に戻せません。次のものが削除されます:", - "deleteWarningBranch": "ブランチ '{{branch}}' と未コミットの変更すべて", + "deleteWarningBranch": "ブランチと未コミットの変更すべて", "deleteWarningFiles": "worktree ディレクトリ内のすべてのファイル", + "deleteNoticeLarge": "大規模なリポジトリの場合、少し時間がかかる場合があります。", "forceDelete": "強制削除", "worktreeIsLocked": "worktree がロックされています", "deleting": "削除中...", "close": "閉じる", - "showInHomeScreen": "ホーム画面に worktrees を表示" + "showInHomeScreen": "ホーム画面に worktrees を表示", + + "selector": { + "worktree": "Worktree", + "title": "Worktrees", + "tooltip": "Worktree を切り替え", + "description": "Git worktrees を使うと、複数のブランチで同時に作業できます。クリックしてワークスペースを切り替えます。", + "settings": "Worktrees を管理", + "info": "Git worktrees を使うと、同じリポジトリに複数の作業ディレクトリを附属できます。" + } } diff --git a/webview-ui/src/i18n/locales/ko/worktrees.json b/webview-ui/src/i18n/locales/ko/worktrees.json index 04c8f18b7bf..388a508a9b5 100644 --- a/webview-ui/src/i18n/locales/ko/worktrees.json +++ b/webview-ui/src/i18n/locales/ko/worktrees.json @@ -18,13 +18,12 @@ "detachedHead": "Detached HEAD", "noBranch": "브랜치 없음", - "openInCurrentWindow": "현재 창에서 열기", + "switchInThisWindow": "Worktree로 전환", "openInNewWindow": "새 창에서 열기", "delete": "삭제", "newWorktree": "새 Worktree", "createWorktree": "Worktree 만들기", - "createWorktreeDescription": "별도의 브랜치에서 작업하기 위해 전용 디렉터리에 새 worktree를 만듭니다.", "branchName": "브랜치 이름", "createNewBranch": "새 브랜치 만들기", "checkoutExisting": "기존 브랜치 체크아웃", @@ -35,8 +34,9 @@ "noBranchFound": "브랜치를 찾을 수 없습니다", "localBranches": "로컬 브랜치", "remoteBranches": "원격 브랜치", - "worktreePath": "Worktree 경로", - "pathHint": "worktree가 생성될 경로", + "worktreePath": "In", + "selectWorktreeLocation": "Worktree 위치 선택", + "selectFolderForWorktree": "새 worktree의 폴더 선택", "noIncludeFileWarning": ".worktreeinclude 파일 없음", "noIncludeFileHint": ".worktreeinclude 파일이 없으면 node_modules 같은 파일이 새 worktree로 복사되지 않습니다. 생성 후 npm install을 실행해야 할 수도 있습니다.", "create": "만들기", @@ -46,15 +46,24 @@ "cancel": "취소", "deleteWorktree": "Worktree 삭제", - "deleteWorktreeDescription": "이 작업은 worktree와 그 안의 모든 파일을 제거합니다.", "deleteWarning": "이 작업은 되돌릴 수 없습니다. 다음이 삭제됩니다:", - "deleteWarningBranch": "브랜치 '{{branch}}' 및 커밋되지 않은 모든 변경 사항", + "deleteWarningBranch": "브랜치 및 커밋되지 않은 모든 변경 사항", "deleteWarningFiles": "worktree 디렉터리의 모든 파일", + "deleteNoticeLarge": "대규모 저장소의 경우 시간이 조금 걸릴 수 있습니다.", "forceDelete": "강제 삭제", "worktreeIsLocked": "worktree가 잠겨 있습니다", "deleting": "삭제 중...", "close": "닫기", - "showInHomeScreen": "홈 화면에 worktrees 표시" + "showInHomeScreen": "홈 화면에 worktrees 표시", + + "selector": { + "worktree": "Worktree", + "title": "Worktrees", + "tooltip": "Worktree 간 전환", + "description": "Git worktree를 사용하면 동시에 여러 브랜치에서 작업할 수 있습니다. 클릭하여 워크스페이스를 전환합니다.", + "settings": "Worktree 관리", + "info": "Git worktree를 사용하면 동일한 저장소에 여러 작업 디렉터리를 연결할 수 있습니다." + } } diff --git a/webview-ui/src/i18n/locales/nl/worktrees.json b/webview-ui/src/i18n/locales/nl/worktrees.json index f3d0436520a..8602d48527d 100644 --- a/webview-ui/src/i18n/locales/nl/worktrees.json +++ b/webview-ui/src/i18n/locales/nl/worktrees.json @@ -18,13 +18,12 @@ "detachedHead": "Detached HEAD", "noBranch": "Geen branch", - "openInCurrentWindow": "Openen in huidig venster", + "switchInThisWindow": "Naar worktree wisselen", "openInNewWindow": "Openen in nieuw venster", "delete": "Verwijderen", "newWorktree": "Nieuwe Worktree", "createWorktree": "Worktree aanmaken", - "createWorktreeDescription": "Maak een nieuwe worktree aan om in een aparte branch in zijn eigen map te werken.", "branchName": "Branchnaam", "createNewBranch": "Nieuwe branch aanmaken", "checkoutExisting": "Bestaande branch uitchecken", @@ -35,8 +34,9 @@ "noBranchFound": "Geen branch gevonden", "localBranches": "Lokale branches", "remoteBranches": "Remote-branches", - "worktreePath": "Worktree-pad", - "pathHint": "Het pad waar de worktree wordt aangemaakt", + "worktreePath": "In", + "selectWorktreeLocation": "Locatie Worktree selecteren", + "selectFolderForWorktree": "Map voor nieuwe worktree selecteren", "noIncludeFileWarning": "Geen .worktreeinclude-bestand", "noIncludeFileHint": "Zonder een .worktreeinclude-bestand worden bestanden zoals node_modules niet naar de nieuwe worktree gekopieerd. Mogelijk moet je na het aanmaken npm install uitvoeren.", "create": "Aanmaken", @@ -46,15 +46,24 @@ "cancel": "Annuleren", "deleteWorktree": "Worktree verwijderen", - "deleteWorktreeDescription": "Hiermee wordt de worktree en alle bestanden verwijderd.", "deleteWarning": "Deze actie kan niet ongedaan worden gemaakt. Het volgende wordt verwijderd:", - "deleteWarningBranch": "De branch '{{branch}}' en alle niet-gecommitte wijzigingen", + "deleteWarningBranch": "De branch en alle niet-gecommitte wijzigingen", "deleteWarningFiles": "Alle bestanden in de worktree-map", + "deleteNoticeLarge": "Als dit een grote repository is, kan dit even duren.", "forceDelete": "Geforceerd verwijderen", "worktreeIsLocked": "worktree is vergrendeld", "deleting": "Bezig met verwijderen...", "close": "Sluiten", - "showInHomeScreen": "Worktrees weergeven op startscherm" + "showInHomeScreen": "Worktrees weergeven op startscherm", + + "selector": { + "worktree": "Worktree", + "title": "Worktrees", + "tooltip": "Tussen worktrees wisselen", + "description": "Met Git worktrees kun je tegelijkertijd aan meerdere branches werken. Klik om van workspace te wisselen.", + "settings": "Worktrees beheren", + "info": "Met Git worktrees kun je meerdere werkdirectories aan dezelfde repository koppelen." + } } diff --git a/webview-ui/src/i18n/locales/pl/worktrees.json b/webview-ui/src/i18n/locales/pl/worktrees.json index dd76e124f4a..58fa26f7ac1 100644 --- a/webview-ui/src/i18n/locales/pl/worktrees.json +++ b/webview-ui/src/i18n/locales/pl/worktrees.json @@ -18,13 +18,12 @@ "detachedHead": "Detached HEAD", "noBranch": "Brak brancha", - "openInCurrentWindow": "Otwórz w bieżącym oknie", + "switchInThisWindow": "Przełącz na worktree", "openInNewWindow": "Otwórz w nowym oknie", "delete": "Usuń", "newWorktree": "Nowy Worktree", "createWorktree": "Utwórz Worktree", - "createWorktreeDescription": "Utwórz nowy worktree, aby pracować na oddzielnym branchu w osobnym katalogu.", "branchName": "Nazwa brancha", "createNewBranch": "Utwórz nowy branch", "checkoutExisting": "Checkout istniejącego brancha", @@ -35,8 +34,9 @@ "noBranchFound": "Nie znaleziono brancha", "localBranches": "Branche lokalne", "remoteBranches": "Branche zdalne", - "worktreePath": "Ścieżka worktree", - "pathHint": "Ścieżka, w której zostanie utworzony worktree", + "worktreePath": "W", + "selectWorktreeLocation": "Wybierz lokalizację Worktree", + "selectFolderForWorktree": "Wybierz folder dla nowego worktree", "noIncludeFileWarning": "Brak pliku .worktreeinclude", "noIncludeFileHint": "Bez pliku .worktreeinclude pliki takie jak node_modules nie zostaną skopiowane do nowego worktree. Po utworzeniu może być konieczne uruchomienie npm install.", "create": "Utwórz", @@ -46,15 +46,24 @@ "cancel": "Anuluj", "deleteWorktree": "Usuń Worktree", - "deleteWorktreeDescription": "To usunie worktree oraz wszystkie jego pliki.", "deleteWarning": "Tej akcji nie można cofnąć. Zostanie usunięte:", - "deleteWarningBranch": "Branch '{{branch}}' i wszystkie niezatwierdzone zmiany", + "deleteWarningBranch": "Branch i wszystkie niezatwierdzone zmiany", "deleteWarningFiles": "Wszystkie pliki w katalogu worktree", + "deleteNoticeLarge": "Jeśli jest to duże repozytorium, może to chwilę potrwać.", "forceDelete": "Wymuś usunięcie", "worktreeIsLocked": "worktree jest zablokowany", "deleting": "Usuwanie...", "close": "Zamknij", - "showInHomeScreen": "Pokaż worktrees na ekranie głównym" + "showInHomeScreen": "Pokaż worktrees na ekranie głównym", + + "selector": { + "worktree": "Worktree", + "title": "Worktrees", + "tooltip": "Przełączaj się między worktrees", + "description": "Git worktrees pozwalają pracować jednocześnie na wielu branchach. Kliknij, aby zmienić workspace.", + "settings": "Zarządzaj Worktrees", + "info": "Git worktrees pozwalają mieć wiele katalogów roboczych dołączonych do tego samego repozytorium." + } } diff --git a/webview-ui/src/i18n/locales/pt-BR/worktrees.json b/webview-ui/src/i18n/locales/pt-BR/worktrees.json index 72c32034132..4e438d6a9c4 100644 --- a/webview-ui/src/i18n/locales/pt-BR/worktrees.json +++ b/webview-ui/src/i18n/locales/pt-BR/worktrees.json @@ -18,13 +18,12 @@ "detachedHead": "Detached HEAD", "noBranch": "Sem branch", - "openInCurrentWindow": "Abrir na janela atual", + "switchInThisWindow": "Mudar para worktree", "openInNewWindow": "Abrir em uma nova janela", "delete": "Excluir", "newWorktree": "Novo Worktree", "createWorktree": "Criar Worktree", - "createWorktreeDescription": "Crie um novo worktree para trabalhar em um branch separado no seu próprio diretório.", "branchName": "Nome do branch", "createNewBranch": "Criar novo branch", "checkoutExisting": "Fazer checkout de um branch existente", @@ -35,8 +34,9 @@ "noBranchFound": "Nenhum branch encontrado", "localBranches": "Branches locais", "remoteBranches": "Branches remotos", - "worktreePath": "Caminho do worktree", - "pathHint": "O caminho onde o worktree será criado", + "worktreePath": "Em", + "selectWorktreeLocation": "Selecionar local do Worktree", + "selectFolderForWorktree": "Selecionar pasta para o novo worktree", "noIncludeFileWarning": "Sem arquivo .worktreeinclude", "noIncludeFileHint": "Sem um arquivo .worktreeinclude, arquivos como node_modules não serão copiados para o novo worktree. Você pode precisar executar npm install depois de criá-lo.", "create": "Criar", @@ -46,15 +46,24 @@ "cancel": "Cancelar", "deleteWorktree": "Excluir Worktree", - "deleteWorktreeDescription": "Isso removerá o worktree e todos os seus arquivos.", "deleteWarning": "Esta ação não pode ser desfeita. O seguinte será excluído:", - "deleteWarningBranch": "O branch '{{branch}}' e todas as alterações não commitadas", + "deleteWarningBranch": "O branch e todas as alterações não commitadas", "deleteWarningFiles": "Todos os arquivos no diretório do worktree", + "deleteNoticeLarge": "Se for um repositório grande, pode levar um pouco.", "forceDelete": "Forçar exclusão", "worktreeIsLocked": "worktree está bloqueado", "deleting": "Excluindo...", "close": "Fechar", - "showInHomeScreen": "Mostrar worktrees na tela inicial" + "showInHomeScreen": "Mostrar worktrees na tela inicial", + + "selector": { + "worktree": "Worktree", + "title": "Worktrees", + "tooltip": "Alterne entre worktrees", + "description": "Os worktrees do Git permitem trabalhar em vários branches simultaneamente. Clique para alternar o workspace.", + "settings": "Gerenciar Worktrees", + "info": "Os worktrees do Git permitem ter vários diretórios de trabalho conectados ao mesmo repositório." + } } diff --git a/webview-ui/src/i18n/locales/ru/worktrees.json b/webview-ui/src/i18n/locales/ru/worktrees.json index 85c36390fb0..a3ea03c3ef4 100644 --- a/webview-ui/src/i18n/locales/ru/worktrees.json +++ b/webview-ui/src/i18n/locales/ru/worktrees.json @@ -18,13 +18,12 @@ "detachedHead": "Detached HEAD", "noBranch": "Нет ветки", - "openInCurrentWindow": "Открыть в текущем окне", + "switchInThisWindow": "Перейти на worktree", "openInNewWindow": "Открыть в новом окне", "delete": "Удалить", "newWorktree": "Новый Worktree", "createWorktree": "Создать Worktree", - "createWorktreeDescription": "Создай новый worktree, чтобы работать с отдельной веткой в своём каталоге.", "branchName": "Имя ветки", "createNewBranch": "Создать новую ветку", "checkoutExisting": "Переключиться на существующую ветку", @@ -35,8 +34,9 @@ "noBranchFound": "Ветка не найдена", "localBranches": "Локальные ветки", "remoteBranches": "Удалённые ветки", - "worktreePath": "Путь worktree", - "pathHint": "Путь, где будет создан worktree", + "worktreePath": "В", + "selectWorktreeLocation": "Выбрать расположение Worktree", + "selectFolderForWorktree": "Выбрать папку для нового worktree", "noIncludeFileWarning": "Нет файла .worktreeinclude", "noIncludeFileHint": "Без файла .worktreeinclude файлы вроде node_modules не будут скопированы в новый worktree. Возможно, после создания нужно будет выполнить npm install.", "create": "Создать", @@ -46,15 +46,24 @@ "cancel": "Отмена", "deleteWorktree": "Удалить Worktree", - "deleteWorktreeDescription": "Это удалит worktree и все его файлы.", "deleteWarning": "Это действие нельзя отменить. Будет удалено:", - "deleteWarningBranch": "Ветка '{{branch}}' и все незакоммиченные изменения", + "deleteWarningBranch": "Ветка и все незакоммиченные изменения", "deleteWarningFiles": "Все файлы в каталоге worktree", + "deleteNoticeLarge": "Если это большой репозиторий, это может занять некоторое время.", "forceDelete": "Удалить принудительно", "worktreeIsLocked": "worktree заблокирован", "deleting": "Удаление...", "close": "Закрыть", - "showInHomeScreen": "Показывать worktrees на главном экране" + "showInHomeScreen": "Показывать worktrees на главном экране", + + "selector": { + "worktree": "Worktree", + "title": "Worktrees", + "tooltip": "Переключайтесь между worktrees", + "description": "Git worktrees позволяют работать с несколькими ветками одновременно. Нажми, чтобы переключить workspace.", + "settings": "Управление Worktrees", + "info": "Git worktrees позволяют иметь несколько рабочих каталогов, подключенных к одному репозиторию." + } } diff --git a/webview-ui/src/i18n/locales/tr/worktrees.json b/webview-ui/src/i18n/locales/tr/worktrees.json index e7bfa3866ae..50e5a3ba827 100644 --- a/webview-ui/src/i18n/locales/tr/worktrees.json +++ b/webview-ui/src/i18n/locales/tr/worktrees.json @@ -18,13 +18,12 @@ "detachedHead": "Detached HEAD", "noBranch": "Branch yok", - "openInCurrentWindow": "Mevcut pencerede aç", + "switchInThisWindow": "Worktree'ye geç", "openInNewWindow": "Yeni pencerede aç", "delete": "Sil", "newWorktree": "Yeni Worktree", "createWorktree": "Worktree oluştur", - "createWorktreeDescription": "Kendi dizininde ayrı bir branch üzerinde çalışmak için yeni bir worktree oluştur.", "branchName": "Branch adı", "createNewBranch": "Yeni branch oluştur", "checkoutExisting": "Mevcut branch'i checkout et", @@ -35,8 +34,9 @@ "noBranchFound": "Branch bulunamadı", "localBranches": "Yerel branch'ler", "remoteBranches": "Uzak branch'ler", - "worktreePath": "Worktree yolu", - "pathHint": "Worktree'nin oluşturulacağı yol", + "worktreePath": "In", + "selectWorktreeLocation": "Worktree Konumunu Seç", + "selectFolderForWorktree": "Yeni worktree için klasör seç", "noIncludeFileWarning": ".worktreeinclude dosyası yok", "noIncludeFileHint": ".worktreeinclude dosyası olmadan node_modules gibi dosyalar yeni worktree'ye kopyalanmaz. Oluşturduktan sonra npm install çalıştırman gerekebilir.", "create": "Oluştur", @@ -46,15 +46,24 @@ "cancel": "İptal", "deleteWorktree": "Worktree'yi sil", - "deleteWorktreeDescription": "Bu işlem worktree'yi ve tüm dosyalarını kaldırır.", "deleteWarning": "Bu işlem geri alınamaz. Şunlar silinecek:", - "deleteWarningBranch": "'{{branch}}' branch'i ve commit edilmemiş tüm değişiklikler", + "deleteWarningBranch": "Branch'i ve commit edilmemiş tüm değişiklikler", "deleteWarningFiles": "worktree dizinindeki tüm dosyalar", + "deleteNoticeLarge": "Bu büyük bir depo ise, biraz zaman alabilir.", "forceDelete": "Silmeye zorla", "worktreeIsLocked": "worktree kilitli", "deleting": "Siliniyor...", "close": "Kapat", - "showInHomeScreen": "Ana ekranda worktrees göster" + "showInHomeScreen": "Ana ekranda worktrees göster", + + "selector": { + "worktree": "Worktree", + "title": "Worktrees", + "tooltip": "Worktree'ler arasında geç", + "description": "Git worktree'leri aynı anda birden fazla branch'te çalışmanı sağlar. Workspace'i değiştirmek için tıkla.", + "settings": "Worktree'leri Yönet", + "info": "Git worktree'leri aynı depo ile bağlantılı birden fazla çalışma dizinine sahip olmanı sağlar." + } } diff --git a/webview-ui/src/i18n/locales/vi/worktrees.json b/webview-ui/src/i18n/locales/vi/worktrees.json index 3897007f903..28b80891c69 100644 --- a/webview-ui/src/i18n/locales/vi/worktrees.json +++ b/webview-ui/src/i18n/locales/vi/worktrees.json @@ -18,13 +18,12 @@ "detachedHead": "Detached HEAD", "noBranch": "Không có nhánh", - "openInCurrentWindow": "Mở trong cửa sổ hiện tại", + "switchInThisWindow": "Chuyển sang worktree", "openInNewWindow": "Mở trong cửa sổ mới", "delete": "Xóa", "newWorktree": "Worktree Mới", "createWorktree": "Tạo Worktree", - "createWorktreeDescription": "Tạo worktree mới để làm việc trên một nhánh riêng trong thư mục riêng của nó.", "branchName": "Tên nhánh", "createNewBranch": "Tạo nhánh mới", "checkoutExisting": "Checkout nhánh hiện có", @@ -35,8 +34,9 @@ "noBranchFound": "Không tìm thấy nhánh", "localBranches": "Nhánh cục bộ", "remoteBranches": "Nhánh từ xa", - "worktreePath": "Đường dẫn worktree", - "pathHint": "Đường dẫn nơi worktree sẽ được tạo", + "worktreePath": "Trong", + "selectWorktreeLocation": "Chọn vị trí Worktree", + "selectFolderForWorktree": "Chọn thư mục cho worktree mới", "noIncludeFileWarning": "Không có tệp .worktreeinclude", "noIncludeFileHint": "Không có tệp .worktreeinclude thì các tệp như node_modules sẽ không được sao chép sang worktree mới. Bạn có thể cần chạy npm install sau khi tạo.", "create": "Tạo", @@ -46,15 +46,24 @@ "cancel": "Hủy", "deleteWorktree": "Xóa Worktree", - "deleteWorktreeDescription": "Thao tác này sẽ xóa worktree và tất cả các tệp của nó.", "deleteWarning": "Không thể hoàn tác thao tác này. Những thứ sau sẽ bị xóa:", - "deleteWarningBranch": "Nhánh '{{branch}}' và tất cả thay đổi chưa commit", + "deleteWarningBranch": "Nhánh và tất cả thay đổi chưa commit", "deleteWarningFiles": "Tất cả tệp trong thư mục worktree", + "deleteNoticeLarge": "Nếu đây là kho lớn, có thể mất một chút thời gian.", "forceDelete": "Buộc xóa", "worktreeIsLocked": "worktree đang bị khóa", "deleting": "Đang xóa...", "close": "Đóng", - "showInHomeScreen": "Hiển thị worktrees trên màn hình chính" + "showInHomeScreen": "Hiển thị worktrees trên màn hình chính", + + "selector": { + "worktree": "Worktree", + "title": "Worktrees", + "tooltip": "Chuyển đổi giữa các worktrees", + "description": "Git worktrees cho phép bạn làm việc trên nhiều nhánh cùng lúc. Nhấp để chuyển workspace.", + "settings": "Quản lý Worktrees", + "info": "Git worktrees cho phép bạn có nhiều thư mục làm việc được kết nối với cùng một kho." + } } diff --git a/webview-ui/src/i18n/locales/zh-CN/worktrees.json b/webview-ui/src/i18n/locales/zh-CN/worktrees.json index 8ebcf0e04f4..2ff06dd9a77 100644 --- a/webview-ui/src/i18n/locales/zh-CN/worktrees.json +++ b/webview-ui/src/i18n/locales/zh-CN/worktrees.json @@ -18,13 +18,12 @@ "detachedHead": "Detached HEAD", "noBranch": "无分支", - "openInCurrentWindow": "在当前窗口打开", + "switchInThisWindow": "切换到 worktree", "openInNewWindow": "在新窗口打开", "delete": "删除", "newWorktree": "新建 Worktree", "createWorktree": "创建 Worktree", - "createWorktreeDescription": "创建一个新的 worktree,在独立目录中处理单独的分支。", "branchName": "分支名称", "createNewBranch": "创建新分支", "checkoutExisting": "Checkout 现有分支", @@ -35,8 +34,9 @@ "noBranchFound": "未找到分支", "localBranches": "本地分支", "remoteBranches": "远程分支", - "worktreePath": "Worktree 路径", - "pathHint": "worktree 将创建到的路径", + "worktreePath": "在", + "selectWorktreeLocation": "选择 Worktree 位置", + "selectFolderForWorktree": "为新 worktree 选择文件夹", "noIncludeFileWarning": "没有 .worktreeinclude 文件", "noIncludeFileHint": "没有 .worktreeinclude 文件时,node_modules 等文件不会复制到新 worktree。创建后你可能需要运行 npm install。", "create": "创建", @@ -46,15 +46,24 @@ "cancel": "取消", "deleteWorktree": "删除 Worktree", - "deleteWorktreeDescription": "这将删除 worktree 及其所有文件。", "deleteWarning": "此操作不可逆。将删除以下内容:", - "deleteWarningBranch": "分支 '{{branch}}' 以及所有未提交的更改", + "deleteWarningBranch": "分支以及所有未提交的更改", "deleteWarningFiles": "worktree 目录中的所有文件", + "deleteNoticeLarge": "如果这是一个大型仓库,可能需要一些时间。", "forceDelete": "强制删除", "worktreeIsLocked": "worktree 已锁定", "deleting": "正在删除...", "close": "关闭", - "showInHomeScreen": "在主屏幕显示 worktrees" + "showInHomeScreen": "在主屏幕显示 worktrees", + + "selector": { + "worktree": "Worktree", + "title": "Worktrees", + "tooltip": "在 worktrees 之间切换", + "description": "Git worktrees 让你能在多个分支上同时工作。点击以切换 workspace。", + "settings": "管理 Worktrees", + "info": "Git worktrees 允许你将多个工作目录连接到同一个仓库。" + } } diff --git a/webview-ui/src/i18n/locales/zh-TW/worktrees.json b/webview-ui/src/i18n/locales/zh-TW/worktrees.json index 8a4abc47446..6085d25dd3a 100644 --- a/webview-ui/src/i18n/locales/zh-TW/worktrees.json +++ b/webview-ui/src/i18n/locales/zh-TW/worktrees.json @@ -18,13 +18,12 @@ "detachedHead": "Detached HEAD", "noBranch": "無分支", - "openInCurrentWindow": "在目前視窗開啟", + "switchInThisWindow": "切換到 worktree", "openInNewWindow": "在新視窗開啟", "delete": "刪除", "newWorktree": "新增 Worktree", "createWorktree": "建立 Worktree", - "createWorktreeDescription": "建立新的 worktree,讓你在獨立目錄中處理單獨的分支。", "branchName": "分支名稱", "createNewBranch": "建立新分支", "checkoutExisting": "Checkout 現有分支", @@ -35,8 +34,9 @@ "noBranchFound": "找不到分支", "localBranches": "本機分支", "remoteBranches": "遠端分支", - "worktreePath": "Worktree 路徑", - "pathHint": "worktree 將建立到的路徑", + "worktreePath": "位於", + "selectWorktreeLocation": "選取 Worktree 位置", + "selectFolderForWorktree": "為新 worktree 選取資料夾", "noIncludeFileWarning": "沒有 .worktreeinclude 檔案", "noIncludeFileHint": "沒有 .worktreeinclude 檔案時,node_modules 等檔案不會複製到新的 worktree。建立後你可能需要執行 npm install。", "create": "建立", @@ -46,15 +46,24 @@ "cancel": "取消", "deleteWorktree": "刪除 Worktree", - "deleteWorktreeDescription": "這會刪除 worktree 及其所有檔案。", "deleteWarning": "此操作無法復原。將刪除以下內容:", - "deleteWarningBranch": "分支 '{{branch}}' 以及所有未提交的變更", + "deleteWarningBranch": "分支以及所有未提交的變更", "deleteWarningFiles": "worktree 目錄中的所有檔案", + "deleteNoticeLarge": "如果這是大型儲存庫,可能需要一些時間。", "forceDelete": "強制刪除", "worktreeIsLocked": "worktree 已鎖定", "deleting": "正在刪除...", "close": "關閉", - "showInHomeScreen": "在主畫面顯示 worktrees" + "showInHomeScreen": "在主畫面顯示 worktrees", + + "selector": { + "worktree": "Worktree", + "title": "Worktrees", + "tooltip": "在 worktrees 之間切換", + "description": "Git worktrees 讓你能在多個分支上同時工作。點選以切換工作區。", + "settings": "管理 Worktrees", + "info": "Git worktrees 允許你將多個工作目錄連線到同一個儲存庫。" + } } From d3c63c115a6a102f515d387c84e9e73d53766d3e Mon Sep 17 00:00:00 2001 From: Bruno Bergher Date: Sat, 24 Jan 2026 17:42:44 +0000 Subject: [PATCH 06/11] Fixes i18n --- src/i18n/locales/ca/worktrees.json | 4 ++++ src/i18n/locales/de/worktrees.json | 4 ++++ src/i18n/locales/en/worktrees.json | 4 ++++ src/i18n/locales/es/worktrees.json | 4 ++++ src/i18n/locales/fr/worktrees.json | 4 ++++ src/i18n/locales/hi/worktrees.json | 4 ++++ src/i18n/locales/id/worktrees.json | 4 ++++ src/i18n/locales/it/worktrees.json | 4 ++++ src/i18n/locales/ja/worktrees.json | 4 ++++ src/i18n/locales/ko/worktrees.json | 4 ++++ src/i18n/locales/nl/worktrees.json | 4 ++++ src/i18n/locales/pl/worktrees.json | 4 ++++ src/i18n/locales/pt-BR/worktrees.json | 4 ++++ src/i18n/locales/ru/worktrees.json | 4 ++++ src/i18n/locales/tr/worktrees.json | 4 ++++ src/i18n/locales/vi/worktrees.json | 4 ++++ src/i18n/locales/zh-CN/worktrees.json | 4 ++++ src/i18n/locales/zh-TW/worktrees.json | 4 ++++ 18 files changed, 72 insertions(+) create mode 100644 src/i18n/locales/ca/worktrees.json create mode 100644 src/i18n/locales/de/worktrees.json create mode 100644 src/i18n/locales/en/worktrees.json create mode 100644 src/i18n/locales/es/worktrees.json create mode 100644 src/i18n/locales/fr/worktrees.json create mode 100644 src/i18n/locales/hi/worktrees.json create mode 100644 src/i18n/locales/id/worktrees.json create mode 100644 src/i18n/locales/it/worktrees.json create mode 100644 src/i18n/locales/ja/worktrees.json create mode 100644 src/i18n/locales/ko/worktrees.json create mode 100644 src/i18n/locales/nl/worktrees.json create mode 100644 src/i18n/locales/pl/worktrees.json create mode 100644 src/i18n/locales/pt-BR/worktrees.json create mode 100644 src/i18n/locales/ru/worktrees.json create mode 100644 src/i18n/locales/tr/worktrees.json create mode 100644 src/i18n/locales/vi/worktrees.json create mode 100644 src/i18n/locales/zh-CN/worktrees.json create mode 100644 src/i18n/locales/zh-TW/worktrees.json diff --git a/src/i18n/locales/ca/worktrees.json b/src/i18n/locales/ca/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/ca/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} diff --git a/src/i18n/locales/de/worktrees.json b/src/i18n/locales/de/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/de/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} diff --git a/src/i18n/locales/en/worktrees.json b/src/i18n/locales/en/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/en/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} diff --git a/src/i18n/locales/es/worktrees.json b/src/i18n/locales/es/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/es/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} diff --git a/src/i18n/locales/fr/worktrees.json b/src/i18n/locales/fr/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/fr/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} diff --git a/src/i18n/locales/hi/worktrees.json b/src/i18n/locales/hi/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/hi/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} diff --git a/src/i18n/locales/id/worktrees.json b/src/i18n/locales/id/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/id/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} diff --git a/src/i18n/locales/it/worktrees.json b/src/i18n/locales/it/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/it/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} diff --git a/src/i18n/locales/ja/worktrees.json b/src/i18n/locales/ja/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/ja/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} diff --git a/src/i18n/locales/ko/worktrees.json b/src/i18n/locales/ko/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/ko/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} diff --git a/src/i18n/locales/nl/worktrees.json b/src/i18n/locales/nl/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/nl/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} diff --git a/src/i18n/locales/pl/worktrees.json b/src/i18n/locales/pl/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/pl/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} diff --git a/src/i18n/locales/pt-BR/worktrees.json b/src/i18n/locales/pt-BR/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/pt-BR/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} diff --git a/src/i18n/locales/ru/worktrees.json b/src/i18n/locales/ru/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/ru/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} diff --git a/src/i18n/locales/tr/worktrees.json b/src/i18n/locales/tr/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/tr/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} diff --git a/src/i18n/locales/vi/worktrees.json b/src/i18n/locales/vi/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/vi/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} diff --git a/src/i18n/locales/zh-CN/worktrees.json b/src/i18n/locales/zh-CN/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/zh-CN/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} diff --git a/src/i18n/locales/zh-TW/worktrees.json b/src/i18n/locales/zh-TW/worktrees.json new file mode 100644 index 00000000000..5be60dc737f --- /dev/null +++ b/src/i18n/locales/zh-TW/worktrees.json @@ -0,0 +1,4 @@ +{ + "selectWorktreeLocation": "Select Worktree Location", + "selectFolderForWorktree": "Select folder for new worktree" +} From 615b0dfa0710079c735cc51b773ccaf86fe98ee2 Mon Sep 17 00:00:00 2001 From: Bruno Bergher Date: Sat, 24 Jan 2026 17:46:41 +0000 Subject: [PATCH 07/11] Remove mergeresultmodel --- .../components/worktrees/MergeResultModal.tsx | 89 ------------------- 1 file changed, 89 deletions(-) delete mode 100644 webview-ui/src/components/worktrees/MergeResultModal.tsx diff --git a/webview-ui/src/components/worktrees/MergeResultModal.tsx b/webview-ui/src/components/worktrees/MergeResultModal.tsx deleted file mode 100644 index 7e82705b917..00000000000 --- a/webview-ui/src/components/worktrees/MergeResultModal.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import type { MergeWorktreeResult } from "@roo-code/types" - -import { useAppTranslation } from "@/i18n/TranslationContext" -import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, Button } from "@/components/ui" -import { Check, TriangleAlert, XCircle } from "lucide-react" - -interface MergeResultModalProps { - open: boolean - onClose: () => void - result: MergeWorktreeResult - onAskRooResolve: () => void -} - -export const MergeResultModal = ({ open, onClose, result, onAskRooResolve }: MergeResultModalProps) => { - const { t } = useAppTranslation() - - // Determine the title and icon based on result state - const getResultDisplay = () => { - if (result.success) { - return { - title: t("worktrees:mergeSuccess"), - icon: , - } - } - if (result.hasConflicts) { - return { - title: t("worktrees:mergeConflicts"), - icon: , - } - } - return { - title: t("worktrees:mergeFailed"), - icon: , - } - } - - const { title, icon } = getResultDisplay() - - return ( - !isOpen && onClose()}> - - - - {icon} - {title} - - - -
- {result.success ? ( -

{result.message}

- ) : result.hasConflicts ? ( - <> -

- {t("worktrees:conflictsDescription")} -

- - {/* Conflicting files list */} -
- {result.conflictingFiles.map((file) => ( -
- {file} -
- ))} -
- - ) : ( -

{result.message}

- )} -
- - - {result.success ? ( - - ) : result.hasConflicts ? ( - <> - - - - ) : ( - - )} - -
-
- ) -} From b84b13dffcaf28039bbc560312be0efa85c0ce07 Mon Sep 17 00:00:00 2001 From: Bruno Bergher Date: Sat, 24 Jan 2026 21:10:40 +0000 Subject: [PATCH 08/11] i18n --- webview-ui/src/i18n/locales/ca/settings.json | 1 + webview-ui/src/i18n/locales/de/settings.json | 1 + webview-ui/src/i18n/locales/es/settings.json | 1 + webview-ui/src/i18n/locales/fr/settings.json | 1 + webview-ui/src/i18n/locales/hi/settings.json | 1 + webview-ui/src/i18n/locales/id/settings.json | 1 + webview-ui/src/i18n/locales/it/settings.json | 1 + webview-ui/src/i18n/locales/ja/settings.json | 1 + webview-ui/src/i18n/locales/ko/settings.json | 1 + webview-ui/src/i18n/locales/nl/settings.json | 1 + webview-ui/src/i18n/locales/pl/settings.json | 1 + webview-ui/src/i18n/locales/pt-BR/settings.json | 1 + webview-ui/src/i18n/locales/ru/settings.json | 1 + webview-ui/src/i18n/locales/tr/settings.json | 1 + webview-ui/src/i18n/locales/vi/settings.json | 1 + webview-ui/src/i18n/locales/zh-CN/settings.json | 1 + webview-ui/src/i18n/locales/zh-TW/settings.json | 1 + 17 files changed, 17 insertions(+) diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index 8709334e5ae..1509137a902 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -29,6 +29,7 @@ "providers": "Proveïdors", "modes": "Modes", "mcp": "Servidors MCP", + "worktrees": "Worktrees", "autoApprove": "Auto-aprovació", "browser": "Accés a l'ordinador", "checkpoints": "Punts de control", diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index cb09cba088b..bc275a64e50 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -29,6 +29,7 @@ "providers": "Anbieter", "modes": "Modi", "mcp": "MCP-Server", + "worktrees": "Worktrees", "autoApprove": "Auto-Genehmigung", "browser": "Computerzugriff", "checkpoints": "Kontrollpunkte", diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index b8c124614a7..36243b99be0 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -29,6 +29,7 @@ "providers": "Proveedores", "modes": "Modos", "mcp": "Servidores MCP", + "worktrees": "Worktrees", "autoApprove": "Auto-aprobación", "browser": "Acceso al ordenador", "checkpoints": "Puntos de control", diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 8dbd308aa83..1c28b763077 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -29,6 +29,7 @@ "providers": "Fournisseurs", "modes": "Modes", "mcp": "Serveurs MCP", + "worktrees": "Worktrees", "autoApprove": "Auto-approbation", "browser": "Accès ordinateur", "checkpoints": "Points de contrôle", diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index 1f74fd4aae7..4974ff706b4 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -29,6 +29,7 @@ "providers": "प्रदाता", "modes": "मोड", "mcp": "एमसीपी सर्वर", + "worktrees": "Worktrees", "autoApprove": "अनुमोदन", "browser": "ब्राउज़र", "checkpoints": "चेकपॉइंट", diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index 26b1ca0e8ac..908c975a5b8 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -29,6 +29,7 @@ "providers": "Provider", "modes": "Mode", "mcp": "Server MCP", + "worktrees": "Worktrees", "autoApprove": "Auto-Approve", "browser": "Browser", "checkpoints": "Checkpoint", diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index 8a6da00b847..1c3c7e494d7 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -29,6 +29,7 @@ "providers": "Fornitori", "modes": "Modalità", "mcp": "Server MCP", + "worktrees": "Worktrees", "autoApprove": "Auto-approvazione", "browser": "Accesso computer", "checkpoints": "Punti di controllo", diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index 1ebea573b9b..b4af9d4033e 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -29,6 +29,7 @@ "providers": "プロバイダー", "modes": "モード", "mcp": "MCPサーバー", + "worktrees": "Worktrees", "autoApprove": "自動承認", "browser": "コンピューターアクセス", "checkpoints": "チェックポイント", diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index a0f1b7a710b..2888d75bb0b 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -29,6 +29,7 @@ "providers": "공급자", "modes": "모드", "mcp": "MCP 서버", + "worktrees": "Worktrees", "autoApprove": "자동 승인", "browser": "컴퓨터 접근", "checkpoints": "체크포인트", diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index 5ff57bf331e..83e1f4b7ab3 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -29,6 +29,7 @@ "providers": "Providers", "modes": "Modi", "mcp": "MCP-servers", + "worktrees": "Worktrees", "autoApprove": "Auto-goedkeuren", "browser": "Browser", "checkpoints": "Checkpoints", diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index 1986522f267..7c339f96a5b 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -29,6 +29,7 @@ "providers": "Dostawcy", "modes": "Tryby", "mcp": "Serwery MCP", + "worktrees": "Worktrees", "autoApprove": "Auto-zatwierdzanie", "browser": "Dostęp komputera", "checkpoints": "Punkty kontrolne", diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index e45efdf6665..04a786ab11e 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -29,6 +29,7 @@ "providers": "Provedores", "modes": "Modos", "mcp": "Servidores MCP", + "worktrees": "Worktrees", "autoApprove": "Aprovação", "browser": "Navegador", "checkpoints": "Checkpoints", diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index ca1c790c87b..ebdbc01b931 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -29,6 +29,7 @@ "providers": "Провайдеры", "modes": "Режимы", "mcp": "Серверы MCP", + "worktrees": "Worktrees", "autoApprove": "Автоодобрение", "browser": "Доступ к компьютеру", "checkpoints": "Контрольные точки", diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 7d275b23e63..5a7daeec1d7 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -29,6 +29,7 @@ "providers": "Sağlayıcılar", "modes": "Modlar", "mcp": "MCP Sunucuları", + "worktrees": "Worktrees", "autoApprove": "Oto-Onay", "browser": "Bilgisayar Erişimi", "checkpoints": "Kontrol Noktaları", diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index 3e0f4594f5f..3e8e22d8f0c 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -29,6 +29,7 @@ "providers": "Nhà cung cấp", "modes": "Chế độ", "mcp": "Máy chủ MCP", + "worktrees": "Worktrees", "autoApprove": "Phê duyệt", "browser": "Trình duyệt", "checkpoints": "Điểm kiểm tra", diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 701570903c1..85bc9bd431b 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -29,6 +29,7 @@ "providers": "提供商", "modes": "模式", "mcp": "MCP 服务", + "worktrees": "Worktrees", "autoApprove": "自动批准", "browser": "计算机交互", "checkpoints": "存档点", diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index ec6dc04fdf9..b33443238ab 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -29,6 +29,7 @@ "providers": "供應商", "modes": "模式", "mcp": "MCP 伺服器", + "worktrees": "Worktrees", "autoApprove": "自動核准", "browser": "電腦存取", "checkpoints": "檢查點", From 75e163c6fcb6514e5c919071c397c5fdc3ab8788 Mon Sep 17 00:00:00 2001 From: Bruno Bergher Date: Sat, 24 Jan 2026 21:16:45 +0000 Subject: [PATCH 09/11] tests --- .../__tests__/SettingsView.change-detection.spec.tsx | 5 +++++ .../components/settings/__tests__/SettingsView.spec.tsx | 5 +++++ .../__tests__/SettingsView.unsaved-changes.spec.tsx | 5 +++++ .../src/components/ui/__tests__/toggle-switch.spec.tsx | 8 ++++---- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/webview-ui/src/components/settings/__tests__/SettingsView.change-detection.spec.tsx b/webview-ui/src/components/settings/__tests__/SettingsView.change-detection.spec.tsx index 8f9467c332f..ddaf6a7b996 100644 --- a/webview-ui/src/components/settings/__tests__/SettingsView.change-detection.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/SettingsView.change-detection.spec.tsx @@ -28,6 +28,11 @@ vi.mock("@src/i18n/TranslationContext", () => ({ // Mock UI components vi.mock("@src/components/ui", () => ({ + ToggleSwitch: ({ checked, onChange, "aria-label": ariaLabel, "data-testid": dataTestId }: any) => ( + + ), AlertDialog: ({ open, children }: any) => (open ?
{children}
: null), AlertDialogContent: ({ children }: any) =>
{children}
, AlertDialogTitle: ({ children }: any) =>
{children}
, diff --git a/webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx b/webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx index 913cce743e6..b80fee3ee10 100644 --- a/webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx @@ -116,6 +116,11 @@ vi.mock("../../../components/common/Tab", () => ({ vi.mock("@/components/ui", () => ({ ...vi.importActual("@/components/ui"), + ToggleSwitch: ({ checked, onChange, "aria-label": ariaLabel, "data-testid": dataTestId }: any) => ( + + ), Popover: ({ children }: any) =>
{children}
, PopoverTrigger: ({ children }: any) =>
{children}
, PopoverContent: ({ children }: any) =>
{children}
, diff --git a/webview-ui/src/components/settings/__tests__/SettingsView.unsaved-changes.spec.tsx b/webview-ui/src/components/settings/__tests__/SettingsView.unsaved-changes.spec.tsx index 726d0248cfe..4a1733c376d 100644 --- a/webview-ui/src/components/settings/__tests__/SettingsView.unsaved-changes.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/SettingsView.unsaved-changes.spec.tsx @@ -29,6 +29,11 @@ vi.mock("@src/i18n/TranslationContext", () => ({ // Mock UI components vi.mock("@src/components/ui", () => ({ + ToggleSwitch: ({ checked, onChange, "aria-label": ariaLabel, "data-testid": dataTestId }: any) => ( + + ), AlertDialog: ({ children }: any) =>
{children}
, AlertDialogContent: ({ children }: any) =>
{children}
, AlertDialogTitle: ({ children }: any) =>
{children}
, diff --git a/webview-ui/src/components/ui/__tests__/toggle-switch.spec.tsx b/webview-ui/src/components/ui/__tests__/toggle-switch.spec.tsx index e394e761399..81823447bd5 100644 --- a/webview-ui/src/components/ui/__tests__/toggle-switch.spec.tsx +++ b/webview-ui/src/components/ui/__tests__/toggle-switch.spec.tsx @@ -85,8 +85,8 @@ describe("ToggleSwitch", () => { const toggle = screen.getByRole("switch") expect(toggle).toBeInTheDocument() - // Medium size should be 20px x 10px - expect(toggle).toHaveStyle({ width: "20px", height: "10px" }) + // Medium size should be 26px x 10px + expect(toggle).toHaveStyle({ width: "26px", height: "10px" }) }) it("defaults to small size", () => { @@ -95,7 +95,7 @@ describe("ToggleSwitch", () => { const toggle = screen.getByRole("switch") expect(toggle).toBeInTheDocument() - // Small size should be 16px x 8px - expect(toggle).toHaveStyle({ width: "16px", height: "8px" }) + // Small size should be 20px x 10px + expect(toggle).toHaveStyle({ width: "20px", height: "10px" }) }) }) From 533683a4172b48a27adebc3765c073e5ab4985ac Mon Sep 17 00:00:00 2001 From: Bruno Bergher Date: Sat, 24 Jan 2026 21:22:02 +0000 Subject: [PATCH 10/11] knip --- .../worktrees/MergeWorktreeModal.tsx | 89 ------------------- webview-ui/src/components/worktrees/index.ts | 3 - 2 files changed, 92 deletions(-) delete mode 100644 webview-ui/src/components/worktrees/MergeWorktreeModal.tsx delete mode 100644 webview-ui/src/components/worktrees/index.ts diff --git a/webview-ui/src/components/worktrees/MergeWorktreeModal.tsx b/webview-ui/src/components/worktrees/MergeWorktreeModal.tsx deleted file mode 100644 index 2d8e964d2cd..00000000000 --- a/webview-ui/src/components/worktrees/MergeWorktreeModal.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import type { Worktree } from "@roo-code/types" - -import { useAppTranslation } from "@/i18n/TranslationContext" -import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, Button, Checkbox } from "@/components/ui" -import { ArrowBigRightDash, GitBranch } from "lucide-react" - -interface MergeWorktreeModalProps { - open: boolean - onClose: () => void - worktree: Worktree - targetBranch: string - deleteAfterMerge: boolean - onDeleteAfterMergeChange: (checked: boolean) => void - isMerging: boolean - onMerge: () => void -} - -export const MergeWorktreeModal = ({ - open, - onClose, - worktree, - targetBranch, - deleteAfterMerge, - onDeleteAfterMergeChange, - isMerging, - onMerge, -}: MergeWorktreeModalProps) => { - const { t } = useAppTranslation() - - return ( - !isOpen && onClose()}> - - - {t("worktrees:mergeBranch")} - - -
- {/* Merge info */} -
-
- - {worktree.branch} -
- -
- -
- -
- - {targetBranch} -
-
- - {/* Delete after merge option */} -
- onDeleteAfterMergeChange(checked === true)} - /> - -
-
- - - - - -
-
- ) -} diff --git a/webview-ui/src/components/worktrees/index.ts b/webview-ui/src/components/worktrees/index.ts deleted file mode 100644 index cdf20f972e6..00000000000 --- a/webview-ui/src/components/worktrees/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { WorktreesView } from "./WorktreesView" -export { CreateWorktreeModal } from "./CreateWorktreeModal" -export { DeleteWorktreeModal } from "./DeleteWorktreeModal" From 584d6815c5ed1836fc01109814b412d8e65899c2 Mon Sep 17 00:00:00 2001 From: Bruno Bergher Date: Sat, 24 Jan 2026 21:25:43 +0000 Subject: [PATCH 11/11] code review --- webview-ui/src/components/worktrees/WorktreesView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webview-ui/src/components/worktrees/WorktreesView.tsx b/webview-ui/src/components/worktrees/WorktreesView.tsx index 02654b2705e..1df762c207d 100644 --- a/webview-ui/src/components/worktrees/WorktreesView.tsx +++ b/webview-ui/src/components/worktrees/WorktreesView.tsx @@ -128,7 +128,7 @@ export const WorktreesView = () => { setShowWorktreesInHomeScreen(newValue) vscode.postMessage({ type: "updateSettings", - values: { showWorktreesInHomeScreen: newValue }, + updatedSettings: { showWorktreesInHomeScreen: newValue }, }) }, [showWorktreesInHomeScreen, setShowWorktreesInHomeScreen])