refactor(conversation-context-bar): slim folder and branch pickers to selection only
- Match popover corner styling of folder picker with branch picker - Drop 'open folder from disk' entry from folder picker - Drop 'new branch' entry and dialog from branch picker
This commit is contained in:
@@ -3,23 +3,13 @@
|
|||||||
import { memo, useCallback, useEffect, useMemo, useState } from "react"
|
import { memo, useCallback, useEffect, useMemo, useState } from "react"
|
||||||
import { useTranslations } from "next-intl"
|
import { useTranslations } from "next-intl"
|
||||||
import { toast } from "sonner"
|
import { toast } from "sonner"
|
||||||
import {
|
import { Check, ChevronsUpDown, Folder, GitBranch, Loader2 } from "lucide-react"
|
||||||
Check,
|
|
||||||
ChevronsUpDown,
|
|
||||||
Folder,
|
|
||||||
FolderOpen,
|
|
||||||
GitBranch,
|
|
||||||
Loader2,
|
|
||||||
Plus,
|
|
||||||
} from "lucide-react"
|
|
||||||
import { useAppWorkspace } from "@/contexts/app-workspace-context"
|
import { useAppWorkspace } from "@/contexts/app-workspace-context"
|
||||||
import { useTabContext } from "@/contexts/tab-context"
|
import { useTabContext } from "@/contexts/tab-context"
|
||||||
import { useTaskContext } from "@/contexts/task-context"
|
import { useTaskContext } from "@/contexts/task-context"
|
||||||
import { gitListAllBranches, gitCheckout, gitNewBranch } from "@/lib/api"
|
import { gitListAllBranches, gitCheckout } from "@/lib/api"
|
||||||
import { isDesktop, openFileDialog } from "@/lib/platform"
|
|
||||||
import type { GitBranchList } from "@/lib/types"
|
import type { GitBranchList } from "@/lib/types"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Input } from "@/components/ui/input"
|
|
||||||
import {
|
import {
|
||||||
Popover,
|
Popover,
|
||||||
PopoverContent,
|
PopoverContent,
|
||||||
@@ -32,15 +22,7 @@ import {
|
|||||||
CommandInput,
|
CommandInput,
|
||||||
CommandItem,
|
CommandItem,
|
||||||
CommandList,
|
CommandList,
|
||||||
CommandSeparator,
|
|
||||||
} from "@/components/ui/command"
|
} from "@/components/ui/command"
|
||||||
import {
|
|
||||||
Dialog,
|
|
||||||
DialogContent,
|
|
||||||
DialogFooter,
|
|
||||||
DialogHeader,
|
|
||||||
DialogTitle,
|
|
||||||
} from "@/components/ui/dialog"
|
|
||||||
import {
|
import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
TooltipContent,
|
TooltipContent,
|
||||||
@@ -64,7 +46,6 @@ export const ConversationContextBar = memo(function ConversationContextBar({
|
|||||||
allFolders,
|
allFolders,
|
||||||
branches,
|
branches,
|
||||||
setBranch,
|
setBranch,
|
||||||
openFolder,
|
|
||||||
addFolderToWorkspaceById,
|
addFolderToWorkspaceById,
|
||||||
refreshFolder,
|
refreshFolder,
|
||||||
} = useAppWorkspace()
|
} = useAppWorkspace()
|
||||||
@@ -115,25 +96,6 @@ export const ConversationContextBar = memo(function ConversationContextBar({
|
|||||||
toast.error(t("toasts.openFolderFailed"))
|
toast.error(t("toasts.openFolderFailed"))
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onOpenNewFolder={async () => {
|
|
||||||
try {
|
|
||||||
if (isDesktop()) {
|
|
||||||
const result = await openFileDialog({
|
|
||||||
directory: true,
|
|
||||||
multiple: false,
|
|
||||||
})
|
|
||||||
if (!result) return
|
|
||||||
const selected = Array.isArray(result) ? result[0] : result
|
|
||||||
const detail = await openFolder(selected)
|
|
||||||
setTabFolder(ownTab.id, detail.id, detail.path)
|
|
||||||
toast.success(t("toasts.folderChanged", { name: detail.name }))
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("[ConversationContextBar] open folder failed:", err)
|
|
||||||
toast.error(t("toasts.openFolderFailed"))
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
labelOpenNew={t("openNewFolder")}
|
|
||||||
labelEmpty={t("noFolders")}
|
labelEmpty={t("noFolders")}
|
||||||
labelSearch={t("searchFolder")}
|
labelSearch={t("searchFolder")}
|
||||||
/>
|
/>
|
||||||
@@ -157,21 +119,6 @@ export const ConversationContextBar = memo(function ConversationContextBar({
|
|||||||
toast.error(msg)
|
toast.error(msg)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onNewBranch={async (branchName, startPoint) => {
|
|
||||||
const taskId = `new-branch-${ownFolder.id}-${Date.now()}`
|
|
||||||
addTask(taskId, tBd("tasks.newBranch", { name: branchName }))
|
|
||||||
updateTask(taskId, { status: "running" })
|
|
||||||
try {
|
|
||||||
await gitNewBranch(ownFolder.path, branchName, startPoint)
|
|
||||||
setBranch(ownFolder.id, branchName)
|
|
||||||
await refreshFolder(ownFolder.id)
|
|
||||||
updateTask(taskId, { status: "completed" })
|
|
||||||
} catch (err) {
|
|
||||||
const msg = err instanceof Error ? err.message : String(err)
|
|
||||||
updateTask(taskId, { status: "failed", error: msg })
|
|
||||||
toast.error(msg)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
@@ -190,8 +137,6 @@ interface FolderPickerProps {
|
|||||||
currentFolderName: string
|
currentFolderName: string
|
||||||
editable: boolean
|
editable: boolean
|
||||||
onSelect: (folderId: number) => void | Promise<void>
|
onSelect: (folderId: number) => void | Promise<void>
|
||||||
onOpenNewFolder: () => void | Promise<void>
|
|
||||||
labelOpenNew: string
|
|
||||||
labelEmpty: string
|
labelEmpty: string
|
||||||
labelSearch: string
|
labelSearch: string
|
||||||
}
|
}
|
||||||
@@ -202,8 +147,6 @@ const FolderPicker = memo(function FolderPicker({
|
|||||||
currentFolderName,
|
currentFolderName,
|
||||||
editable,
|
editable,
|
||||||
onSelect,
|
onSelect,
|
||||||
onOpenNewFolder,
|
|
||||||
labelOpenNew,
|
|
||||||
labelEmpty,
|
labelEmpty,
|
||||||
labelSearch,
|
labelSearch,
|
||||||
}: FolderPickerProps) {
|
}: FolderPickerProps) {
|
||||||
@@ -236,8 +179,8 @@ const FolderPicker = memo(function FolderPicker({
|
|||||||
return (
|
return (
|
||||||
<Popover open={open} onOpenChange={setOpen}>
|
<Popover open={open} onOpenChange={setOpen}>
|
||||||
<PopoverTrigger asChild>{trigger}</PopoverTrigger>
|
<PopoverTrigger asChild>{trigger}</PopoverTrigger>
|
||||||
<PopoverContent align="start" className="p-0 w-72">
|
<PopoverContent align="start" className="p-0 w-72 overflow-hidden">
|
||||||
<Command>
|
<Command className="rounded-2xl">
|
||||||
<CommandInput placeholder={labelSearch} />
|
<CommandInput placeholder={labelSearch} />
|
||||||
<CommandList>
|
<CommandList>
|
||||||
<CommandEmpty>{labelEmpty}</CommandEmpty>
|
<CommandEmpty>{labelEmpty}</CommandEmpty>
|
||||||
@@ -264,18 +207,6 @@ const FolderPicker = memo(function FolderPicker({
|
|||||||
</CommandItem>
|
</CommandItem>
|
||||||
))}
|
))}
|
||||||
</CommandGroup>
|
</CommandGroup>
|
||||||
<CommandSeparator />
|
|
||||||
<CommandGroup>
|
|
||||||
<CommandItem
|
|
||||||
onSelect={() => {
|
|
||||||
setOpen(false)
|
|
||||||
void onOpenNewFolder()
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FolderOpen className="h-4 w-4" />
|
|
||||||
{labelOpenNew}
|
|
||||||
</CommandItem>
|
|
||||||
</CommandGroup>
|
|
||||||
</CommandList>
|
</CommandList>
|
||||||
</Command>
|
</Command>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
@@ -292,7 +223,6 @@ interface BranchPickerProps {
|
|||||||
folderPath: string
|
folderPath: string
|
||||||
currentBranch: string | null
|
currentBranch: string | null
|
||||||
onCheckout: (branchName: string) => Promise<void>
|
onCheckout: (branchName: string) => Promise<void>
|
||||||
onNewBranch: (branchName: string, startPoint?: string) => Promise<void>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const BranchPicker = memo(function BranchPicker({
|
const BranchPicker = memo(function BranchPicker({
|
||||||
@@ -300,15 +230,12 @@ const BranchPicker = memo(function BranchPicker({
|
|||||||
folderPath,
|
folderPath,
|
||||||
currentBranch,
|
currentBranch,
|
||||||
onCheckout,
|
onCheckout,
|
||||||
onNewBranch,
|
|
||||||
}: BranchPickerProps) {
|
}: BranchPickerProps) {
|
||||||
const t = useTranslations("Folder.conversationContextBar")
|
const t = useTranslations("Folder.conversationContextBar")
|
||||||
const tBd = useTranslations("Folder.branchDropdown")
|
const tBd = useTranslations("Folder.branchDropdown")
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
const [branchList, setBranchList] = useState<GitBranchList | null>(null)
|
const [branchList, setBranchList] = useState<GitBranchList | null>(null)
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [newBranchOpen, setNewBranchOpen] = useState(false)
|
|
||||||
const [newBranchName, setNewBranchName] = useState("")
|
|
||||||
|
|
||||||
const loadBranches = useCallback(async () => {
|
const loadBranches = useCallback(async () => {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
@@ -333,135 +260,79 @@ const BranchPicker = memo(function BranchPicker({
|
|||||||
}, [folderId])
|
}, [folderId])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Popover open={open} onOpenChange={setOpen}>
|
||||||
<Popover open={open} onOpenChange={setOpen}>
|
<PopoverTrigger asChild>
|
||||||
<PopoverTrigger asChild>
|
<Button variant="outline" size="xs" className="min-w-0 bg-transparent">
|
||||||
<Button
|
<GitBranch className="size-3 shrink-0 text-muted-foreground" />
|
||||||
variant="outline"
|
<span className="max-w-[160px] truncate">
|
||||||
size="xs"
|
{currentBranch ?? t("noBranch")}
|
||||||
className="min-w-0 bg-transparent"
|
</span>
|
||||||
>
|
<ChevronsUpDown className="size-3 shrink-0 text-muted-foreground" />
|
||||||
<GitBranch className="size-3 shrink-0 text-muted-foreground" />
|
</Button>
|
||||||
<span className="max-w-[160px] truncate">
|
</PopoverTrigger>
|
||||||
{currentBranch ?? t("noBranch")}
|
<PopoverContent align="start" className="p-0 w-80 overflow-hidden">
|
||||||
</span>
|
<Command className="rounded-2xl">
|
||||||
<ChevronsUpDown className="size-3 shrink-0 text-muted-foreground" />
|
<CommandInput placeholder={t("searchBranch")} />
|
||||||
</Button>
|
<CommandList>
|
||||||
</PopoverTrigger>
|
{loading ? (
|
||||||
<PopoverContent align="start" className="p-0 w-80 overflow-hidden">
|
<div className="py-6 text-center text-xs text-muted-foreground">
|
||||||
<Command className="rounded-2xl">
|
<Loader2 className="h-3.5 w-3.5 animate-spin mx-auto" />
|
||||||
<CommandInput placeholder={t("searchBranch")} />
|
</div>
|
||||||
<CommandList>
|
) : (
|
||||||
{loading ? (
|
<>
|
||||||
<div className="py-6 text-center text-xs text-muted-foreground">
|
<CommandEmpty>{t("noBranches")}</CommandEmpty>
|
||||||
<Loader2 className="h-3.5 w-3.5 animate-spin mx-auto" />
|
{branchList && branchList.local.length > 0 && (
|
||||||
</div>
|
<CommandGroup
|
||||||
) : (
|
heading={tBd("localBranches", {
|
||||||
<>
|
count: branchList.local.length,
|
||||||
<CommandEmpty>{t("noBranches")}</CommandEmpty>
|
})}
|
||||||
<CommandGroup>
|
>
|
||||||
<CommandItem
|
{branchList.local.map((b) => (
|
||||||
onSelect={() => {
|
<CommandItem
|
||||||
setOpen(false)
|
key={`local-${b}`}
|
||||||
setNewBranchName("")
|
value={`local ${b}`}
|
||||||
setNewBranchOpen(true)
|
onSelect={() => {
|
||||||
}}
|
setOpen(false)
|
||||||
>
|
if (b !== currentBranch) void onCheckout(b)
|
||||||
<Plus className="h-4 w-4" />
|
}}
|
||||||
{tBd("newBranch")}
|
|
||||||
</CommandItem>
|
|
||||||
</CommandGroup>
|
|
||||||
{branchList && branchList.local.length > 0 && (
|
|
||||||
<>
|
|
||||||
<CommandSeparator />
|
|
||||||
<CommandGroup
|
|
||||||
heading={tBd("localBranches", {
|
|
||||||
count: branchList.local.length,
|
|
||||||
})}
|
|
||||||
>
|
>
|
||||||
{branchList.local.map((b) => (
|
<GitBranch className="h-4 w-4" />
|
||||||
<CommandItem
|
<span className="flex-1 truncate">{b}</span>
|
||||||
key={`local-${b}`}
|
{b === currentBranch && (
|
||||||
value={`local ${b}`}
|
<Check className="h-4 w-4 shrink-0" />
|
||||||
onSelect={() => {
|
)}
|
||||||
setOpen(false)
|
</CommandItem>
|
||||||
if (b !== currentBranch) void onCheckout(b)
|
))}
|
||||||
}}
|
</CommandGroup>
|
||||||
>
|
)}
|
||||||
<GitBranch className="h-4 w-4" />
|
{branchList && branchList.remote.length > 0 && (
|
||||||
<span className="flex-1 truncate">{b}</span>
|
<CommandGroup
|
||||||
{b === currentBranch && (
|
heading={tBd("remoteBranches", {
|
||||||
<Check className="h-4 w-4 shrink-0" />
|
count: branchList.remote.length,
|
||||||
)}
|
})}
|
||||||
</CommandItem>
|
>
|
||||||
))}
|
{branchList.remote.map((b) => (
|
||||||
</CommandGroup>
|
<CommandItem
|
||||||
</>
|
key={`remote-${b}`}
|
||||||
)}
|
value={`remote ${b}`}
|
||||||
{branchList && branchList.remote.length > 0 && (
|
onSelect={() => {
|
||||||
<CommandGroup
|
setOpen(false)
|
||||||
heading={tBd("remoteBranches", {
|
void onCheckout(b)
|
||||||
count: branchList.remote.length,
|
}}
|
||||||
})}
|
>
|
||||||
>
|
<GitBranch className="h-4 w-4 opacity-60" />
|
||||||
{branchList.remote.map((b) => (
|
<span className="flex-1 truncate text-muted-foreground">
|
||||||
<CommandItem
|
{b}
|
||||||
key={`remote-${b}`}
|
</span>
|
||||||
value={`remote ${b}`}
|
</CommandItem>
|
||||||
onSelect={() => {
|
))}
|
||||||
setOpen(false)
|
</CommandGroup>
|
||||||
void onCheckout(b)
|
)}
|
||||||
}}
|
</>
|
||||||
>
|
)}
|
||||||
<GitBranch className="h-4 w-4 opacity-60" />
|
</CommandList>
|
||||||
<span className="flex-1 truncate text-muted-foreground">
|
</Command>
|
||||||
{b}
|
</PopoverContent>
|
||||||
</span>
|
</Popover>
|
||||||
</CommandItem>
|
|
||||||
))}
|
|
||||||
</CommandGroup>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</CommandList>
|
|
||||||
</Command>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
|
|
||||||
<Dialog open={newBranchOpen} onOpenChange={setNewBranchOpen}>
|
|
||||||
<DialogContent>
|
|
||||||
<DialogHeader>
|
|
||||||
<DialogTitle>{tBd("dialogs.newBranchTitle")}</DialogTitle>
|
|
||||||
</DialogHeader>
|
|
||||||
<div className="text-sm text-muted-foreground">
|
|
||||||
{tBd("dialogs.newBranchDescription", {
|
|
||||||
branch: currentBranch ?? "-",
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<Input
|
|
||||||
placeholder={tBd("dialogs.branchNamePlaceholder")}
|
|
||||||
value={newBranchName}
|
|
||||||
onChange={(e) => setNewBranchName(e.target.value)}
|
|
||||||
autoFocus
|
|
||||||
/>
|
|
||||||
<DialogFooter>
|
|
||||||
<Button variant="outline" onClick={() => setNewBranchOpen(false)}>
|
|
||||||
{t("cancel")}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
disabled={!newBranchName.trim()}
|
|
||||||
onClick={async () => {
|
|
||||||
const name = newBranchName.trim()
|
|
||||||
if (!name) return
|
|
||||||
setNewBranchOpen(false)
|
|
||||||
await onNewBranch(name, currentBranch ?? undefined)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("create")}
|
|
||||||
</Button>
|
|
||||||
</DialogFooter>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1797,9 +1797,6 @@
|
|||||||
"noFolders": "No folders",
|
"noFolders": "No folders",
|
||||||
"noBranches": "No branches",
|
"noBranches": "No branches",
|
||||||
"noBranch": "(no branch)",
|
"noBranch": "(no branch)",
|
||||||
"openNewFolder": "Open folder from disk...",
|
|
||||||
"cancel": "Cancel",
|
|
||||||
"create": "Create",
|
|
||||||
"commit": "Commit",
|
"commit": "Commit",
|
||||||
"push": "Push",
|
"push": "Push",
|
||||||
"merge": "Merge",
|
"merge": "Merge",
|
||||||
|
|||||||
@@ -1797,9 +1797,6 @@
|
|||||||
"noFolders": "No folders",
|
"noFolders": "No folders",
|
||||||
"noBranches": "No branches",
|
"noBranches": "No branches",
|
||||||
"noBranch": "(no branch)",
|
"noBranch": "(no branch)",
|
||||||
"openNewFolder": "Open folder from disk...",
|
|
||||||
"cancel": "Cancel",
|
|
||||||
"create": "Create",
|
|
||||||
"commit": "Commit",
|
"commit": "Commit",
|
||||||
"push": "Push",
|
"push": "Push",
|
||||||
"merge": "Merge",
|
"merge": "Merge",
|
||||||
|
|||||||
@@ -1797,9 +1797,6 @@
|
|||||||
"noFolders": "No folders",
|
"noFolders": "No folders",
|
||||||
"noBranches": "No branches",
|
"noBranches": "No branches",
|
||||||
"noBranch": "(no branch)",
|
"noBranch": "(no branch)",
|
||||||
"openNewFolder": "Open folder from disk...",
|
|
||||||
"cancel": "Cancel",
|
|
||||||
"create": "Create",
|
|
||||||
"commit": "Commit",
|
"commit": "Commit",
|
||||||
"push": "Push",
|
"push": "Push",
|
||||||
"merge": "Merge",
|
"merge": "Merge",
|
||||||
|
|||||||
@@ -1797,9 +1797,6 @@
|
|||||||
"noFolders": "No folders",
|
"noFolders": "No folders",
|
||||||
"noBranches": "No branches",
|
"noBranches": "No branches",
|
||||||
"noBranch": "(no branch)",
|
"noBranch": "(no branch)",
|
||||||
"openNewFolder": "Open folder from disk...",
|
|
||||||
"cancel": "Cancel",
|
|
||||||
"create": "Create",
|
|
||||||
"commit": "Commit",
|
"commit": "Commit",
|
||||||
"push": "Push",
|
"push": "Push",
|
||||||
"merge": "Merge",
|
"merge": "Merge",
|
||||||
|
|||||||
@@ -1797,9 +1797,6 @@
|
|||||||
"noFolders": "No folders",
|
"noFolders": "No folders",
|
||||||
"noBranches": "No branches",
|
"noBranches": "No branches",
|
||||||
"noBranch": "(no branch)",
|
"noBranch": "(no branch)",
|
||||||
"openNewFolder": "Open folder from disk...",
|
|
||||||
"cancel": "Cancel",
|
|
||||||
"create": "Create",
|
|
||||||
"commit": "Commit",
|
"commit": "Commit",
|
||||||
"push": "Push",
|
"push": "Push",
|
||||||
"merge": "Merge",
|
"merge": "Merge",
|
||||||
|
|||||||
@@ -1797,9 +1797,6 @@
|
|||||||
"noFolders": "No folders",
|
"noFolders": "No folders",
|
||||||
"noBranches": "No branches",
|
"noBranches": "No branches",
|
||||||
"noBranch": "(no branch)",
|
"noBranch": "(no branch)",
|
||||||
"openNewFolder": "Open folder from disk...",
|
|
||||||
"cancel": "Cancel",
|
|
||||||
"create": "Create",
|
|
||||||
"commit": "Commit",
|
"commit": "Commit",
|
||||||
"push": "Push",
|
"push": "Push",
|
||||||
"merge": "Merge",
|
"merge": "Merge",
|
||||||
|
|||||||
@@ -1797,9 +1797,6 @@
|
|||||||
"noFolders": "No folders",
|
"noFolders": "No folders",
|
||||||
"noBranches": "No branches",
|
"noBranches": "No branches",
|
||||||
"noBranch": "(no branch)",
|
"noBranch": "(no branch)",
|
||||||
"openNewFolder": "Open folder from disk...",
|
|
||||||
"cancel": "Cancel",
|
|
||||||
"create": "Create",
|
|
||||||
"commit": "Commit",
|
"commit": "Commit",
|
||||||
"push": "Push",
|
"push": "Push",
|
||||||
"merge": "Merge",
|
"merge": "Merge",
|
||||||
|
|||||||
@@ -1797,9 +1797,6 @@
|
|||||||
"noFolders": "No folders",
|
"noFolders": "No folders",
|
||||||
"noBranches": "No branches",
|
"noBranches": "No branches",
|
||||||
"noBranch": "(no branch)",
|
"noBranch": "(no branch)",
|
||||||
"openNewFolder": "Open folder from disk...",
|
|
||||||
"cancel": "Cancel",
|
|
||||||
"create": "Create",
|
|
||||||
"commit": "Commit",
|
"commit": "Commit",
|
||||||
"push": "Push",
|
"push": "Push",
|
||||||
"merge": "Merge",
|
"merge": "Merge",
|
||||||
|
|||||||
@@ -1797,9 +1797,6 @@
|
|||||||
"noFolders": "暂无文件夹",
|
"noFolders": "暂无文件夹",
|
||||||
"noBranches": "暂无分支",
|
"noBranches": "暂无分支",
|
||||||
"noBranch": "(无分支)",
|
"noBranch": "(无分支)",
|
||||||
"openNewFolder": "从磁盘打开文件夹...",
|
|
||||||
"cancel": "取消",
|
|
||||||
"create": "创建",
|
|
||||||
"commit": "提交",
|
"commit": "提交",
|
||||||
"push": "推送",
|
"push": "推送",
|
||||||
"merge": "合并",
|
"merge": "合并",
|
||||||
|
|||||||
@@ -1797,9 +1797,6 @@
|
|||||||
"noFolders": "No folders",
|
"noFolders": "No folders",
|
||||||
"noBranches": "No branches",
|
"noBranches": "No branches",
|
||||||
"noBranch": "(no branch)",
|
"noBranch": "(no branch)",
|
||||||
"openNewFolder": "Open folder from disk...",
|
|
||||||
"cancel": "Cancel",
|
|
||||||
"create": "Create",
|
|
||||||
"commit": "Commit",
|
"commit": "Commit",
|
||||||
"push": "Push",
|
"push": "Push",
|
||||||
"merge": "Merge",
|
"merge": "Merge",
|
||||||
|
|||||||
Reference in New Issue
Block a user