在文件树上支持右键添加文件和添加目录操作
This commit is contained in:
@@ -2555,6 +2555,69 @@ pub async fn delete_file_tree_entry(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn create_file_tree_entry(
|
||||
root_path: String,
|
||||
path: String,
|
||||
name: String,
|
||||
kind: String,
|
||||
) -> Result<String, AppCommandError> {
|
||||
let root = PathBuf::from(&root_path);
|
||||
if !root.exists() || !root.is_dir() {
|
||||
return Err(AppCommandError::not_found("Folder does not exist"));
|
||||
}
|
||||
|
||||
let validated_name = validate_new_name(&name)?;
|
||||
|
||||
let parent_dir = if path.is_empty() {
|
||||
root.clone()
|
||||
} else {
|
||||
let resolved = resolve_tree_path(&root, &path)?;
|
||||
if !resolved.exists() {
|
||||
return Err(AppCommandError::not_found("Parent path does not exist"));
|
||||
}
|
||||
if resolved.is_file() {
|
||||
resolved
|
||||
.parent()
|
||||
.map(|p| p.to_path_buf())
|
||||
.ok_or_else(|| AppCommandError::invalid_input("Cannot determine parent directory"))?
|
||||
} else {
|
||||
resolved
|
||||
}
|
||||
};
|
||||
|
||||
let target = parent_dir.join(validated_name);
|
||||
if target.exists() {
|
||||
return Err(AppCommandError::already_exists(
|
||||
"A file or directory with this name already exists",
|
||||
));
|
||||
}
|
||||
|
||||
match kind.as_str() {
|
||||
"file" => {
|
||||
std::fs::File::create(&target).map_err(AppCommandError::io)?;
|
||||
}
|
||||
"dir" => {
|
||||
std::fs::create_dir(&target).map_err(AppCommandError::io)?;
|
||||
}
|
||||
_ => {
|
||||
return Err(AppCommandError::invalid_input(
|
||||
"Kind must be 'file' or 'dir'",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let rel = target
|
||||
.strip_prefix(&root)
|
||||
.map_err(|e| {
|
||||
AppCommandError::invalid_input("Failed to compute relative path")
|
||||
.with_detail(e.to_string())
|
||||
})?
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
Ok(rel)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn git_log(
|
||||
path: String,
|
||||
|
||||
@@ -218,6 +218,7 @@ pub fn run() {
|
||||
folders::save_file_copy,
|
||||
folders::rename_file_tree_entry,
|
||||
folders::delete_file_tree_entry,
|
||||
folders::create_file_tree_entry,
|
||||
folders::git_log,
|
||||
folders::git_commit_branches,
|
||||
windows::open_folder_window,
|
||||
|
||||
@@ -21,6 +21,7 @@ import { useTabContext } from "@/contexts/tab-context"
|
||||
import { useTerminalContext } from "@/contexts/terminal-context"
|
||||
import { useWorkspaceContext } from "@/contexts/workspace-context"
|
||||
import {
|
||||
createFileTreeEntry,
|
||||
deleteFileTreeEntry,
|
||||
gitAddFiles,
|
||||
getGitBranch,
|
||||
@@ -419,6 +420,7 @@ interface RenderNodeProps {
|
||||
onOpenDirInTerminal: (dirPath: string, fileName: string) => Promise<void>
|
||||
onRequestAddToVcs: (target: FileActionTarget) => void
|
||||
onRequestRename: (target: FileActionTarget) => void
|
||||
onRequestCreate: (parentPath: string, kind: "file" | "dir") => void
|
||||
onRequestDelete: (target: FileActionTarget) => void
|
||||
onRefresh: () => void
|
||||
}
|
||||
@@ -441,6 +443,7 @@ function RenderNode({
|
||||
onRequestRollback,
|
||||
onOpenDirInTerminal,
|
||||
onRequestAddToVcs,
|
||||
onRequestCreate,
|
||||
onRequestRename,
|
||||
onRequestDelete,
|
||||
onRefresh,
|
||||
@@ -507,6 +510,21 @@ function RenderNode({
|
||||
>
|
||||
{t("attachToCurrentSession")}
|
||||
</ContextMenuItem>
|
||||
<ContextMenuSub>
|
||||
<ContextMenuSubTrigger>{t("new")}</ContextMenuSubTrigger>
|
||||
<ContextMenuSubContent>
|
||||
<ContextMenuItem
|
||||
onSelect={() => onRequestCreate(node.path, "file")}
|
||||
>
|
||||
{t("newFile")}
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem
|
||||
onSelect={() => onRequestCreate(node.path, "dir")}
|
||||
>
|
||||
{t("newDirectory")}
|
||||
</ContextMenuItem>
|
||||
</ContextMenuSubContent>
|
||||
</ContextMenuSub>
|
||||
<ContextMenuSub>
|
||||
<ContextMenuSubTrigger disabled={isGitMenuDisabled}>
|
||||
{t("git")}
|
||||
@@ -629,6 +647,7 @@ function RenderNode({
|
||||
onRequestCompareWithBranch={onRequestCompareWithBranch}
|
||||
onRequestRollback={onRequestRollback}
|
||||
onOpenDirInTerminal={onOpenDirInTerminal}
|
||||
onRequestCreate={onRequestCreate}
|
||||
onRequestAddToVcs={onRequestAddToVcs}
|
||||
onRequestRename={onRequestRename}
|
||||
onRequestDelete={onRequestDelete}
|
||||
@@ -639,6 +658,19 @@ function RenderNode({
|
||||
</FileTreeFolder>
|
||||
</ContextMenuTrigger>
|
||||
<ContextMenuContent>
|
||||
<ContextMenuSub>
|
||||
<ContextMenuSubTrigger>{t("new")}</ContextMenuSubTrigger>
|
||||
<ContextMenuSubContent>
|
||||
<ContextMenuItem
|
||||
onSelect={() => onRequestCreate(node.path, "file")}
|
||||
>
|
||||
{t("newFile")}
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem onSelect={() => onRequestCreate(node.path, "dir")}>
|
||||
{t("newDirectory")}
|
||||
</ContextMenuItem>
|
||||
</ContextMenuSubContent>
|
||||
</ContextMenuSub>
|
||||
<ContextMenuSub>
|
||||
<ContextMenuSubTrigger disabled={isGitMenuDisabled}>
|
||||
{t("git")}
|
||||
@@ -736,6 +768,10 @@ export function FileTreeTab() {
|
||||
)
|
||||
const [renameValue, setRenameValue] = useState("")
|
||||
const [renaming, setRenaming] = useState(false)
|
||||
const [createParentPath, setCreateParentPath] = useState<string | null>(null)
|
||||
const [createKind, setCreateKind] = useState<"file" | "dir">("file")
|
||||
const [createName, setCreateName] = useState("")
|
||||
const [creating, setCreating] = useState(false)
|
||||
const [deleteTarget, setDeleteTarget] = useState<FileActionTarget | null>(
|
||||
null
|
||||
)
|
||||
@@ -1139,6 +1175,15 @@ export function FileTreeTab() {
|
||||
})
|
||||
}, [folder, t])
|
||||
|
||||
const handleRequestCreate = useCallback(
|
||||
(parentPath: string, kind: "file" | "dir") => {
|
||||
setCreateParentPath(parentPath)
|
||||
setCreateKind(kind)
|
||||
setCreateName("")
|
||||
},
|
||||
[]
|
||||
)
|
||||
|
||||
const handleRequestRename = useCallback((target: FileActionTarget) => {
|
||||
setRenameTarget(target)
|
||||
setRenameValue(target.name)
|
||||
@@ -1516,6 +1561,33 @@ export function FileTreeTab() {
|
||||
]
|
||||
)
|
||||
|
||||
const handleCreateConfirm = useCallback(async () => {
|
||||
if (!folder?.path || createParentPath === null) return
|
||||
const trimmedName = createName.trim()
|
||||
if (!trimmedName) {
|
||||
setCreateParentPath(null)
|
||||
return
|
||||
}
|
||||
|
||||
setCreating(true)
|
||||
try {
|
||||
await createFileTreeEntry(
|
||||
folder.path,
|
||||
createParentPath,
|
||||
trimmedName,
|
||||
createKind
|
||||
)
|
||||
setCreateParentPath(null)
|
||||
setCreateName("")
|
||||
await fetchTree()
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error)
|
||||
toast.error(t("toasts.createFailed"), { description: message })
|
||||
} finally {
|
||||
setCreating(false)
|
||||
}
|
||||
}, [createKind, createName, createParentPath, fetchTree, folder?.path, t])
|
||||
|
||||
const handleRenameConfirm = useCallback(async () => {
|
||||
if (!folder?.path || !renameTarget) return
|
||||
const nextName = renameValue.trim()
|
||||
@@ -2074,6 +2146,7 @@ export function FileTreeTab() {
|
||||
}
|
||||
onRequestRollback={handleRequestRollback}
|
||||
onOpenDirInTerminal={handleOpenDirInTerminal}
|
||||
onRequestCreate={handleRequestCreate}
|
||||
onRequestAddToVcs={handleAddToVcs}
|
||||
onRequestRename={handleRequestRename}
|
||||
onRequestDelete={handleRequestDelete}
|
||||
@@ -2083,6 +2156,21 @@ export function FileTreeTab() {
|
||||
</FileTreeFolder>
|
||||
</ContextMenuTrigger>
|
||||
<ContextMenuContent>
|
||||
<ContextMenuSub>
|
||||
<ContextMenuSubTrigger>{t("new")}</ContextMenuSubTrigger>
|
||||
<ContextMenuSubContent>
|
||||
<ContextMenuItem
|
||||
onSelect={() => handleRequestCreate("", "file")}
|
||||
>
|
||||
{t("newFile")}
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem
|
||||
onSelect={() => handleRequestCreate("", "dir")}
|
||||
>
|
||||
{t("newDirectory")}
|
||||
</ContextMenuItem>
|
||||
</ContextMenuSubContent>
|
||||
</ContextMenuSub>
|
||||
<ContextMenuSub>
|
||||
<ContextMenuSubTrigger disabled={!gitEnabled}>
|
||||
{t("git")}
|
||||
@@ -2165,6 +2253,17 @@ export function FileTreeTab() {
|
||||
</div>
|
||||
</ContextMenuTrigger>
|
||||
<ContextMenuContent>
|
||||
<ContextMenuSub>
|
||||
<ContextMenuSubTrigger>{t("new")}</ContextMenuSubTrigger>
|
||||
<ContextMenuSubContent>
|
||||
<ContextMenuItem onSelect={() => handleRequestCreate("", "file")}>
|
||||
{t("newFile")}
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem onSelect={() => handleRequestCreate("", "dir")}>
|
||||
{t("newDirectory")}
|
||||
</ContextMenuItem>
|
||||
</ContextMenuSubContent>
|
||||
</ContextMenuSub>
|
||||
<ContextMenuItem
|
||||
onSelect={() => {
|
||||
void fetchTree()
|
||||
@@ -2175,6 +2274,68 @@ export function FileTreeTab() {
|
||||
</ContextMenuContent>
|
||||
</ContextMenu>
|
||||
|
||||
<Dialog
|
||||
open={createParentPath !== null}
|
||||
onOpenChange={(open) => {
|
||||
if (open) return
|
||||
setCreateParentPath(null)
|
||||
setCreateName("")
|
||||
}}
|
||||
>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
{createKind === "dir"
|
||||
? t("createDialog.newDirectory")
|
||||
: t("createDialog.newFile")}
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
{t("createDialog.description", {
|
||||
kind:
|
||||
createKind === "dir"
|
||||
? t("newDirectory").toLowerCase()
|
||||
: t("newFile").toLowerCase(),
|
||||
})}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<form
|
||||
onSubmit={(event) => {
|
||||
event.preventDefault()
|
||||
void handleCreateConfirm()
|
||||
}}
|
||||
className="space-y-4"
|
||||
>
|
||||
<Input
|
||||
value={createName}
|
||||
onChange={(event) => setCreateName(event.target.value)}
|
||||
autoFocus
|
||||
disabled={creating}
|
||||
placeholder={
|
||||
createKind === "dir"
|
||||
? t("createDialog.placeholderDirectory")
|
||||
: t("createDialog.placeholderFile")
|
||||
}
|
||||
/>
|
||||
<DialogFooter>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
disabled={creating}
|
||||
onClick={() => {
|
||||
setCreateParentPath(null)
|
||||
setCreateName("")
|
||||
}}
|
||||
>
|
||||
{tCommon("cancel")}
|
||||
</Button>
|
||||
<Button type="submit" disabled={creating || !createName.trim()}>
|
||||
{tCommon("create")}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<Dialog
|
||||
open={Boolean(renameTarget)}
|
||||
onOpenChange={(open) => {
|
||||
@@ -2473,7 +2634,12 @@ export function FileTreeTab() {
|
||||
<Collapsible key={remoteName}>
|
||||
<CollapsibleTrigger className="flex w-full items-center gap-2.5 rounded-xl px-2 py-1.5 pl-5 text-sm hover:bg-accent hover:text-accent-foreground select-none outline-hidden">
|
||||
<ChevronRight className="h-3 w-3 shrink-0 transition-transform [[data-state=open]>&]:rotate-90" />
|
||||
{remoteName} ({groupedCompareRemoteBranches[remoteName].length})
|
||||
{remoteName} (
|
||||
{
|
||||
groupedCompareRemoteBranches[remoteName]
|
||||
.length
|
||||
}
|
||||
)
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent className="space-y-1 pt-1 pl-3">
|
||||
{groupedCompareRemoteBranches[remoteName].map(
|
||||
@@ -2489,7 +2655,9 @@ export function FileTreeTab() {
|
||||
}}
|
||||
disabled={comparing}
|
||||
>
|
||||
{branch.substring(remoteName.length + 1)}
|
||||
{branch.substring(
|
||||
remoteName.length + 1
|
||||
)}
|
||||
</Button>
|
||||
)
|
||||
)}
|
||||
|
||||
@@ -967,6 +967,9 @@
|
||||
"attachToCurrentSession": "إرفاق بالجلسة الحالية",
|
||||
"compareWithBranch": "المقارنة مع الفرع...",
|
||||
"reloadFromDisk": "إعادة التحميل من القرص",
|
||||
"new": "جديد",
|
||||
"newFile": "ملف",
|
||||
"newDirectory": "مجلد",
|
||||
"openIn": "فتح في",
|
||||
"openInTerminal": "فتح في الطرفية",
|
||||
"actions": {
|
||||
@@ -996,7 +999,15 @@
|
||||
"rolledBackFiles": "{count, plural, one {تم التراجع عن ملف واحد} other {تم التراجع عن # ملفات}}",
|
||||
"savedAsCopy": "تم الحفظ كنسخة",
|
||||
"saveCopyFailed": "فشل الحفظ كنسخة",
|
||||
"watchStartFailed": "فشل بدء مراقبة الملفات"
|
||||
"watchStartFailed": "فشل بدء مراقبة الملفات",
|
||||
"createFailed": "فشل في الإنشاء"
|
||||
},
|
||||
"createDialog": {
|
||||
"newFile": "ملف جديد",
|
||||
"newDirectory": "مجلد جديد",
|
||||
"description": "أدخل اسمًا لـ{kind} الجديد.",
|
||||
"placeholderFile": "file-name.ext",
|
||||
"placeholderDirectory": "folder-name"
|
||||
},
|
||||
"renameDialog": {
|
||||
"renameDirectory": "إعادة تسمية المجلد",
|
||||
|
||||
@@ -967,6 +967,9 @@
|
||||
"attachToCurrentSession": "An aktuelle Sitzung anhängen",
|
||||
"compareWithBranch": "Mit Branch vergleichen...",
|
||||
"reloadFromDisk": "Von Datenträger neu laden",
|
||||
"new": "Neu",
|
||||
"newFile": "Datei",
|
||||
"newDirectory": "Verzeichnis",
|
||||
"openIn": "Öffnen in",
|
||||
"openInTerminal": "Im Terminal öffnen",
|
||||
"actions": {
|
||||
@@ -996,7 +999,15 @@
|
||||
"rolledBackFiles": "{count, plural, one {# Datei zurückgesetzt} other {# Dateien zurückgesetzt}}",
|
||||
"savedAsCopy": "Als Kopie gespeichert",
|
||||
"saveCopyFailed": "Speichern als Kopie fehlgeschlagen",
|
||||
"watchStartFailed": "Dateiwatch konnte nicht gestartet werden"
|
||||
"watchStartFailed": "Dateiwatch konnte nicht gestartet werden",
|
||||
"createFailed": "Erstellen fehlgeschlagen"
|
||||
},
|
||||
"createDialog": {
|
||||
"newFile": "Neue Datei",
|
||||
"newDirectory": "Neues Verzeichnis",
|
||||
"description": "Geben Sie einen Namen für das neue {kind} ein.",
|
||||
"placeholderFile": "file-name.ext",
|
||||
"placeholderDirectory": "folder-name"
|
||||
},
|
||||
"renameDialog": {
|
||||
"renameDirectory": "Verzeichnis umbenennen",
|
||||
|
||||
@@ -967,6 +967,9 @@
|
||||
"attachToCurrentSession": "Attach to current session",
|
||||
"compareWithBranch": "Compare with branch...",
|
||||
"reloadFromDisk": "Reload from disk",
|
||||
"new": "New",
|
||||
"newFile": "File",
|
||||
"newDirectory": "Directory",
|
||||
"openIn": "Open in",
|
||||
"openInTerminal": "Open in terminal",
|
||||
"actions": {
|
||||
@@ -996,7 +999,15 @@
|
||||
"rolledBackFiles": "Rolled back {count, plural, one {# file} other {# files}}",
|
||||
"savedAsCopy": "Saved as a copy",
|
||||
"saveCopyFailed": "Failed to save as copy",
|
||||
"watchStartFailed": "Failed to start file watch"
|
||||
"watchStartFailed": "Failed to start file watch",
|
||||
"createFailed": "Failed to create"
|
||||
},
|
||||
"createDialog": {
|
||||
"newFile": "New file",
|
||||
"newDirectory": "New directory",
|
||||
"description": "Enter a name for the new {kind}.",
|
||||
"placeholderFile": "file-name.ext",
|
||||
"placeholderDirectory": "folder-name"
|
||||
},
|
||||
"renameDialog": {
|
||||
"renameDirectory": "Rename directory",
|
||||
|
||||
@@ -967,6 +967,9 @@
|
||||
"attachToCurrentSession": "Adjuntar a la sesión actual",
|
||||
"compareWithBranch": "Comparar con rama...",
|
||||
"reloadFromDisk": "Recargar desde disco",
|
||||
"new": "Nuevo",
|
||||
"newFile": "Archivo",
|
||||
"newDirectory": "Directorio",
|
||||
"openIn": "Abrir en",
|
||||
"openInTerminal": "Abrir en terminal",
|
||||
"actions": {
|
||||
@@ -996,7 +999,15 @@
|
||||
"rolledBackFiles": "{count, plural, one {Se revirtió # archivo} other {Se revirtieron # archivos}}",
|
||||
"savedAsCopy": "Guardado como copia",
|
||||
"saveCopyFailed": "No se pudo guardar como copia",
|
||||
"watchStartFailed": "No se pudo iniciar la vigilancia de archivos"
|
||||
"watchStartFailed": "No se pudo iniciar la vigilancia de archivos",
|
||||
"createFailed": "Error al crear"
|
||||
},
|
||||
"createDialog": {
|
||||
"newFile": "Nuevo archivo",
|
||||
"newDirectory": "Nuevo directorio",
|
||||
"description": "Ingrese un nombre para el nuevo {kind}.",
|
||||
"placeholderFile": "file-name.ext",
|
||||
"placeholderDirectory": "folder-name"
|
||||
},
|
||||
"renameDialog": {
|
||||
"renameDirectory": "Renombrar directorio",
|
||||
|
||||
@@ -967,6 +967,9 @@
|
||||
"attachToCurrentSession": "Attacher à la session actuelle",
|
||||
"compareWithBranch": "Comparer avec la branche...",
|
||||
"reloadFromDisk": "Recharger depuis le disque",
|
||||
"new": "Nouveau",
|
||||
"newFile": "Fichier",
|
||||
"newDirectory": "Répertoire",
|
||||
"openIn": "Ouvrir dans",
|
||||
"openInTerminal": "Ouvrir dans le terminal",
|
||||
"actions": {
|
||||
@@ -996,7 +999,15 @@
|
||||
"rolledBackFiles": "{count, plural, one {# fichier annulé} other {# fichiers annulés}}",
|
||||
"savedAsCopy": "Enregistré en copie",
|
||||
"saveCopyFailed": "Échec de l'enregistrement en copie",
|
||||
"watchStartFailed": "Échec du démarrage de la surveillance de fichiers"
|
||||
"watchStartFailed": "Échec du démarrage de la surveillance de fichiers",
|
||||
"createFailed": "Échec de la création"
|
||||
},
|
||||
"createDialog": {
|
||||
"newFile": "Nouveau fichier",
|
||||
"newDirectory": "Nouveau répertoire",
|
||||
"description": "Entrez un nom pour le nouveau {kind}.",
|
||||
"placeholderFile": "file-name.ext",
|
||||
"placeholderDirectory": "folder-name"
|
||||
},
|
||||
"renameDialog": {
|
||||
"renameDirectory": "Renommer le dossier",
|
||||
|
||||
@@ -967,6 +967,9 @@
|
||||
"attachToCurrentSession": "現在のセッションに添付",
|
||||
"compareWithBranch": "ブランチと比較...",
|
||||
"reloadFromDisk": "ディスクから再読み込み",
|
||||
"new": "新規作成",
|
||||
"newFile": "ファイル",
|
||||
"newDirectory": "ディレクトリ",
|
||||
"openIn": "で開く",
|
||||
"openInTerminal": "ターミナルで開く",
|
||||
"actions": {
|
||||
@@ -996,7 +999,15 @@
|
||||
"rolledBackFiles": "{count, plural, one {# 件のファイルをロールバックしました} other {# 件のファイルをロールバックしました}}",
|
||||
"savedAsCopy": "コピーとして保存しました",
|
||||
"saveCopyFailed": "コピーとして保存できませんでした",
|
||||
"watchStartFailed": "ファイル監視の開始に失敗しました"
|
||||
"watchStartFailed": "ファイル監視の開始に失敗しました",
|
||||
"createFailed": "作成に失敗しました"
|
||||
},
|
||||
"createDialog": {
|
||||
"newFile": "新規ファイル",
|
||||
"newDirectory": "新規ディレクトリ",
|
||||
"description": "新しい{kind}の名前を入力してください。",
|
||||
"placeholderFile": "file-name.ext",
|
||||
"placeholderDirectory": "folder-name"
|
||||
},
|
||||
"renameDialog": {
|
||||
"renameDirectory": "ディレクトリ名を変更",
|
||||
|
||||
@@ -967,6 +967,9 @@
|
||||
"attachToCurrentSession": "현재 세션에 연결",
|
||||
"compareWithBranch": "브랜치와 비교...",
|
||||
"reloadFromDisk": "디스크에서 다시 불러오기",
|
||||
"new": "새로 만들기",
|
||||
"newFile": "파일",
|
||||
"newDirectory": "디렉터리",
|
||||
"openIn": "열기",
|
||||
"openInTerminal": "터미널에서 열기",
|
||||
"actions": {
|
||||
@@ -996,7 +999,15 @@
|
||||
"rolledBackFiles": "{count, plural, one {#개 파일을 롤백했습니다} other {#개 파일을 롤백했습니다}}",
|
||||
"savedAsCopy": "사본으로 저장했습니다",
|
||||
"saveCopyFailed": "사본으로 저장하지 못했습니다",
|
||||
"watchStartFailed": "파일 감시 시작에 실패했습니다"
|
||||
"watchStartFailed": "파일 감시 시작에 실패했습니다",
|
||||
"createFailed": "생성 실패"
|
||||
},
|
||||
"createDialog": {
|
||||
"newFile": "새 파일",
|
||||
"newDirectory": "새 디렉터리",
|
||||
"description": "새 {kind}의 이름을 입력하세요.",
|
||||
"placeholderFile": "file-name.ext",
|
||||
"placeholderDirectory": "folder-name"
|
||||
},
|
||||
"renameDialog": {
|
||||
"renameDirectory": "디렉터리 이름 변경",
|
||||
|
||||
@@ -967,6 +967,9 @@
|
||||
"attachToCurrentSession": "Anexar à sessão atual",
|
||||
"compareWithBranch": "Comparar com branch...",
|
||||
"reloadFromDisk": "Recarregar do disco",
|
||||
"new": "Novo",
|
||||
"newFile": "Arquivo",
|
||||
"newDirectory": "Diretório",
|
||||
"openIn": "Abrir em",
|
||||
"openInTerminal": "Abrir no terminal",
|
||||
"actions": {
|
||||
@@ -996,7 +999,15 @@
|
||||
"rolledBackFiles": "{count, plural, one {# arquivo revertido} other {# arquivos revertidos}}",
|
||||
"savedAsCopy": "Salvo como cópia",
|
||||
"saveCopyFailed": "Falha ao salvar como cópia",
|
||||
"watchStartFailed": "Falha ao iniciar monitoramento de arquivos"
|
||||
"watchStartFailed": "Falha ao iniciar monitoramento de arquivos",
|
||||
"createFailed": "Falha ao criar"
|
||||
},
|
||||
"createDialog": {
|
||||
"newFile": "Novo arquivo",
|
||||
"newDirectory": "Novo diretório",
|
||||
"description": "Digite um nome para o novo {kind}.",
|
||||
"placeholderFile": "file-name.ext",
|
||||
"placeholderDirectory": "folder-name"
|
||||
},
|
||||
"renameDialog": {
|
||||
"renameDirectory": "Renomear diretório",
|
||||
|
||||
@@ -967,6 +967,9 @@
|
||||
"attachToCurrentSession": "附加到当前会话",
|
||||
"compareWithBranch": "与分支比较...",
|
||||
"reloadFromDisk": "从磁盘重新加载",
|
||||
"new": "新建",
|
||||
"newFile": "文件",
|
||||
"newDirectory": "目录",
|
||||
"openIn": "打开于",
|
||||
"openInTerminal": "在终端打开",
|
||||
"actions": {
|
||||
@@ -996,7 +999,15 @@
|
||||
"rolledBackFiles": "已回滚 {count} 个文件",
|
||||
"savedAsCopy": "已另存为副本",
|
||||
"saveCopyFailed": "另存为副本失败",
|
||||
"watchStartFailed": "文件监听启动失败"
|
||||
"watchStartFailed": "文件监听启动失败",
|
||||
"createFailed": "创建失败"
|
||||
},
|
||||
"createDialog": {
|
||||
"newFile": "新建文件",
|
||||
"newDirectory": "新建目录",
|
||||
"description": "输入新{kind}的名称。",
|
||||
"placeholderFile": "文件名.ext",
|
||||
"placeholderDirectory": "文件夹名"
|
||||
},
|
||||
"renameDialog": {
|
||||
"renameDirectory": "重命名目录",
|
||||
|
||||
@@ -967,6 +967,9 @@
|
||||
"attachToCurrentSession": "附加到目前會話",
|
||||
"compareWithBranch": "與分支比較...",
|
||||
"reloadFromDisk": "從磁碟重新載入",
|
||||
"new": "新建",
|
||||
"newFile": "檔案",
|
||||
"newDirectory": "目錄",
|
||||
"openIn": "開啟於",
|
||||
"openInTerminal": "在終端開啟",
|
||||
"actions": {
|
||||
@@ -996,7 +999,15 @@
|
||||
"rolledBackFiles": "已回滾 {count} 個檔案",
|
||||
"savedAsCopy": "已另存為副本",
|
||||
"saveCopyFailed": "另存為副本失敗",
|
||||
"watchStartFailed": "檔案監聽啟動失敗"
|
||||
"watchStartFailed": "檔案監聽啟動失敗",
|
||||
"createFailed": "建立失敗"
|
||||
},
|
||||
"createDialog": {
|
||||
"newFile": "新建檔案",
|
||||
"newDirectory": "新建目錄",
|
||||
"description": "輸入新{kind}的名稱。",
|
||||
"placeholderFile": "file-name.ext",
|
||||
"placeholderDirectory": "folder-name"
|
||||
},
|
||||
"renameDialog": {
|
||||
"renameDirectory": "重新命名目錄",
|
||||
|
||||
@@ -850,6 +850,15 @@ export async function deleteFileTreeEntry(
|
||||
return invoke("delete_file_tree_entry", { rootPath, path })
|
||||
}
|
||||
|
||||
export async function createFileTreeEntry(
|
||||
rootPath: string,
|
||||
path: string,
|
||||
name: string,
|
||||
kind: "file" | "dir"
|
||||
): Promise<string> {
|
||||
return invoke("create_file_tree_entry", { rootPath, path, name, kind })
|
||||
}
|
||||
|
||||
export async function gitLog(
|
||||
path: string,
|
||||
limit?: number,
|
||||
|
||||
Reference in New Issue
Block a user