mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-10-06 02:47:56 +00:00
ux: improve worktree selector and creation UX (#10940)
* Delete modal * Restructured * Much more prominent * UI * i18n * Fixes i18n * Remove mergeresultmodel * i18n * tests * knip * code review
This commit is contained in:
parent
c7910a99c7
commit
c56f0f43c7
97 changed files with 1208 additions and 399 deletions
|
|
@ -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<typeof globalSettingsSchema>
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ export interface ExtensionMessage {
|
|||
| "worktreeDefaults"
|
||||
| "worktreeIncludeStatus"
|
||||
| "branchWorktreeIncludeResult"
|
||||
| "folderSelected"
|
||||
text?: string
|
||||
payload?: any // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
checkpointWarning?: {
|
||||
|
|
@ -119,7 +120,6 @@ export interface ExtensionMessage {
|
|||
| "historyButtonClicked"
|
||||
| "marketplaceButtonClicked"
|
||||
| "cloudButtonClicked"
|
||||
| "worktreesButtonClicked"
|
||||
| "didBecomeVisible"
|
||||
| "focusInput"
|
||||
| "switchTab"
|
||||
|
|
@ -257,6 +257,8 @@ export interface ExtensionMessage {
|
|||
copyProgressBytesCopied?: number
|
||||
copyProgressTotalBytes?: number
|
||||
copyProgressItemName?: string
|
||||
// folderSelected
|
||||
path?: string
|
||||
}
|
||||
|
||||
export interface OpenAiCodexRateLimitsMessage {
|
||||
|
|
@ -332,6 +334,7 @@ export type ExtensionState = Pick<
|
|||
| "includeCurrentCost"
|
||||
| "maxGitStatusFiles"
|
||||
| "requestDelaySeconds"
|
||||
| "showWorktreesInHomeScreen"
|
||||
> & {
|
||||
version: string
|
||||
clineMessages: ClineMessage[]
|
||||
|
|
@ -600,6 +603,7 @@ export interface WebviewMessage {
|
|||
| "checkBranchWorktreeInclude"
|
||||
| "createWorktreeInclude"
|
||||
| "checkoutBranch"
|
||||
| "browseForWorktreePath"
|
||||
text?: string
|
||||
editedMessageContent?: string
|
||||
tab?: "settings" | "history" | "mcp" | "modes" | "chat" | "marketplace" | "cloud"
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ export const commandIds = [
|
|||
"popoutButtonClicked",
|
||||
"cloudButtonClicked",
|
||||
"settingsButtonClicked",
|
||||
"worktreesButtonClicked",
|
||||
|
||||
"openInNewTab",
|
||||
|
||||
|
|
|
|||
|
|
@ -134,12 +134,6 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt
|
|||
if (!visibleProvider) return
|
||||
visibleProvider.postMessageToWebview({ type: "action", action: "marketplaceButtonClicked" })
|
||||
},
|
||||
worktreesButtonClicked: () => {
|
||||
const visibleProvider = getVisibleProviderOrLog(outputChannel)
|
||||
if (!visibleProvider) return
|
||||
TelemetryService.instance.captureTitleButtonClicked("worktrees")
|
||||
visibleProvider.postMessageToWebview({ type: "action", action: "worktreesButtonClicked" })
|
||||
},
|
||||
newTask: handleNewTask,
|
||||
setCustomStoragePath: async () => {
|
||||
const { promptForCustomStoragePath } = await import("../utils/storage")
|
||||
|
|
|
|||
|
|
@ -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}`)
|
||||
//
|
||||
|
|
|
|||
4
src/i18n/locales/ca/worktrees.json
generated
Normal file
4
src/i18n/locales/ca/worktrees.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
4
src/i18n/locales/de/worktrees.json
generated
Normal file
4
src/i18n/locales/de/worktrees.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
4
src/i18n/locales/en/worktrees.json
Normal file
4
src/i18n/locales/en/worktrees.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
4
src/i18n/locales/es/worktrees.json
generated
Normal file
4
src/i18n/locales/es/worktrees.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
4
src/i18n/locales/fr/worktrees.json
generated
Normal file
4
src/i18n/locales/fr/worktrees.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
4
src/i18n/locales/hi/worktrees.json
generated
Normal file
4
src/i18n/locales/hi/worktrees.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
4
src/i18n/locales/id/worktrees.json
generated
Normal file
4
src/i18n/locales/id/worktrees.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
4
src/i18n/locales/it/worktrees.json
generated
Normal file
4
src/i18n/locales/it/worktrees.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
4
src/i18n/locales/ja/worktrees.json
generated
Normal file
4
src/i18n/locales/ja/worktrees.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
4
src/i18n/locales/ko/worktrees.json
generated
Normal file
4
src/i18n/locales/ko/worktrees.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
4
src/i18n/locales/nl/worktrees.json
generated
Normal file
4
src/i18n/locales/nl/worktrees.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
4
src/i18n/locales/pl/worktrees.json
generated
Normal file
4
src/i18n/locales/pl/worktrees.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
4
src/i18n/locales/pt-BR/worktrees.json
generated
Normal file
4
src/i18n/locales/pt-BR/worktrees.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
4
src/i18n/locales/ru/worktrees.json
generated
Normal file
4
src/i18n/locales/ru/worktrees.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
4
src/i18n/locales/tr/worktrees.json
generated
Normal file
4
src/i18n/locales/tr/worktrees.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
4
src/i18n/locales/vi/worktrees.json
generated
Normal file
4
src/i18n/locales/vi/worktrees.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
4
src/i18n/locales/zh-CN/worktrees.json
generated
Normal file
4
src/i18n/locales/zh-CN/worktrees.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
4
src/i18n/locales/zh-TW/worktrees.json
generated
Normal file
4
src/i18n/locales/zh-TW/worktrees.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"selectWorktreeLocation": "Select Worktree Location",
|
||||
"selectFolderForWorktree": "Select folder for new worktree"
|
||||
}
|
||||
|
|
@ -100,11 +100,6 @@
|
|||
"title": "%command.settings.title%",
|
||||
"icon": "$(settings-gear)"
|
||||
},
|
||||
{
|
||||
"command": "roo-cline.worktreesButtonClicked",
|
||||
"title": "%command.worktrees.title%",
|
||||
"icon": "$(git-branch)"
|
||||
},
|
||||
{
|
||||
"command": "roo-cline.openInNewTab",
|
||||
"title": "%command.openInNewTab.title%",
|
||||
|
|
|
|||
1
src/package.nls.ca.json
generated
1
src/package.nls.ca.json
generated
|
|
@ -24,7 +24,6 @@
|
|||
"command.openInEditor.title": "Obrir a l'Editor",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "Configuració",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "Documentació",
|
||||
"configuration.title": "Roo Code",
|
||||
"commands.allowedCommands.description": "Ordres que es poden executar automàticament quan 'Aprova sempre les operacions d'execució' està activat",
|
||||
|
|
|
|||
1
src/package.nls.de.json
generated
1
src/package.nls.de.json
generated
|
|
@ -24,7 +24,6 @@
|
|||
"command.openInEditor.title": "Im Editor Öffnen",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "Einstellungen",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "Dokumentation",
|
||||
"configuration.title": "Roo Code",
|
||||
"commands.allowedCommands.description": "Befehle, die automatisch ausgeführt werden können, wenn 'Ausführungsoperationen immer genehmigen' aktiviert ist",
|
||||
|
|
|
|||
1
src/package.nls.es.json
generated
1
src/package.nls.es.json
generated
|
|
@ -24,7 +24,6 @@
|
|||
"command.openInEditor.title": "Abrir en Editor",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "Configuración",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "Documentación",
|
||||
"configuration.title": "Roo Code",
|
||||
"commands.allowedCommands.description": "Comandos que pueden ejecutarse automáticamente cuando 'Aprobar siempre operaciones de ejecución' está activado",
|
||||
|
|
|
|||
1
src/package.nls.fr.json
generated
1
src/package.nls.fr.json
generated
|
|
@ -24,7 +24,6 @@
|
|||
"command.openInEditor.title": "Ouvrir dans l'Éditeur",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "Paramètres",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "Documentation",
|
||||
"configuration.title": "Roo Code",
|
||||
"commands.allowedCommands.description": "Commandes pouvant être exécutées automatiquement lorsque 'Toujours approuver les opérations d'exécution' est activé",
|
||||
|
|
|
|||
1
src/package.nls.hi.json
generated
1
src/package.nls.hi.json
generated
|
|
@ -24,7 +24,6 @@
|
|||
"command.openInEditor.title": "एडिटर में खोलें",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "सेटिंग्स",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "दस्तावेज़ीकरण",
|
||||
"configuration.title": "Roo Code",
|
||||
"commands.allowedCommands.description": "वे कमांड जो स्वचालित रूप से निष्पादित की जा सकती हैं जब 'हमेशा निष्पादन संचालन को स्वीकृत करें' सक्रिय हो",
|
||||
|
|
|
|||
1
src/package.nls.id.json
generated
1
src/package.nls.id.json
generated
|
|
@ -11,7 +11,6 @@
|
|||
"command.openInEditor.title": "Buka di Editor",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "Pengaturan",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "Dokumentasi",
|
||||
"command.openInNewTab.title": "Buka di Tab Baru",
|
||||
"command.explainCode.title": "Jelaskan Kode",
|
||||
|
|
|
|||
1
src/package.nls.it.json
generated
1
src/package.nls.it.json
generated
|
|
@ -24,7 +24,6 @@
|
|||
"command.openInEditor.title": "Apri nell'Editor",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "Impostazioni",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "Documentazione",
|
||||
"configuration.title": "Roo Code",
|
||||
"commands.allowedCommands.description": "Comandi che possono essere eseguiti automaticamente quando 'Approva sempre le operazioni di esecuzione' è attivato",
|
||||
|
|
|
|||
1
src/package.nls.ja.json
generated
1
src/package.nls.ja.json
generated
|
|
@ -11,7 +11,6 @@
|
|||
"command.openInEditor.title": "エディタで開く",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "設定",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "ドキュメント",
|
||||
"command.openInNewTab.title": "新しいタブで開く",
|
||||
"command.explainCode.title": "コードの説明",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
"command.openInEditor.title": "Open in Editor",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "Settings",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "Documentation",
|
||||
"command.openInNewTab.title": "Open In New Tab",
|
||||
"command.explainCode.title": "Explain Code",
|
||||
|
|
|
|||
1
src/package.nls.ko.json
generated
1
src/package.nls.ko.json
generated
|
|
@ -24,7 +24,6 @@
|
|||
"command.openInEditor.title": "에디터에서 열기",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "설정",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "문서",
|
||||
"configuration.title": "Roo Code",
|
||||
"commands.allowedCommands.description": "'항상 실행 작업 승인' 이 활성화되어 있을 때 자동으로 실행할 수 있는 명령어",
|
||||
|
|
|
|||
1
src/package.nls.nl.json
generated
1
src/package.nls.nl.json
generated
|
|
@ -11,7 +11,6 @@
|
|||
"command.openInEditor.title": "Openen in Editor",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "Instellingen",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "Documentatie",
|
||||
"command.openInNewTab.title": "Openen in Nieuw Tabblad",
|
||||
"command.explainCode.title": "Leg Code Uit",
|
||||
|
|
|
|||
1
src/package.nls.pl.json
generated
1
src/package.nls.pl.json
generated
|
|
@ -24,7 +24,6 @@
|
|||
"command.openInEditor.title": "Otwórz w Edytorze",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "Ustawienia",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "Dokumentacja",
|
||||
"configuration.title": "Roo Code",
|
||||
"commands.allowedCommands.description": "Polecenia, które mogą być wykonywane automatycznie, gdy włączona jest opcja 'Zawsze zatwierdzaj operacje wykonania'",
|
||||
|
|
|
|||
1
src/package.nls.pt-BR.json
generated
1
src/package.nls.pt-BR.json
generated
|
|
@ -24,7 +24,6 @@
|
|||
"command.openInEditor.title": "Abrir no Editor",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "Configurações",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "Documentação",
|
||||
"configuration.title": "Roo Code",
|
||||
"commands.allowedCommands.description": "Comandos que podem ser executados automaticamente quando 'Sempre aprovar operações de execução' está ativado",
|
||||
|
|
|
|||
1
src/package.nls.ru.json
generated
1
src/package.nls.ru.json
generated
|
|
@ -11,7 +11,6 @@
|
|||
"command.openInEditor.title": "Открыть в редакторе",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "Настройки",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "Документация",
|
||||
"command.openInNewTab.title": "Открыть в новой вкладке",
|
||||
"command.explainCode.title": "Объяснить код",
|
||||
|
|
|
|||
1
src/package.nls.tr.json
generated
1
src/package.nls.tr.json
generated
|
|
@ -24,7 +24,6 @@
|
|||
"command.openInEditor.title": "Düzenleyicide Aç",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "Ayarlar",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "Dokümantasyon",
|
||||
"configuration.title": "Roo Code",
|
||||
"commands.allowedCommands.description": "'Her zaman yürütme işlemlerini onayla' etkinleştirildiğinde otomatik olarak yürütülebilen komutlar",
|
||||
|
|
|
|||
1
src/package.nls.vi.json
generated
1
src/package.nls.vi.json
generated
|
|
@ -24,7 +24,6 @@
|
|||
"command.openInEditor.title": "Mở trong Trình Soạn Thảo",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "Cài Đặt",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "Tài Liệu",
|
||||
"configuration.title": "Roo Code",
|
||||
"commands.allowedCommands.description": "Các lệnh có thể được thực thi tự động khi 'Luôn phê duyệt các thao tác thực thi' được bật",
|
||||
|
|
|
|||
1
src/package.nls.zh-CN.json
generated
1
src/package.nls.zh-CN.json
generated
|
|
@ -24,7 +24,6 @@
|
|||
"command.openInEditor.title": "在编辑器中打开",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "设置",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "文档",
|
||||
"configuration.title": "Roo Code",
|
||||
"commands.allowedCommands.description": "当启用'始终批准执行操作'时可以自动执行的命令",
|
||||
|
|
|
|||
1
src/package.nls.zh-TW.json
generated
1
src/package.nls.zh-TW.json
generated
|
|
@ -24,7 +24,6 @@
|
|||
"command.openInEditor.title": "在編輯器中開啟",
|
||||
"command.cloud.title": "Cloud",
|
||||
"command.settings.title": "設定",
|
||||
"command.worktrees.title": "Worktrees",
|
||||
"command.documentation.title": "文件",
|
||||
"configuration.title": "Roo Code",
|
||||
"commands.allowedCommands.description": "當啟用'始終批准執行操作'時可以自動執行的命令",
|
||||
|
|
|
|||
|
|
@ -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<Record<NonNullable<ExtensionMessage["action"]
|
|||
historyButtonClicked: "history",
|
||||
marketplaceButtonClicked: "marketplace",
|
||||
cloudButtonClicked: "cloud",
|
||||
worktreesButtonClicked: "worktrees",
|
||||
}
|
||||
|
||||
const App = () => {
|
||||
|
|
@ -247,7 +245,6 @@ const App = () => {
|
|||
organizations={cloudOrganizations}
|
||||
/>
|
||||
)}
|
||||
{tab === "worktrees" && <WorktreesView onDone={() => switchTab("chat")} />}
|
||||
<ChatView
|
||||
ref={chatViewRef}
|
||||
isHidden={tab !== "chat"}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ import SystemPromptWarning from "./SystemPromptWarning"
|
|||
import ProfileViolationWarning from "./ProfileViolationWarning"
|
||||
import { CheckpointWarning } from "./CheckpointWarning"
|
||||
import { QueuedMessages } from "./QueuedMessages"
|
||||
import { WorktreeSelector } from "./WorktreeSelector"
|
||||
import DismissibleUpsell from "../common/DismissibleUpsell"
|
||||
import { useCloudUpsell } from "@src/hooks/useCloudUpsell"
|
||||
import { Cloud } from "lucide-react"
|
||||
|
|
@ -95,6 +96,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
|
|||
cloudIsAuthenticated,
|
||||
messageQueue = [],
|
||||
isBrowserSessionActive,
|
||||
showWorktreesInHomeScreen,
|
||||
} = useExtensionState()
|
||||
|
||||
const messagesRef = useRef(messages)
|
||||
|
|
@ -1543,6 +1545,8 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
|
|||
</div>
|
||||
)}
|
||||
|
||||
{!task && showWorktreesInHomeScreen && <WorktreeSelector />}
|
||||
|
||||
{task && (
|
||||
<>
|
||||
<div className="grow flex" ref={scrollContainerRef}>
|
||||
|
|
|
|||
193
webview-ui/src/components/chat/WorktreeSelector.tsx
Normal file
193
webview-ui/src/components/chat/WorktreeSelector.tsx
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
import React, { useState, useCallback, useEffect, useMemo } from "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, 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 {
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
export const WorktreeSelector = ({ disabled = false }: WorktreeSelectorProps) => {
|
||||
const { t } = useAppTranslation()
|
||||
const [open, setOpen] = useState(false)
|
||||
const [worktrees, setWorktrees] = useState<Worktree[]>([])
|
||||
const [isGitRepo, setIsGitRepo] = useState(true)
|
||||
const [showCreateModal, setShowCreateModal] = useState(false)
|
||||
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")
|
||||
|
||||
return (
|
||||
<Popover open={open} onOpenChange={setOpen} data-testid="worktree-selector-root">
|
||||
<StandardTooltip content={title}>
|
||||
<PopoverTrigger
|
||||
disabled={disabled}
|
||||
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 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"
|
||||
: "opacity-90 hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)] cursor-pointer",
|
||||
)}>
|
||||
<span className="font-semibold mr-2">{t("worktrees:selector.worktree")}:</span>
|
||||
<GitBranch className="w-3 h-3" />
|
||||
<span className="truncate">{currentWorktree?.branch || t("worktrees:noBranch")}</span>
|
||||
<ChevronDown className="size-3" />
|
||||
</PopoverTrigger>
|
||||
</StandardTooltip>
|
||||
<PopoverContent
|
||||
align="start"
|
||||
sideOffset={4}
|
||||
container={portalContainer}
|
||||
className="p-0 overflow-hidden min-w-80 max-w-9/10">
|
||||
<div className="flex flex-col w-full">
|
||||
{/* Bottom bar with settings cog and title */}
|
||||
<div className="px-3 pb-4">
|
||||
<div className="flex flex-row items-center justify-between">
|
||||
<h4 className="">{t("worktrees:selector.title")}</h4>
|
||||
<IconButton
|
||||
iconClass="codicon-settings-gear"
|
||||
title={t("worktrees:selector.settings")}
|
||||
onClick={handleSettingsClick}
|
||||
/>
|
||||
</div>
|
||||
<p className="m-0 text-xs text-vscode-descriptionForeground">
|
||||
{t("worktrees:selector.description")}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Worktree list */}
|
||||
<div className="max-h-[300px] overflow-y-auto py-1">
|
||||
{worktrees.map((worktree) => {
|
||||
const isSelected = worktree.isCurrent
|
||||
return (
|
||||
<div
|
||||
key={worktree.path}
|
||||
onClick={() => !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",
|
||||
)}>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2">
|
||||
<GitBranch className="w-3 h-3 shrink-0" />
|
||||
<span className="font-bold truncate">
|
||||
{worktree.branch || t("worktrees:noBranch")}
|
||||
</span>
|
||||
{worktree.isBare && (
|
||||
<span className="text-xs opacity-70">{t("worktrees:primary")}</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-xs text-vscode-descriptionForeground ml-5 truncate">
|
||||
{worktree.path}
|
||||
</div>
|
||||
</div>
|
||||
{isSelected && <Check className="ml-auto size-4 p-0.5" />}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* New worktree button */}
|
||||
<div className="px-3 py-2 border-t border-vscode-panel-border">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="w-full justify-start"
|
||||
onClick={() => {
|
||||
setShowCreateModal(true)
|
||||
setOpen(false)
|
||||
}}>
|
||||
<Plus className="w-3 h-3 mr-2" />
|
||||
{t("worktrees:newWorktree")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
|
||||
{/* Create Worktree Modal */}
|
||||
{showCreateModal && (
|
||||
<CreateWorktreeModal
|
||||
open={showCreateModal}
|
||||
onClose={() => setShowCreateModal(false)}
|
||||
openAfterCreate={true}
|
||||
onSuccess={() => {
|
||||
setShowCreateModal(false)
|
||||
fetchWorktrees()
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,299 @@
|
|||
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<WorktreeListResponse> & { 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(<WorktreeSelector />)
|
||||
|
||||
expect(mockPostMessage).toHaveBeenCalledWith({ type: "listWorktrees" })
|
||||
})
|
||||
|
||||
test("does not render when not a git repo", () => {
|
||||
const { container } = render(<WorktreeSelector />)
|
||||
|
||||
simulateWorktreeListMessage([], false)
|
||||
|
||||
expect(container.querySelector('[data-testid="worktree-selector-trigger"]')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
test("does not render when only one worktree exists", () => {
|
||||
const { container } = render(<WorktreeSelector />)
|
||||
|
||||
simulateWorktreeListMessage([mockWorktrees[0]])
|
||||
|
||||
expect(container.querySelector('[data-testid="worktree-selector-trigger"]')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
test("renders trigger when multiple worktrees exist", () => {
|
||||
render(<WorktreeSelector />)
|
||||
|
||||
simulateWorktreeListMessage(mockWorktrees)
|
||||
|
||||
expect(screen.getByTestId("worktree-selector-trigger")).toBeInTheDocument()
|
||||
})
|
||||
|
||||
test("shows current branch name on trigger", () => {
|
||||
render(<WorktreeSelector />)
|
||||
|
||||
simulateWorktreeListMessage(mockWorktrees)
|
||||
|
||||
const trigger = screen.getByTestId("worktree-selector-trigger")
|
||||
expect(trigger).toHaveTextContent("main")
|
||||
})
|
||||
|
||||
test("opens popover and shows all worktrees when clicked", () => {
|
||||
render(<WorktreeSelector />)
|
||||
|
||||
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(<WorktreeSelector />)
|
||||
|
||||
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(<WorktreeSelector />)
|
||||
|
||||
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(<WorktreeSelector />)
|
||||
|
||||
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(<WorktreeSelector />)
|
||||
|
||||
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(<WorktreeSelector />)
|
||||
|
||||
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(<WorktreeSelector />)
|
||||
|
||||
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 title in header", () => {
|
||||
render(<WorktreeSelector />)
|
||||
|
||||
simulateWorktreeListMessage(mockWorktrees)
|
||||
|
||||
fireEvent.click(screen.getByTestId("worktree-selector-trigger"))
|
||||
|
||||
expect(screen.getByText("worktrees:selector.title")).toBeInTheDocument()
|
||||
})
|
||||
|
||||
test("shows description in popover", () => {
|
||||
render(<WorktreeSelector />)
|
||||
|
||||
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(<WorktreeSelector disabled={true} />)
|
||||
|
||||
simulateWorktreeListMessage(mockWorktrees)
|
||||
|
||||
const trigger = screen.getByTestId("worktree-selector-trigger")
|
||||
expect(trigger).toBeDisabled()
|
||||
})
|
||||
|
||||
test("refreshes worktrees when popover opens", () => {
|
||||
render(<WorktreeSelector />)
|
||||
|
||||
simulateWorktreeListMessage(mockWorktrees)
|
||||
|
||||
mockPostMessage.mockClear()
|
||||
|
||||
fireEvent.click(screen.getByTestId("worktree-selector-trigger"))
|
||||
|
||||
expect(mockPostMessage).toHaveBeenCalledWith({ type: "listWorktrees" })
|
||||
})
|
||||
|
||||
test("shows check mark on current worktree", () => {
|
||||
render(<WorktreeSelector />)
|
||||
|
||||
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(<WorktreeSelector />)
|
||||
|
||||
simulateWorktreeListMessage(worktreesWithDetached)
|
||||
|
||||
fireEvent.click(screen.getByTestId("worktree-selector-trigger"))
|
||||
|
||||
// Should show "worktrees:noBranch" translation key for detached HEAD
|
||||
expect(screen.getByText("worktrees:noBranch")).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
|
@ -28,6 +28,7 @@ import {
|
|||
Server,
|
||||
Users2,
|
||||
ArrowLeft,
|
||||
GitCommitVertical,
|
||||
} from "lucide-react"
|
||||
|
||||
import {
|
||||
|
|
@ -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",
|
||||
|
|
@ -518,11 +521,12 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
|
|||
{ id: "autoApprove", icon: CheckCheck },
|
||||
{ id: "slashCommands", icon: SquareSlash },
|
||||
{ id: "browser", icon: SquareMousePointer },
|
||||
{ id: "checkpoints", icon: GitBranch },
|
||||
{ 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 },
|
||||
|
|
@ -889,6 +893,9 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
|
|||
{/* MCP Section */}
|
||||
{renderTab === "mcp" && <McpView />}
|
||||
|
||||
{/* Worktrees Section */}
|
||||
{renderTab === "worktrees" && <WorktreesView />}
|
||||
|
||||
{/* Prompts Section */}
|
||||
{renderTab === "prompts" && (
|
||||
<PromptsSettings
|
||||
|
|
|
|||
|
|
@ -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) => (
|
||||
<button role="switch" aria-checked={checked} aria-label={ariaLabel} data-testid={dataTestId} onClick={onChange}>
|
||||
Toggle
|
||||
</button>
|
||||
),
|
||||
AlertDialog: ({ open, children }: any) => (open ? <div data-testid="alert-dialog">{children}</div> : null),
|
||||
AlertDialogContent: ({ children }: any) => <div>{children}</div>,
|
||||
AlertDialogTitle: ({ children }: any) => <div data-testid="alert-title">{children}</div>,
|
||||
|
|
|
|||
|
|
@ -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) => (
|
||||
<button role="switch" aria-checked={checked} aria-label={ariaLabel} data-testid={dataTestId} onClick={onChange}>
|
||||
Toggle
|
||||
</button>
|
||||
),
|
||||
Popover: ({ children }: any) => <div data-testid="popover">{children}</div>,
|
||||
PopoverTrigger: ({ children }: any) => <div data-testid="popover-trigger">{children}</div>,
|
||||
PopoverContent: ({ children }: any) => <div data-testid="popover-content">{children}</div>,
|
||||
|
|
|
|||
|
|
@ -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) => (
|
||||
<button role="switch" aria-checked={checked} aria-label={ariaLabel} data-testid={dataTestId} onClick={onChange}>
|
||||
Toggle
|
||||
</button>
|
||||
),
|
||||
AlertDialog: ({ children }: any) => <div>{children}</div>,
|
||||
AlertDialogContent: ({ children }: any) => <div>{children}</div>,
|
||||
AlertDialogTitle: ({ children }: any) => <div>{children}</div>,
|
||||
|
|
|
|||
|
|
@ -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" })
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { cva, type VariantProps } from "class-variance-authority"
|
|||
import { cn } from "@/lib/utils"
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-full text-base font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 cursor-pointer active:opacity-80",
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-full text-base font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-30 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 cursor-pointer active:opacity-80",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
|
|
|
|||
|
|
@ -40,12 +40,12 @@ function DialogContent({ className, children, ...props }: React.ComponentProps<t
|
|||
<DialogPrimitive.Content
|
||||
data-slot="dialog-content"
|
||||
className={cn(
|
||||
"bg-vscode-editor-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
|
||||
"bg-vscode-editor-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-2xl border p-6 shadow-lg duration-200 sm:max-w-lg",
|
||||
className,
|
||||
)}
|
||||
{...props}>
|
||||
{children}
|
||||
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4">
|
||||
<DialogPrimitive.Close className="ring-offset-background cursor-pointer focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4">
|
||||
<XIcon />
|
||||
<span className="sr-only">Close</span>
|
||||
</DialogPrimitive.Close>
|
||||
|
|
@ -68,7 +68,7 @@ function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|||
return (
|
||||
<div
|
||||
data-slot="dialog-footer"
|
||||
className={cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)}
|
||||
className={cn("flex justify-end gap-2 sm:flex-row sm:justify-end", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
|
|||
<input
|
||||
type={type}
|
||||
className={cn(
|
||||
"flex w-full text-vscode-input-foreground border border-vscode-dropdown-border bg-vscode-input-background rounded-xs px-3 py-1 text-base transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus:outline-0 focus-visible:outline-none focus-visible:border-vscode-focusBorder disabled:cursor-not-allowed disabled:opacity-50",
|
||||
"flex w-full text-vscode-input-foreground border border-vscode-dropdown-border bg-vscode-input-background rounded-xs px-3 py-1 text-base transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-vscode-focusBorder disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export const ToggleSwitch: React.FC<ToggleSwitchProps> = ({
|
|||
"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<ToggleSwitchProps> = ({
|
|||
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<ToggleSwitchProps> = ({
|
|||
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`,
|
||||
|
|
|
|||
|
|
@ -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 = ({
|
|||
<DialogContent className="max-w-lg">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{t("worktrees:createWorktree")}</DialogTitle>
|
||||
<DialogDescription>{t("worktrees:createWorktreeDescription")}</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="flex flex-col gap-3">
|
||||
{/* No .worktreeinclude warning - shows when the current worktree doesn't have .worktreeinclude */}
|
||||
{includeStatus?.exists === false && (
|
||||
<div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-vscode-inputValidation-warningBackground border border-vscode-inputValidation-warningBorder text-sm">
|
||||
<span className="codicon codicon-warning text-vscode-charts-yellow flex-shrink-0" />
|
||||
<Info />
|
||||
<span className="text-vscode-foreground">
|
||||
<span className="font-medium">{t("worktrees:noIncludeFileWarning")}</span>
|
||||
{" — "}
|
||||
|
|
@ -170,17 +167,6 @@ export const CreateWorktreeModal = ({
|
|||
</div>
|
||||
)}
|
||||
|
||||
{/* Branch name */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<label className="text-sm text-vscode-foreground">{t("worktrees:branchName")}</label>
|
||||
<Input
|
||||
value={branchName}
|
||||
onChange={(e) => setBranchName(e.target.value)}
|
||||
placeholder={defaults?.suggestedBranch || "worktree/feature-name"}
|
||||
className="rounded-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Base branch selector */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<label className="text-sm text-vscode-foreground">{t("worktrees:baseBranch")}</label>
|
||||
|
|
@ -201,16 +187,32 @@ export const CreateWorktreeModal = ({
|
|||
)}
|
||||
</div>
|
||||
|
||||
{/* Branch name */}
|
||||
<div className="flex items-center gap-2">
|
||||
<CornerDownRight className="size-4 ml-2 shrink-0" />
|
||||
<label className="text-sm text-vscode-foreground shrink-0">{t("worktrees:branchName")}</label>
|
||||
<Input
|
||||
value={branchName}
|
||||
onChange={(e) => setBranchName(e.target.value)}
|
||||
placeholder={defaults?.suggestedBranch || "worktree/feature-name"}
|
||||
className="rounded-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Worktree path */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<label className="text-sm text-vscode-foreground">{t("worktrees:worktreePath")}</label>
|
||||
<div className="flex items-center gap-2 relative">
|
||||
<Folder className="size-4 ml-2 shrink-0" />
|
||||
<label className="text-sm text-vscode-foreground shrink-0">{t("worktrees:worktreePath")}</label>
|
||||
<Input
|
||||
value={worktreePath}
|
||||
onChange={(e) => setWorktreePath(e.target.value)}
|
||||
placeholder={defaults?.suggestedPath || "/path/to/worktree"}
|
||||
className="rounded-full"
|
||||
className="rounded-full flex-1 pr-9"
|
||||
/>
|
||||
<FolderSearch
|
||||
className="size-4 shrink-0 absolute right-3 cursor-pointer hover:opacity-75 transition-opacity"
|
||||
onClick={() => vscode.postMessage({ type: "browseForWorktreePath" })}
|
||||
/>
|
||||
<p className="text-xs text-vscode-descriptionForeground">{t("worktrees:pathHint")}</p>
|
||||
</div>
|
||||
|
||||
{/* Error message */}
|
||||
|
|
@ -244,7 +246,7 @@ export const CreateWorktreeModal = ({
|
|||
<Button variant="secondary" onClick={onClose} disabled={isCreating}>
|
||||
{t("worktrees:cancel")}
|
||||
</Button>
|
||||
<Button onClick={handleCreate} disabled={!isValid || isCreating}>
|
||||
<Button variant="primary" onClick={handleCreate} disabled={!isValid || isCreating}>
|
||||
{isCreating ? (
|
||||
<>
|
||||
<span className="codicon codicon-loading codicon-modifier-spin mr-2" />
|
||||
|
|
|
|||
|
|
@ -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,35 +55,38 @@ export const DeleteWorktreeModal = ({ open, onClose, worktree, onSuccess }: Dele
|
|||
<Dialog open={open} onOpenChange={(isOpen: boolean) => !isOpen && onClose()}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="codicon codicon-warning text-vscode-charts-yellow text-xl" />
|
||||
<DialogTitle>{t("worktrees:deleteWorktree")}</DialogTitle>
|
||||
</div>
|
||||
<DialogDescription>{t("worktrees:deleteWorktreeDescription")}</DialogDescription>
|
||||
<DialogTitle>{t("worktrees:deleteWorktree")}</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="flex flex-col gap-3 overflow-hidden">
|
||||
{/* Worktree info */}
|
||||
<div className="px-2 py-1.5 rounded bg-vscode-input-background border border-vscode-input-border">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="codicon codicon-git-branch flex-shrink-0" />
|
||||
<span className="font-medium text-vscode-foreground truncate">
|
||||
<div className="flex flex-col p-5 gap-2 cursor-default rounded-xl text-vscode-foreground bg-vscode-input-background">
|
||||
<p className="flex items-center gap-2 m-0">
|
||||
<GitBranch className="size-4 shrink-0" />
|
||||
<span className="font-medium truncate">
|
||||
{worktree.branch ||
|
||||
(worktree.isDetached ? t("worktrees:detachedHead") : t("worktrees:noBranch"))}
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-xs text-vscode-descriptionForeground mt-0.5 truncate">{worktree.path}</div>
|
||||
</p>
|
||||
|
||||
<p className="flex items-start gap-2 m-0">
|
||||
<Folder className="size-4 shrink-0" />
|
||||
<span className="m-0 text-sm font-mono font-medium text-vscode-descriptionForeground">
|
||||
{worktree.path}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Warning message */}
|
||||
<div className="flex items-start gap-2 p-2 rounded bg-vscode-inputValidation-warningBackground border border-vscode-inputValidation-warningBorder text-sm">
|
||||
<span className="codicon codicon-warning text-vscode-charts-yellow flex-shrink-0 mt-0.5" />
|
||||
<div className="min-w-0">
|
||||
<p className="text-vscode-foreground m-0">{t("worktrees:deleteWarning")}</p>
|
||||
<ul className="mt-1 mb-0 pl-0 list-none space-y-0.5 text-vscode-descriptionForeground">
|
||||
<li>• {t("worktrees:deleteWarningBranch", { branch: worktree.branch || "HEAD" })}</li>
|
||||
<div className="flex items-start gap-2 px-5 py-2">
|
||||
<TriangleAlert className="size-4 text-vscode-charts-yellow flex-shrink-0" />
|
||||
<div className="flex flex-col min-w-0 gap-2">
|
||||
<p className="m-0 text-vscode-foreground">{t("worktrees:deleteWarning")}</p>
|
||||
<ul className="m-0 pl-0 list-none space-y-1 text-vscode-descriptionForeground">
|
||||
<li>• {t("worktrees:deleteWarningBranch")}</li>
|
||||
<li>• {t("worktrees:deleteWarningFiles")}</li>
|
||||
</ul>
|
||||
<p className="m-0 text-vscode-descriptionForeground">{t("worktrees:deleteNoticeLarge")}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,21 +2,20 @@ import { useState, useEffect, useCallback } from "react"
|
|||
|
||||
import type { Worktree, WorktreeListResponse, WorktreeIncludeStatus } from "@roo-code/types"
|
||||
|
||||
import { Badge, Button, StandardTooltip } from "@/components/ui"
|
||||
import { Badge, Button, StandardTooltip, ToggleSwitch } from "@/components/ui"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
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 { Folder, GitBranch, Lock, Plus, SquareArrowOutUpRight, Trash } from "lucide-react"
|
||||
|
||||
type WorktreesViewProps = {
|
||||
onDone: () => void
|
||||
}
|
||||
|
||||
export const WorktreesView = ({ onDone }: WorktreesViewProps) => {
|
||||
export const WorktreesView = () => {
|
||||
const { t } = useAppTranslation()
|
||||
const { showWorktreesInHomeScreen, setShowWorktreesInHomeScreen } = useExtensionState()
|
||||
|
||||
// State
|
||||
const [worktrees, setWorktrees] = useState<Worktree[]>([])
|
||||
|
|
@ -123,87 +122,178 @@ export const WorktreesView = ({ onDone }: WorktreesViewProps) => {
|
|||
})
|
||||
}, [])
|
||||
|
||||
// Handle toggle show in home screen
|
||||
const handleToggleShowInHomeScreen = useCallback(() => {
|
||||
const newValue = !showWorktreesInHomeScreen
|
||||
setShowWorktreesInHomeScreen(newValue)
|
||||
vscode.postMessage({
|
||||
type: "updateSettings",
|
||||
updatedSettings: { showWorktreesInHomeScreen: newValue },
|
||||
})
|
||||
}, [showWorktreesInHomeScreen, setShowWorktreesInHomeScreen])
|
||||
|
||||
// Render error states
|
||||
if (!isGitRepo) {
|
||||
return (
|
||||
<Tab>
|
||||
<TabHeader className="flex justify-between items-center">
|
||||
<h3 className="text-vscode-foreground m-0">{t("worktrees:title")}</h3>
|
||||
<Button onClick={onDone}>{t("worktrees:done")}</Button>
|
||||
</TabHeader>
|
||||
<TabContent>
|
||||
<div className="flex flex-col items-center justify-center h-48 text-vscode-descriptionForeground">
|
||||
<span className="codicon codicon-warning text-4xl mb-4" />
|
||||
<p className="text-center">{t("worktrees:notGitRepo")}</p>
|
||||
</div>
|
||||
</TabContent>
|
||||
</Tab>
|
||||
<div>
|
||||
<SectionHeader>{t("worktrees:title")}</SectionHeader>
|
||||
<div className="px-5 text-sm">
|
||||
<p className="text-vscode-descriptionForeground">{t("worktrees:description")}</p>
|
||||
<p>{t("worktrees:notGitRepo")}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (isMultiRoot) {
|
||||
return (
|
||||
<Tab>
|
||||
<TabHeader className="flex justify-between items-center">
|
||||
<h3 className="text-vscode-foreground m-0">{t("worktrees:title")}</h3>
|
||||
<Button onClick={onDone}>{t("worktrees:done")}</Button>
|
||||
</TabHeader>
|
||||
<TabContent>
|
||||
<div className="flex flex-col items-center justify-center h-48 text-vscode-descriptionForeground">
|
||||
<span className="codicon codicon-warning text-4xl mb-4" />
|
||||
<p className="text-center">{t("worktrees:multiRootNotSupported")}</p>
|
||||
</div>
|
||||
</TabContent>
|
||||
</Tab>
|
||||
<div>
|
||||
<SectionHeader>{t("worktrees:title")}</SectionHeader>
|
||||
<div className="px-5 text-sm">
|
||||
<p className="text-vscode-descriptionForeground">{t("worktrees:description")}</p>
|
||||
<p>{t("worktrees:multiRootNotSupported")}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (isSubfolder) {
|
||||
return (
|
||||
<Tab>
|
||||
<TabHeader className="flex justify-between items-center">
|
||||
<h3 className="text-vscode-foreground m-0">{t("worktrees:title")}</h3>
|
||||
<Button onClick={onDone}>{t("worktrees:done")}</Button>
|
||||
</TabHeader>
|
||||
<TabContent>
|
||||
<div className="flex flex-col items-center justify-center h-48 text-vscode-descriptionForeground">
|
||||
<span className="codicon codicon-warning text-4xl mb-4" />
|
||||
<p className="text-center">{t("worktrees:subfolderNotSupported")}</p>
|
||||
<p className="text-sm mt-2 text-center">
|
||||
{t("worktrees:gitRoot")}:{" "}
|
||||
<code className="bg-vscode-input-background px-2 py-1 rounded">{gitRootPath}</code>
|
||||
</p>
|
||||
</div>
|
||||
</TabContent>
|
||||
</Tab>
|
||||
<div>
|
||||
<SectionHeader>{t("worktrees:title")}</SectionHeader>
|
||||
<div className="px-5 text-sm">
|
||||
<p className="text-vscode-descriptionForeground">{t("worktrees:description")}</p>
|
||||
<p>{t("worktrees:subfolderNotSupported")}</p>
|
||||
<p>
|
||||
{t("worktrees:gitRoot")}:{" "}
|
||||
<code className="bg-vscode-input-background p-1 rounded-md">{gitRootPath}</code>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Tab>
|
||||
<TabHeader className="flex flex-col gap-2">
|
||||
<div className="flex justify-between items-center">
|
||||
<h3 className="text-vscode-foreground m-0">{t("worktrees:title")}</h3>
|
||||
<Button onClick={onDone}>{t("worktrees:done")}</Button>
|
||||
</div>
|
||||
<p className="text-vscode-descriptionForeground text-sm m-0">{t("worktrees:description")}</p>
|
||||
<div className="flex flex-col h-full overflow-hidden">
|
||||
{/* Fixed Header */}
|
||||
<div className="flex-shrink-0">
|
||||
<SectionHeader>{t("worktrees:title")}</SectionHeader>
|
||||
<div className="flex flex-col gap-2 px-5 py-2">
|
||||
<p className="text-vscode-descriptionForeground text-sm m-0">{t("worktrees:description")}</p>
|
||||
|
||||
{/* Show in Home Screen toggle */}
|
||||
<label
|
||||
className="flex cursor-pointer items-center gap-2 text-sm text-vscode-descriptionForeground"
|
||||
onClick={handleToggleShowInHomeScreen}>
|
||||
<ToggleSwitch checked={showWorktreesInHomeScreen} onChange={handleToggleShowInHomeScreen} />
|
||||
<span>{t("worktrees:showInHomeScreen")}</span>
|
||||
</label>
|
||||
|
||||
{/* New Worktree button */}
|
||||
<Button variant="secondary" className="py-1" onClick={() => setShowCreateModal(true)}>
|
||||
<Plus />
|
||||
{t("worktrees:newWorktree")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Scrollable List Area */}
|
||||
<div className="flex-1 overflow-y-auto px-4 py-2 min-h-0">
|
||||
{isLoading ? (
|
||||
<div className="flex items-center justify-center h-48">
|
||||
<span className="codicon codicon-loading codicon-modifier-spin text-2xl" />
|
||||
</div>
|
||||
) : error ? (
|
||||
<div className="flex flex-col items-center justify-center h-48 text-vscode-errorForeground">
|
||||
<span className="codicon codicon-error text-4xl mb-4" />
|
||||
<p className="text-center">{error}</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col gap-1">
|
||||
{worktrees.map((worktree) => (
|
||||
<div
|
||||
key={worktree.path}
|
||||
className={`p-2.5 px-3.5 rounded-xl hover:bg-vscode-list-hoverBackground border border-transparent ${
|
||||
worktree.isCurrent
|
||||
? " bg-vscode-list-activeSelectionBackground border-vscode-list-activeSelectionForeground/20"
|
||||
: "cursor-pointer"
|
||||
}`}
|
||||
onClick={
|
||||
worktree.isCurrent ? undefined : () => handleSwitchWorktree(worktree.path, false)
|
||||
}>
|
||||
<div className="flex items-start min-[400px]:items-center justify-between gap-2 flex-col min-[400px]:flex-row overflow-hidden">
|
||||
<div className={`flex-1 min-w-0 ${worktree.isCurrent && "cursor-default"}`}>
|
||||
{/* Info */}
|
||||
<div className="flex items-center gap-2 overflow-hidden">
|
||||
<GitBranch className="size-3 shrink-0" />
|
||||
<span className="font-medium truncate">
|
||||
{worktree.branch ||
|
||||
(worktree.isDetached
|
||||
? t("worktrees:detachedHead")
|
||||
: t("worktrees:noBranch"))}
|
||||
</span>
|
||||
{worktree.isBare && (
|
||||
<Badge className="text-[0.7em] -mt-0.25 py-0.5">
|
||||
{t("worktrees:primary")}
|
||||
</Badge>
|
||||
)}
|
||||
{worktree.isLocked && (
|
||||
<StandardTooltip content={worktree.lockReason || t("worktrees:locked")}>
|
||||
<Lock className="text-vscode-charts-yellow" />
|
||||
</StandardTooltip>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex gap-2 text-xs text-vscode-descriptionForeground mt-1">
|
||||
<Folder className="size-3 shrink-0 mt-0.5" />
|
||||
<span className="truncate">{worktree.path}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Actions */}
|
||||
<div className="flex items-center gap-1 ml-3 min-[400px]:ml-0 flex-shrink-0">
|
||||
<StandardTooltip content={t("worktrees:openInNewWindow")}>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
disabled={worktree.isCurrent}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleSwitchWorktree(worktree.path, true)
|
||||
}}>
|
||||
<SquareArrowOutUpRight />
|
||||
</Button>
|
||||
</StandardTooltip>
|
||||
|
||||
<StandardTooltip content={t("worktrees:delete")}>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
disabled={worktree.isCurrent || worktree.isBare}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setDeleteWorktree(worktree)
|
||||
}}>
|
||||
<Trash className="text-destructive" />
|
||||
</Button>
|
||||
</StandardTooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Fixed Footer - Settings */}
|
||||
<div className="flex-shrink-0 flex flex-col border-t border-vscode-sideBar-background">
|
||||
{/* Worktree include status */}
|
||||
{includeStatus && (
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<div className="flex items-center gap-2 text-sm px-5 py-3 justify-between text-vscode-descriptionForeground border-t border-vscode-sideBar-background">
|
||||
{includeStatus.exists ? (
|
||||
<>
|
||||
<span className="codicon codicon-check text-vscode-charts-green" />
|
||||
<span className="text-vscode-descriptionForeground">
|
||||
{t("worktrees:includeFileExists")}
|
||||
</span>
|
||||
</>
|
||||
<span>{t("worktrees:includeFileExists")}</span>
|
||||
) : (
|
||||
<>
|
||||
<span className="codicon codicon-warning text-vscode-charts-yellow" />
|
||||
<span className="text-vscode-descriptionForeground">
|
||||
{t("worktrees:noIncludeFile")}
|
||||
</span>
|
||||
<span>{t("worktrees:noIncludeFile")}</span>
|
||||
{includeStatus.hasGitignore && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
|
|
@ -217,97 +307,7 @@ export const WorktreesView = ({ onDone }: WorktreesViewProps) => {
|
|||
)}
|
||||
</div>
|
||||
)}
|
||||
</TabHeader>
|
||||
|
||||
<TabContent className="px-2 py-0">
|
||||
{isLoading ? (
|
||||
<div className="flex items-center justify-center h-48">
|
||||
<span className="codicon codicon-loading codicon-modifier-spin text-2xl" />
|
||||
</div>
|
||||
) : error ? (
|
||||
<div className="flex flex-col items-center justify-center h-48 text-vscode-errorForeground">
|
||||
<span className="codicon codicon-error text-4xl mb-4" />
|
||||
<p className="text-center">{error}</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col gap-1 py-2">
|
||||
{worktrees.map((worktree) => (
|
||||
<div
|
||||
key={worktree.path}
|
||||
className={`p-3 rounded-xl border transition-colors ${
|
||||
worktree.isCurrent
|
||||
? "border-vscode-focusBorder bg-vscode-list-activeSelectionBackground"
|
||||
: "border-transparent bg-vscode-editor-background hover:bg-vscode-editor-foreground/10"
|
||||
}`}>
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<span className="codicon codicon-git-branch" />
|
||||
<span className="font-medium truncate">
|
||||
{worktree.branch ||
|
||||
(worktree.isDetached
|
||||
? t("worktrees:detachedHead")
|
||||
: t("worktrees:noBranch"))}
|
||||
</span>
|
||||
{worktree.isBare && <Badge>{t("worktrees:primary")}</Badge>}
|
||||
{worktree.isCurrent && (
|
||||
<Badge variant="secondary">{t("worktrees:current")}</Badge>
|
||||
)}
|
||||
{worktree.isLocked && (
|
||||
<StandardTooltip content={worktree.lockReason || t("worktrees:locked")}>
|
||||
<span className="codicon codicon-lock text-vscode-charts-yellow" />
|
||||
</StandardTooltip>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-xs text-vscode-descriptionForeground mt-1 truncate">
|
||||
{worktree.path}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-1 ml-2 flex-shrink-0">
|
||||
{!worktree.isCurrent && (
|
||||
<>
|
||||
<StandardTooltip content={t("worktrees:openInCurrentWindow")}>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => handleSwitchWorktree(worktree.path, false)}>
|
||||
<span className="codicon codicon-window" />
|
||||
</Button>
|
||||
</StandardTooltip>
|
||||
<StandardTooltip content={t("worktrees:openInNewWindow")}>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => handleSwitchWorktree(worktree.path, true)}>
|
||||
<span className="codicon codicon-empty-window" />
|
||||
</Button>
|
||||
</StandardTooltip>
|
||||
</>
|
||||
)}
|
||||
{!worktree.isBare && !worktree.isCurrent && (
|
||||
<StandardTooltip content={t("worktrees:delete")}>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setDeleteWorktree(worktree)}>
|
||||
<span className="codicon codicon-trash text-vscode-errorForeground" />
|
||||
</Button>
|
||||
</StandardTooltip>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{/* New Worktree button */}
|
||||
<Button variant="secondary" className="mt-2" onClick={() => setShowCreateModal(true)}>
|
||||
<span className="codicon codicon-add mr-2" />
|
||||
{t("worktrees:newWorktree")}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</TabContent>
|
||||
</div>
|
||||
|
||||
{/* Create Modal */}
|
||||
{showCreateModal && (
|
||||
|
|
@ -333,6 +333,6 @@ export const WorktreesView = ({ onDone }: WorktreesViewProps) => {
|
|||
}}
|
||||
/>
|
||||
)}
|
||||
</Tab>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
export { WorktreesView } from "./WorktreesView"
|
||||
export { CreateWorktreeModal } from "./CreateWorktreeModal"
|
||||
export { DeleteWorktreeModal } from "./DeleteWorktreeModal"
|
||||
|
|
@ -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<ExtensionStateContextType | undefined>(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 <ExtensionStateContext.Provider value={contextValue}>{children}</ExtensionStateContext.Provider>
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/ca/settings.json
generated
1
webview-ui/src/i18n/locales/ca/settings.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
25
webview-ui/src/i18n/locales/ca/worktrees.json
generated
25
webview-ui/src/i18n/locales/ca/worktrees.json
generated
|
|
@ -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,13 +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"
|
||||
"close": "Tanca",
|
||||
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/de/settings.json
generated
1
webview-ui/src/i18n/locales/de/settings.json
generated
|
|
@ -29,6 +29,7 @@
|
|||
"providers": "Anbieter",
|
||||
"modes": "Modi",
|
||||
"mcp": "MCP-Server",
|
||||
"worktrees": "Worktrees",
|
||||
"autoApprove": "Auto-Genehmigung",
|
||||
"browser": "Computerzugriff",
|
||||
"checkpoints": "Kontrollpunkte",
|
||||
|
|
|
|||
25
webview-ui/src/i18n/locales/de/worktrees.json
generated
25
webview-ui/src/i18n/locales/de/worktrees.json
generated
|
|
@ -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,13 +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"
|
||||
"close": "Schließen",
|
||||
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
"providers": "Providers",
|
||||
"modes": "Modes",
|
||||
"mcp": "MCP Servers",
|
||||
"worktrees": "Worktrees",
|
||||
"autoApprove": "Auto-Approve",
|
||||
"browser": "Browser",
|
||||
"checkpoints": "Checkpoints",
|
||||
|
|
|
|||
|
|
@ -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.",
|
||||
"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",
|
||||
|
||||
"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,27 +18,27 @@
|
|||
"detachedHead": "Detached HEAD",
|
||||
"noBranch": "No branch",
|
||||
|
||||
"openInCurrentWindow": "Open in current window",
|
||||
"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...",
|
||||
|
|
@ -46,13 +46,24 @@
|
|||
"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",
|
||||
"deleteNoticeLarge": "If this is a large repository, it may take a little while.",
|
||||
"forceDelete": "Force delete",
|
||||
"worktreeIsLocked": "worktree is locked",
|
||||
"deleting": "Deleting...",
|
||||
|
||||
"close": "Close"
|
||||
"close": "Close",
|
||||
|
||||
"showInHomeScreen": "Show worktrees in home screen",
|
||||
|
||||
"selector": {
|
||||
"worktree": "Worktree",
|
||||
"title": "Worktrees",
|
||||
"tooltip": "Switch between worktrees",
|
||||
"description": "Git worktrees let you work on multiple branches simultaneously. Click to switch workspace.",
|
||||
"settings": "Manage Worktrees",
|
||||
"info": "Git worktrees allow you to have multiple working directories attached to the same repository."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/es/settings.json
generated
1
webview-ui/src/i18n/locales/es/settings.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
25
webview-ui/src/i18n/locales/es/worktrees.json
generated
25
webview-ui/src/i18n/locales/es/worktrees.json
generated
|
|
@ -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,13 +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"
|
||||
"close": "Cerrar",
|
||||
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/fr/settings.json
generated
1
webview-ui/src/i18n/locales/fr/settings.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
25
webview-ui/src/i18n/locales/fr/worktrees.json
generated
25
webview-ui/src/i18n/locales/fr/worktrees.json
generated
|
|
@ -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,13 +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"
|
||||
"close": "Fermer",
|
||||
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/hi/settings.json
generated
1
webview-ui/src/i18n/locales/hi/settings.json
generated
|
|
@ -29,6 +29,7 @@
|
|||
"providers": "प्रदाता",
|
||||
"modes": "मोड",
|
||||
"mcp": "एमसीपी सर्वर",
|
||||
"worktrees": "Worktrees",
|
||||
"autoApprove": "अनुमोदन",
|
||||
"browser": "ब्राउज़र",
|
||||
"checkpoints": "चेकपॉइंट",
|
||||
|
|
|
|||
25
webview-ui/src/i18n/locales/hi/worktrees.json
generated
25
webview-ui/src/i18n/locales/hi/worktrees.json
generated
|
|
@ -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,13 +46,24 @@
|
|||
"cancel": "रद्द करें",
|
||||
|
||||
"deleteWorktree": "Worktree हटाएँ",
|
||||
"deleteWorktreeDescription": "यह worktree और उसकी सभी फ़ाइलें हटा देगा।",
|
||||
"deleteWarning": "यह कार्रवाई वापस नहीं ली जा सकती। निम्नलिखित हटाया जाएगा:",
|
||||
"deleteWarningBranch": "ब्रांच '{{branch}}' और सभी uncommitted बदलाव",
|
||||
"deleteWarningBranch": "ब्रांच और सभी uncommitted बदलाव",
|
||||
"deleteWarningFiles": "worktree डायरेक्टरी की सभी फ़ाइलें",
|
||||
"deleteNoticeLarge": "अगर यह एक बड़ी रिपोज़िटरी है तो यह कुछ समय ले सकता है।",
|
||||
"forceDelete": "जबरन हटाएँ",
|
||||
"worktreeIsLocked": "worktree लॉक्ड है",
|
||||
"deleting": "हटाया जा रहा है...",
|
||||
|
||||
"close": "बंद करें"
|
||||
"close": "बंद करें",
|
||||
|
||||
"showInHomeScreen": "होम स्क्रीन में worktrees दिखाएँ",
|
||||
|
||||
"selector": {
|
||||
"worktree": "Worktree",
|
||||
"title": "Worktrees",
|
||||
"tooltip": "Worktrees के बीच स्विच करें",
|
||||
"description": "Git worktrees आपको एक साथ कई ब्रांच पर काम करने देते हैं। workspace स्विच करने के लिए क्लिक करें।",
|
||||
"settings": "Worktrees को प्रबंधित करें",
|
||||
"info": "Git worktrees आपको एक ही रिपोज़िटरी से जुड़ी कई working directories रखने देते हैं।"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/id/settings.json
generated
1
webview-ui/src/i18n/locales/id/settings.json
generated
|
|
@ -29,6 +29,7 @@
|
|||
"providers": "Provider",
|
||||
"modes": "Mode",
|
||||
"mcp": "Server MCP",
|
||||
"worktrees": "Worktrees",
|
||||
"autoApprove": "Auto-Approve",
|
||||
"browser": "Browser",
|
||||
"checkpoints": "Checkpoint",
|
||||
|
|
|
|||
25
webview-ui/src/i18n/locales/id/worktrees.json
generated
25
webview-ui/src/i18n/locales/id/worktrees.json
generated
|
|
@ -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,13 +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"
|
||||
"close": "Tutup",
|
||||
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/it/settings.json
generated
1
webview-ui/src/i18n/locales/it/settings.json
generated
|
|
@ -29,6 +29,7 @@
|
|||
"providers": "Fornitori",
|
||||
"modes": "Modalità",
|
||||
"mcp": "Server MCP",
|
||||
"worktrees": "Worktrees",
|
||||
"autoApprove": "Auto-approvazione",
|
||||
"browser": "Accesso computer",
|
||||
"checkpoints": "Punti di controllo",
|
||||
|
|
|
|||
25
webview-ui/src/i18n/locales/it/worktrees.json
generated
25
webview-ui/src/i18n/locales/it/worktrees.json
generated
|
|
@ -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,13 +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"
|
||||
"close": "Chiudi",
|
||||
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/ja/settings.json
generated
1
webview-ui/src/i18n/locales/ja/settings.json
generated
|
|
@ -29,6 +29,7 @@
|
|||
"providers": "プロバイダー",
|
||||
"modes": "モード",
|
||||
"mcp": "MCPサーバー",
|
||||
"worktrees": "Worktrees",
|
||||
"autoApprove": "自動承認",
|
||||
"browser": "コンピューターアクセス",
|
||||
"checkpoints": "チェックポイント",
|
||||
|
|
|
|||
25
webview-ui/src/i18n/locales/ja/worktrees.json
generated
25
webview-ui/src/i18n/locales/ja/worktrees.json
generated
|
|
@ -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,13 +46,24 @@
|
|||
"cancel": "キャンセル",
|
||||
|
||||
"deleteWorktree": "Worktree を削除",
|
||||
"deleteWorktreeDescription": "これにより worktree とそのファイルがすべて削除されます。",
|
||||
"deleteWarning": "この操作は元に戻せません。次のものが削除されます:",
|
||||
"deleteWarningBranch": "ブランチ '{{branch}}' と未コミットの変更すべて",
|
||||
"deleteWarningBranch": "ブランチと未コミットの変更すべて",
|
||||
"deleteWarningFiles": "worktree ディレクトリ内のすべてのファイル",
|
||||
"deleteNoticeLarge": "大規模なリポジトリの場合、少し時間がかかる場合があります。",
|
||||
"forceDelete": "強制削除",
|
||||
"worktreeIsLocked": "worktree がロックされています",
|
||||
"deleting": "削除中...",
|
||||
|
||||
"close": "閉じる"
|
||||
"close": "閉じる",
|
||||
|
||||
"showInHomeScreen": "ホーム画面に worktrees を表示",
|
||||
|
||||
"selector": {
|
||||
"worktree": "Worktree",
|
||||
"title": "Worktrees",
|
||||
"tooltip": "Worktree を切り替え",
|
||||
"description": "Git worktrees を使うと、複数のブランチで同時に作業できます。クリックしてワークスペースを切り替えます。",
|
||||
"settings": "Worktrees を管理",
|
||||
"info": "Git worktrees を使うと、同じリポジトリに複数の作業ディレクトリを附属できます。"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/ko/settings.json
generated
1
webview-ui/src/i18n/locales/ko/settings.json
generated
|
|
@ -29,6 +29,7 @@
|
|||
"providers": "공급자",
|
||||
"modes": "모드",
|
||||
"mcp": "MCP 서버",
|
||||
"worktrees": "Worktrees",
|
||||
"autoApprove": "자동 승인",
|
||||
"browser": "컴퓨터 접근",
|
||||
"checkpoints": "체크포인트",
|
||||
|
|
|
|||
25
webview-ui/src/i18n/locales/ko/worktrees.json
generated
25
webview-ui/src/i18n/locales/ko/worktrees.json
generated
|
|
@ -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,13 +46,24 @@
|
|||
"cancel": "취소",
|
||||
|
||||
"deleteWorktree": "Worktree 삭제",
|
||||
"deleteWorktreeDescription": "이 작업은 worktree와 그 안의 모든 파일을 제거합니다.",
|
||||
"deleteWarning": "이 작업은 되돌릴 수 없습니다. 다음이 삭제됩니다:",
|
||||
"deleteWarningBranch": "브랜치 '{{branch}}' 및 커밋되지 않은 모든 변경 사항",
|
||||
"deleteWarningBranch": "브랜치 및 커밋되지 않은 모든 변경 사항",
|
||||
"deleteWarningFiles": "worktree 디렉터리의 모든 파일",
|
||||
"deleteNoticeLarge": "대규모 저장소의 경우 시간이 조금 걸릴 수 있습니다.",
|
||||
"forceDelete": "강제 삭제",
|
||||
"worktreeIsLocked": "worktree가 잠겨 있습니다",
|
||||
"deleting": "삭제 중...",
|
||||
|
||||
"close": "닫기"
|
||||
"close": "닫기",
|
||||
|
||||
"showInHomeScreen": "홈 화면에 worktrees 표시",
|
||||
|
||||
"selector": {
|
||||
"worktree": "Worktree",
|
||||
"title": "Worktrees",
|
||||
"tooltip": "Worktree 간 전환",
|
||||
"description": "Git worktree를 사용하면 동시에 여러 브랜치에서 작업할 수 있습니다. 클릭하여 워크스페이스를 전환합니다.",
|
||||
"settings": "Worktree 관리",
|
||||
"info": "Git worktree를 사용하면 동일한 저장소에 여러 작업 디렉터리를 연결할 수 있습니다."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/nl/settings.json
generated
1
webview-ui/src/i18n/locales/nl/settings.json
generated
|
|
@ -29,6 +29,7 @@
|
|||
"providers": "Providers",
|
||||
"modes": "Modi",
|
||||
"mcp": "MCP-servers",
|
||||
"worktrees": "Worktrees",
|
||||
"autoApprove": "Auto-goedkeuren",
|
||||
"browser": "Browser",
|
||||
"checkpoints": "Checkpoints",
|
||||
|
|
|
|||
25
webview-ui/src/i18n/locales/nl/worktrees.json
generated
25
webview-ui/src/i18n/locales/nl/worktrees.json
generated
|
|
@ -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,13 +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"
|
||||
"close": "Sluiten",
|
||||
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/pl/settings.json
generated
1
webview-ui/src/i18n/locales/pl/settings.json
generated
|
|
@ -29,6 +29,7 @@
|
|||
"providers": "Dostawcy",
|
||||
"modes": "Tryby",
|
||||
"mcp": "Serwery MCP",
|
||||
"worktrees": "Worktrees",
|
||||
"autoApprove": "Auto-zatwierdzanie",
|
||||
"browser": "Dostęp komputera",
|
||||
"checkpoints": "Punkty kontrolne",
|
||||
|
|
|
|||
25
webview-ui/src/i18n/locales/pl/worktrees.json
generated
25
webview-ui/src/i18n/locales/pl/worktrees.json
generated
|
|
@ -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,13 +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"
|
||||
"close": "Zamknij",
|
||||
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/pt-BR/settings.json
generated
1
webview-ui/src/i18n/locales/pt-BR/settings.json
generated
|
|
@ -29,6 +29,7 @@
|
|||
"providers": "Provedores",
|
||||
"modes": "Modos",
|
||||
"mcp": "Servidores MCP",
|
||||
"worktrees": "Worktrees",
|
||||
"autoApprove": "Aprovação",
|
||||
"browser": "Navegador",
|
||||
"checkpoints": "Checkpoints",
|
||||
|
|
|
|||
25
webview-ui/src/i18n/locales/pt-BR/worktrees.json
generated
25
webview-ui/src/i18n/locales/pt-BR/worktrees.json
generated
|
|
@ -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,13 +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"
|
||||
"close": "Fechar",
|
||||
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/ru/settings.json
generated
1
webview-ui/src/i18n/locales/ru/settings.json
generated
|
|
@ -29,6 +29,7 @@
|
|||
"providers": "Провайдеры",
|
||||
"modes": "Режимы",
|
||||
"mcp": "Серверы MCP",
|
||||
"worktrees": "Worktrees",
|
||||
"autoApprove": "Автоодобрение",
|
||||
"browser": "Доступ к компьютеру",
|
||||
"checkpoints": "Контрольные точки",
|
||||
|
|
|
|||
25
webview-ui/src/i18n/locales/ru/worktrees.json
generated
25
webview-ui/src/i18n/locales/ru/worktrees.json
generated
|
|
@ -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,13 +46,24 @@
|
|||
"cancel": "Отмена",
|
||||
|
||||
"deleteWorktree": "Удалить Worktree",
|
||||
"deleteWorktreeDescription": "Это удалит worktree и все его файлы.",
|
||||
"deleteWarning": "Это действие нельзя отменить. Будет удалено:",
|
||||
"deleteWarningBranch": "Ветка '{{branch}}' и все незакоммиченные изменения",
|
||||
"deleteWarningBranch": "Ветка и все незакоммиченные изменения",
|
||||
"deleteWarningFiles": "Все файлы в каталоге worktree",
|
||||
"deleteNoticeLarge": "Если это большой репозиторий, это может занять некоторое время.",
|
||||
"forceDelete": "Удалить принудительно",
|
||||
"worktreeIsLocked": "worktree заблокирован",
|
||||
"deleting": "Удаление...",
|
||||
|
||||
"close": "Закрыть"
|
||||
"close": "Закрыть",
|
||||
|
||||
"showInHomeScreen": "Показывать worktrees на главном экране",
|
||||
|
||||
"selector": {
|
||||
"worktree": "Worktree",
|
||||
"title": "Worktrees",
|
||||
"tooltip": "Переключайтесь между worktrees",
|
||||
"description": "Git worktrees позволяют работать с несколькими ветками одновременно. Нажми, чтобы переключить workspace.",
|
||||
"settings": "Управление Worktrees",
|
||||
"info": "Git worktrees позволяют иметь несколько рабочих каталогов, подключенных к одному репозиторию."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/tr/settings.json
generated
1
webview-ui/src/i18n/locales/tr/settings.json
generated
|
|
@ -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ı",
|
||||
|
|
|
|||
25
webview-ui/src/i18n/locales/tr/worktrees.json
generated
25
webview-ui/src/i18n/locales/tr/worktrees.json
generated
|
|
@ -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,13 +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"
|
||||
"close": "Kapat",
|
||||
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/vi/settings.json
generated
1
webview-ui/src/i18n/locales/vi/settings.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
25
webview-ui/src/i18n/locales/vi/worktrees.json
generated
25
webview-ui/src/i18n/locales/vi/worktrees.json
generated
|
|
@ -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,13 +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"
|
||||
"close": "Đóng",
|
||||
|
||||
"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."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/zh-CN/settings.json
generated
1
webview-ui/src/i18n/locales/zh-CN/settings.json
generated
|
|
@ -29,6 +29,7 @@
|
|||
"providers": "提供商",
|
||||
"modes": "模式",
|
||||
"mcp": "MCP 服务",
|
||||
"worktrees": "Worktrees",
|
||||
"autoApprove": "自动批准",
|
||||
"browser": "计算机交互",
|
||||
"checkpoints": "存档点",
|
||||
|
|
|
|||
25
webview-ui/src/i18n/locales/zh-CN/worktrees.json
generated
25
webview-ui/src/i18n/locales/zh-CN/worktrees.json
generated
|
|
@ -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,13 +46,24 @@
|
|||
"cancel": "取消",
|
||||
|
||||
"deleteWorktree": "删除 Worktree",
|
||||
"deleteWorktreeDescription": "这将删除 worktree 及其所有文件。",
|
||||
"deleteWarning": "此操作不可逆。将删除以下内容:",
|
||||
"deleteWarningBranch": "分支 '{{branch}}' 以及所有未提交的更改",
|
||||
"deleteWarningBranch": "分支以及所有未提交的更改",
|
||||
"deleteWarningFiles": "worktree 目录中的所有文件",
|
||||
"deleteNoticeLarge": "如果这是一个大型仓库,可能需要一些时间。",
|
||||
"forceDelete": "强制删除",
|
||||
"worktreeIsLocked": "worktree 已锁定",
|
||||
"deleting": "正在删除...",
|
||||
|
||||
"close": "关闭"
|
||||
"close": "关闭",
|
||||
|
||||
"showInHomeScreen": "在主屏幕显示 worktrees",
|
||||
|
||||
"selector": {
|
||||
"worktree": "Worktree",
|
||||
"title": "Worktrees",
|
||||
"tooltip": "在 worktrees 之间切换",
|
||||
"description": "Git worktrees 让你能在多个分支上同时工作。点击以切换 workspace。",
|
||||
"settings": "管理 Worktrees",
|
||||
"info": "Git worktrees 允许你将多个工作目录连接到同一个仓库。"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
webview-ui/src/i18n/locales/zh-TW/settings.json
generated
1
webview-ui/src/i18n/locales/zh-TW/settings.json
generated
|
|
@ -29,6 +29,7 @@
|
|||
"providers": "供應商",
|
||||
"modes": "模式",
|
||||
"mcp": "MCP 伺服器",
|
||||
"worktrees": "Worktrees",
|
||||
"autoApprove": "自動核准",
|
||||
"browser": "電腦存取",
|
||||
"checkpoints": "檢查點",
|
||||
|
|
|
|||
25
webview-ui/src/i18n/locales/zh-TW/worktrees.json
generated
25
webview-ui/src/i18n/locales/zh-TW/worktrees.json
generated
|
|
@ -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,13 +46,24 @@
|
|||
"cancel": "取消",
|
||||
|
||||
"deleteWorktree": "刪除 Worktree",
|
||||
"deleteWorktreeDescription": "這會刪除 worktree 及其所有檔案。",
|
||||
"deleteWarning": "此操作無法復原。將刪除以下內容:",
|
||||
"deleteWarningBranch": "分支 '{{branch}}' 以及所有未提交的變更",
|
||||
"deleteWarningBranch": "分支以及所有未提交的變更",
|
||||
"deleteWarningFiles": "worktree 目錄中的所有檔案",
|
||||
"deleteNoticeLarge": "如果這是大型儲存庫,可能需要一些時間。",
|
||||
"forceDelete": "強制刪除",
|
||||
"worktreeIsLocked": "worktree 已鎖定",
|
||||
"deleting": "正在刪除...",
|
||||
|
||||
"close": "關閉"
|
||||
"close": "關閉",
|
||||
|
||||
"showInHomeScreen": "在主畫面顯示 worktrees",
|
||||
|
||||
"selector": {
|
||||
"worktree": "Worktree",
|
||||
"title": "Worktrees",
|
||||
"tooltip": "在 worktrees 之間切換",
|
||||
"description": "Git worktrees 讓你能在多個分支上同時工作。點選以切換工作區。",
|
||||
"settings": "管理 Worktrees",
|
||||
"info": "Git worktrees 允許你將多個工作目錄連線到同一個儲存庫。"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue