@setoelkahfi / svara / commits / 8daf27b

feat: added copy/paste files

Signed-off-by: mellobacon <mellodev@outlook.com>

mellobacon committed Apr 15, 2024 at 10:27 UTC 8daf27b4ec6648cc9ec91f496ddbea1a65fa4a6f
4 files changed +45 -14
src/lib/File.ts
+35 -1
@@ -1,4 +1,4 @@
1 -import { dialog, fs, path, invoke, window } from "@tauri-apps/api";
1 +import { dialog, fs, path, invoke, window, clipboard } from "@tauri-apps/api";
2 import { get, writable } from 'svelte/store';
3 import { tabs, addEditorTab, renameTab, closeTab, refreshTabs } from "./EditorTabList.svelte";
4 import { filetree } from "./FileTree.svelte";
@@ -6,6 +6,7 @@ import { watchImmediate } from "tauri-plugin-fs-watch-api";
6 import { openFileTree } from "./Sidebar.svelte";
7 import { info, trace, warn, error } from "tauri-plugin-log-api";
8 import { homeDir } from "@tauri-apps/api/path";
9 +import { appSettings } from "../config/config";
10
11 export async function openFile() {
12 let newPath = await dialog.open() as string;
@@ -262,6 +263,39 @@ export async function renameFile(filename: string, oldpath: string) {
263 return true;
264 }
265
266 +export async function readFile(path) {
267 + let fileData = {text: "", encoding: "UTF-8", extension: "", bom: false, spaces: await appSettings.get("editor.tabSize")};
268 + try {
269 + fileData = await invoke("read_file", {path: path});
270 + if (fileData.spaces === 0) {
271 + fileData.spaces = await appSettings.get("editor.tabSize")
272 + }
273 + } catch (error) {
274 + warn(`Can't read file content in ${path}. Setting to empty string. Error: ${error}`, {file: "Tab.ts", line: 79});
275 + }
276 + return fileData;
277 +}
278 +
279 +export async function pasteFile(dest) {
280 + const copied = await clipboard.readText();
281 + const filename = copied.split(path.sep).pop();
282 + if (!await fs.exists(copied) || await fs.exists(`${dest}${path.sep}${filename}`))
283 + return
284 + const fileData = await readFile(copied);
285 +
286 + if (dest === copied) return;
287 +
288 + if (!await dialog.confirm(`Are you sure you want to copy "${filename}" from "./${copied.split(path.sep).pop()}" into "./${dest.split(path.sep).pop()}?"`, {title: "Nucleus: Move File"})) {
289 + return;
290 + }
291 + try {
292 + await invoke("write_file", {path: dest, content: fileData.text, enc: fileData.encoding, hasBom: fileData.bom, spaces: fileData.spaces});
293 + } catch (e) {
294 + error(`Cannot create file in path ${dest}. Error: ${e}`, {file: "File.ts", line: 287});
295 + }
296 + addEditorTab(dest, filename);
297 +}
298 +
299 export function checkValidFileName(input: string) {
300 // refer to https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file for invalid characters
301 // also https://gist.github.com/doctaphred/d01d05291546186941e1b7ddc02034d3
src/lib/FileTree.svelte
+4 -5
@@ -2,7 +2,7 @@
2 import FileTreeView from "./FileTree/FileTreeView.svelte";
3 import ContextMenu from "./utility/ContextMenu.svelte";
4 import { addEditorTab } from "./EditorTabList.svelte";
5 - import { openFolder } from "./File";
5 + import { openFolder, pasteFile } from "./File";
6 import { clipboard } from "@tauri-apps/api";
7 import Button from "./utility/Button.svelte";
8 import { commands } from "../config/commands";
@@ -30,11 +30,10 @@
30 {name: "Open in File Explorer", shortcut: "", action: async () => commands.openInExplorer.command(path)},
31 {name: "New Folder...", shortcut: "", action: () => commands.createFolder.command(path)},
32 {name: "New File...", shortcut: "", action: () => {commands.createFile.command(path)}},
33 - {name: "Copy", shortcut: "Ctrl + C", action: () => {console.warn("Feature not implemented yet.")}},
33 + {name: "Copy", shortcut: "Ctrl + C", action: async () => {await clipboard.writeText(path)}},
34 {name: "Cut", disabled: true, shortcut: "Ctrl + X", action: () => {console.warn("Feature not implemented yet.")}},
35 - {name: "Paste", shortcut: "Ctrl + X", disabled: true, action: () => {console.warn("Feature not implemented yet.")}},
35 + {name: "Paste", shortcut: "Ctrl + V", action: async () => {await pasteFile(path)}},
36 {name: "Copy Filename", shortcut: "", action: async () => {await clipboard.writeText(name)}},
37 - {name: "Copy Absolute Path", shortcut: "", action: async () => {await clipboard.writeText(path)}},
37 {name: "Rename...", shortcut: "F2", disabled: true, action: () => {console.warn("Feature not implemented yet.")}},
38 {name: "Delete", disabled: true, shortcut: "Delete", action: () => {console.warn("Feature not implemented yet.")}}
39 ]
@@ -92,4 +91,4 @@
91 font-size: 0.875rem;
92 }
93 }
95 -</style>
\ No newline at end of file
94 +</style>
src/lib/FileTree/FileTreeList.svelte
+4 -5
@@ -10,7 +10,7 @@
10 import Directory from "../../util/icons/Directory.svelte";
11 import {filetree} from "../FileTree.svelte";
12 import ContextMenu from "../utility/ContextMenu.svelte";
13 - import { moveFile, moveToTrash } from "../File";
13 + import { moveFile, moveToTrash, pasteFile } from "../File";
14 import { clipboard } from "@tauri-apps/api";
15 import { onMount } from "svelte";
16 import { commands } from "../../config/commands";
@@ -40,11 +40,10 @@
40 {name: "Open in File Explorer", shortcut: commands.openInExplorer.keybind, action: async () => commands.openInExplorer.command(path)},
41 {name: "New Folder...", shortcut: "", action: () => commands.createFolder.command(path)},
42 {name: "New File...", shortcut: "", action: () => commands.createFile.command(path)},
43 - {name: "Copy", shortcut: "Ctrl + C", action: () => {console.warn("Feature not implemented yet.")}},
43 + {name: "Copy", shortcut: "Ctrl + C", action: async () => {await clipboard.writeText(path)}},
44 {name: "Cut", disabled: isroot, shortcut: "Ctrl + X", action: () => {console.warn("Feature not implemented yet.")}},
45 - {name: "Paste", shortcut: "Ctrl + X", disabled: true, action: () => {console.warn("Feature not implemented yet.")}},
45 + {name: "Paste", shortcut: "Ctrl + V", action: async () => {await pasteFile(path)}},
46 {name: "Copy Filename", shortcut: "", action: async () => {await clipboard.writeText(name)}},
47 - {name: "Copy Absolute Path", shortcut: "", action: async () => {await clipboard.writeText(path)}},
47 {name: "Rename...", disabled: isroot, shortcut: commands.renameFile.keybind, action: () => {commands.renameFile.command(name, path)}},
48 {name: "Delete", disabled: isroot, shortcut: "Delete", action: async () => {await moveToTrash(path)}}
49 ]
@@ -234,4 +233,4 @@
233 .root > .tree-label {
234 font-weight: bold;
235 }
237 -</style>
\ No newline at end of file
236 +</style>
src/lib/FileTree/FileTreeNode.svelte
+2 -3
@@ -39,10 +39,9 @@
39 let contextmenu = false;
40 let contextmenuitems = [
41 {name: "Open in File Explorer", shortcut: commands.openInExplorer.keybind, action: async () => {commands.openInExplorer.command(path)}},
42 - {name: "Copy", shortcut: "Ctrl + C", action: () => {console.warn("Feature not implemented yet.")}},
42 + {name: "Copy", shortcut: "Ctrl + C", action: async () => {await clipboard.writeText(path)}},
43 {name: "Cut", shortcut: "Ctrl + X", action: () => {console.warn("Feature not implemented yet.")}},
44 {name: "Copy Filename", shortcut: "", action: async () => {await clipboard.writeText(name)}},
45 - {name: "Copy Absolute Path", shortcut: "", action: async () => {await clipboard.writeText(path)}},
45 {name: "Edit", shortcut: "", action: () => {addEditorTab(path, name)}},
46 {name: "Rename...", shortcut: commands.renameFile.keybind, action: () => {commands.renameFile.command(name, path)}},
47 {name: "Delete", shortcut: "Delete", action: async () => {await moveToTrash(path)}}
@@ -142,4 +141,4 @@
141 display: flex;
142 margin-right: 15px;
143 }
145 -</style>
\ No newline at end of file
144 +</style>