Skip to content

Commit

Permalink
feat(monaco-editor): 新增添加/另存为菜单项 | Add add/save as menu item.
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuoqiu-Yingyi committed Jul 25, 2023
1 parent d970b3f commit 8c1b57b
Show file tree
Hide file tree
Showing 5 changed files with 227 additions and 26 deletions.
16 changes: 16 additions & 0 deletions public/i18n/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,9 @@
}
},
"menu": {
"add": {
"label": "添加"
},
"confirm": {
"placeholder": "The full path to the resource",
"text": "Warning: You are operating on a protected resource ${1} !<br/>Your subsequent activities may lead to data loss or damage!<br/><br/>If you want to continue the operation, please enter the complete path of the resource ${2} in the text box below",
Expand Down Expand Up @@ -429,6 +432,19 @@
"revealInExplorer": {
"label": "Reveal In Explorer"
},
"saveAs": {
"label": "Save As"
},
"saveFileAs": {
"label": "Save File As",
"message": "File ${1} has saved to ${2}, does you reveal it in explorer?",
"title": "File ${1} save as"
},
"saveFolderAs": {
"label": "Save Folder As",
"message": "Folder ${1} has saved to ${2}, does you reveal it in explorer?",
"title": "Folder ${1} save as"
},
"standard": {
"accelerator": "Standard"
},
Expand Down
13 changes: 13 additions & 0 deletions public/i18n/zh_CHT.json
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,19 @@
"revealInExplorer": {
"label": "在檔案總管中顯示"
},
"saveAs": {
"label": "另存為"
},
"saveFileAs": {
"label": "檔案另存為",
"message": "檔案 ${1} 已另存至 ${2},是否在檔案資源管理器中查看?",
"title": "檔案 ${1} 另存為"
},
"saveFolderAs": {
"label": "資料夾另存為",
"message": "資料夾 ${1} 已另存至 ${2},是否在檔案資源管理器中查看?",
"title": "資料夾 ${1} 另存為"
},
"standard": {
"accelerator": "標準"
},
Expand Down
24 changes: 24 additions & 0 deletions public/i18n/zh_CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,17 @@
}
},
"menu": {
"add": {
"label": "添加"
},
"addFile": {
"label": "添加文件",
"title": "添加文件至 ${1}"
},
"addFolder": {
"label": "添加文件夹",
"title": "添加文件夹至 ${1}"
},
"confirm": {
"placeholder": "资源完整路径",
"text": "警告:您正在操作受保护的资源 ${1} !<br/>您之后的活动可能导致数据丢失或损坏!<br/><br/>若继续操作,请在下方文本框中输入该资源的完整路径 ${2}",
Expand Down Expand Up @@ -429,6 +440,19 @@
"revealInExplorer": {
"label": "在文件资源管理器中显示"
},
"saveAs": {
"label": "另存为"
},
"saveFileAs": {
"label": "文件另存为",
"message": "文件 ${1} 已另存至 ${2},是否在文件资源管理器中查看?",
"title": "文件 ${1} 另存为"
},
"saveFolderAs": {
"label": "文件夹另存为",
"message": "文件夹 ${1} 已另存至 ${2},是否在文件资源管理器中查看?",
"title": "文件夹 ${1} 另存为"
},
"standard": {
"accelerator": "标准"
},
Expand Down
2 changes: 1 addition & 1 deletion src/configs/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export const DEFAULT_CONFIG: IConfig = {
},
explorer: {
enable: true,
safe: true,
safe: false,
permission: {
protected: {
enable: true,
Expand Down
198 changes: 173 additions & 25 deletions src/explorer/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ import type MonacoEditorPlugin from "@/index";
import { FileTreeNodeType, type IFileTreeNodeStores } from "@workspace/components/siyuan/tree/file";
import { get } from "svelte/store";
import { HandlerType } from "@/facades/facade";
import { FLAG_ELECTRON } from "@workspace/utils/env/front-end";
import { FLAG_BROWSER, FLAG_ELECTRON } from "@workspace/utils/env/front-end";
import { copyText } from "@workspace/utils/misc/copy";
import { isStaticWebFileServicePath, workspacePath2StaticPathname } from "@workspace/utils/siyuan/url";
import { ExplorerIcon } from "./icon";
import { Explorer, ProtectedResourceType } from ".";
import { extname, join } from "@workspace/utils/path/browserify";
import { extname, join, parse } from "@workspace/utils/path/browserify";
import {
fn__code,
ft__error,
Expand All @@ -34,6 +34,13 @@ import {
import { prompt } from "@workspace/components/siyuan/dialog/prompt";
import { isValidName } from "@workspace/utils/file/filename";
import { ResourceOption, isResourceOperable } from "@/utils/permission";
import {
openPath,
showItemInFolder,
} from "@workspace/utils/electron/shell";
import { showOpenDialog, showSaveDialog } from "@workspace/utils/electron/dialog";
import { cp } from "@workspace/utils/node/fs/promises";
import { normalize } from "@workspace/utils/path/normalize";

/* 菜单项类型 */
export enum MenuItemType {
Expand Down Expand Up @@ -182,6 +189,10 @@ export class ExplorerContextMenu {
: null;
const accessible = isStaticWebFileServicePath(relative); // 是否位于静态 web 文件目录下

const root = type === FileTreeNodeType.Root; // 是否为根目录
const file = type === FileTreeNodeType.File; // 是否为文件
const folder = type === FileTreeNodeType.Folder; // 是否为文件夹

const items: IMenuItem[] = [];

/* 新建 */
Expand Down Expand Up @@ -371,20 +382,10 @@ export class ExplorerContextMenu {
label: this.i18n.menu.openWithDefaultProgram.label,
click: () => {
if (type === FileTreeNodeType.File) {
globalThis
.require("electron")
.shell
.openPath(path);
openPath(path);
}
else {
globalThis
.require("electron")
.shell
.showItemInFolder(
globalThis
.require("path")
.normalize(path)
);
showItemInFolder(path);
}
},
},
Expand Down Expand Up @@ -412,14 +413,7 @@ export class ExplorerContextMenu {
icon: "iconFolder",
label: this.i18n.menu.revealInExplorer.label,
click: () => {
globalThis
.require("electron")
.shell
.showItemInFolder(
globalThis
.require("path")
.normalize(path)
);
showItemInFolder(path);
},
},
root: true,
Expand Down Expand Up @@ -573,11 +567,165 @@ export class ExplorerContextMenu {
file: true,
});

// TODO: 另存为
if (FLAG_ELECTRON) {
/**
* 添加文件/文件夹
* REF: https://www.electronjs.org/zh/docs/latest/api/dialog#dialogshowopendialogbrowserwindow-options
*/
items.push({
type: MenuItemType.Submenu,
options: {
icon: "iconUpload",
label: this.i18n.menu.add.label,
},
submenu: [
/* 添加文件 */
{
type: MenuItemType.Action,
options: {
icon: "iconFile",
label: this.i18n.menu.addFile.label,
click: async () => {
const result = await showOpenDialog({
title: i10n_save_as.title.replaceAll("${1}", relative),
buttonLabel: this.i18n.menu.add.label,
properties: [
"openFile",
"multiSelections",
"showHiddenFiles",
"createDirectory",
"treatPackageAsDirectory",
],
});
if (!result.canceled && result.filePaths) {
// this.plugin.logger.debugs(path, result.filePaths);
for (const filePath of result.filePaths) {
const info = parse(normalize(filePath));
// this.plugin.logger.debugs(info);
await cp(
filePath,
join(path, info.base),
);
}
await this.explorer.updateNode(node);
}
},
},
root: true,
folder: true,
file: false,
},
/* 添加文件夹 */
{
type: MenuItemType.Action,
options: {
icon: "iconFolder",
label: this.i18n.menu.addFolder.label,
click: async () => {
const result = await showOpenDialog({
title: i10n_save_as.title.replaceAll("${1}", relative),
buttonLabel: this.i18n.menu.add.label,
properties: [
"openDirectory",
"multiSelections",
"showHiddenFiles",
"createDirectory",
"treatPackageAsDirectory",
],
});
if (!result.canceled && result.filePaths) {
// this.plugin.logger.debug(result.filePaths);
for (const filePath of result.filePaths) {
const info = parse(normalize(filePath));
// this.plugin.logger.debugs(info);
await cp(
filePath,
join(path, info.base),
{
recursive: true,
},
);
}
await this.explorer.updateNode(node);
}
},
},
root: true,
folder: true,
file: false,
},
],
root: true,
folder: true,
file: false,
});

// TODO: 下载
/**
* 文件/文件夹另存为
* REF: https://www.electronjs.org/zh/docs/latest/api/dialog#dialogshowsavedialogbrowserwindow-options
*/
const i10n_save_as = file
? this.i18n.menu.saveFileAs
: this.i18n.menu.saveFolderAs;
items.push({
type: MenuItemType.Action,
options: {
icon: "iconDownload",
label: this.i18n.menu.saveAs.label,
click: async () => {
const asyncFs = globalThis.require("fs/promises") as typeof import("fs/promises");
const result = await showSaveDialog({
title: i10n_save_as.title.replaceAll("${1}", relative),
defaultPath: name,
properties: [
"showHiddenFiles",
"createDirectory",
"treatPackageAsDirectory",
"showOverwriteConfirmation",
],
});
if (!result.canceled && result.filePath) {
// this.plugin.logger.debugs(path, result.filePath);
await asyncFs.cp(
path,
result.filePath,
{
recursive: true, // 递归复制
},
);
this.plugin.siyuan.confirm(
i10n_save_as.label,
i10n_save_as.message
.replaceAll("${1}", fn__code(relative))
.replaceAll("${2}", fn__code(result.filePath)),
() => {
showItemInFolder(result.filePath);
},
)
}
},
},
root: false,
folder: true,
file: true,
});
}
else if (FLAG_BROWSER) {
/**
* TODO: 上传文件/文件夹
* REF: https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLInputElement/webkitdirectory
* REF: https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/webkitEntries
*/
// TODO: 下载文件 (StreamSaver.js)
// TODO: 下载目录 (打包为 zip)
}

// TODO: 上传
items.push({
type: MenuItemType.Separator,
root: true,
folder: true,
file: true,
});

/* 重命名 */
items.push({
Expand Down

0 comments on commit 8c1b57b

Please sign in to comment.