diff --git a/app/src/boot/globalShortcut.ts b/app/src/boot/globalShortcut.ts
index 48acc4098..ce54aaffa 100644
--- a/app/src/boot/globalShortcut.ts
+++ b/app/src/boot/globalShortcut.ts
@@ -76,7 +76,7 @@ const switchDialogEvent = (event: MouseEvent, switchDialog: Dialog) => {
if (currentType === "riffCard") {
openCard();
} else {
- getDockByType(currentType as TDockType).toggleModel(currentType as TDockType, true);
+ getDockByType(currentType).toggleModel(currentType, true);
}
} else {
const currentId = target.getAttribute("data-id");
@@ -369,7 +369,7 @@ export const globalShortcut = (app: App) => {
if (currentType === "riffCard") {
openCard();
} else {
- getDockByType(currentType as TDockType).toggleModel(currentType as TDockType, true);
+ getDockByType(currentType).toggleModel(currentType, true);
}
if (document.activeElement) {
(document.activeElement as HTMLElement).blur();
@@ -492,8 +492,8 @@ export const globalShortcut = (app: App) => {
getAllDocks().forEach((item, index) => {
dockHtml += `
- ${window.siyuan.languages[item.hotkeyLangId]}
- ${updateHotkeyTip(window.siyuan.config.keymap.general[item.hotkeyLangId].custom)}
+ ${item.title}
+ ${updateHotkeyTip(item.hotkey || "")}
`;
});
dockHtml = dockHtml + "";
@@ -623,7 +623,7 @@ export const globalShortcut = (app: App) => {
return;
}
const matchDock = getAllDocks().find(item => {
- if (matchHotKey(window.siyuan.config.keymap.general[item.hotkeyLangId].custom, event)) {
+ if (matchHotKey(item.hotkey, event)) {
getDockByType(item.type).toggleModel(item.type);
if (document.activeElement) {
(document.activeElement as HTMLElement).blur();
@@ -751,15 +751,15 @@ export const globalShortcut = (app: App) => {
event.preventDefault();
let activeTabElement = document.querySelector(".layout__tab--active");
if (activeTabElement && activeTabElement.getBoundingClientRect().width > 0) {
- let type: TDockType;
+ let type = "";
Array.from(activeTabElement.classList).find(item => {
if (item.startsWith("sy__")) {
- type = item.replace("sy__", "") as TDockType;
+ type = item.replace("sy__", "");
return true;
}
});
if (type) {
- getDockByType(type).toggleModel(type, false, true);
+ getDockByType(type)?.toggleModel(type, false, true);
}
return;
}
@@ -932,7 +932,7 @@ const dialogArrow = (element: HTMLElement, event: KeyboardEvent) => {
if (currentType === "riffCard") {
openCard();
} else {
- getDockByType(currentType as TDockType).toggleModel(currentType as TDockType, true);
+ getDockByType(currentType).toggleModel(currentType, true);
}
} else {
openFileById({
diff --git a/app/src/business/openRecentDocs.ts b/app/src/business/openRecentDocs.ts
index 9fc6a2ba1..c56e0fe77 100644
--- a/app/src/business/openRecentDocs.ts
+++ b/app/src/business/openRecentDocs.ts
@@ -33,8 +33,8 @@ ${unicode2Emoji(item.icon || Constants.SIYUAN_IMAGE_FILE, false, "b3-list-item__
getAllDocks().forEach((item, index) => {
dockHtml += `
- ${window.siyuan.languages[item.hotkeyLangId]}
- ${updateHotkeyTip(window.siyuan.config.keymap.general[item.hotkeyLangId].custom)}
+ ${item.title}
+ ${updateHotkeyTip(item.hotkey || "")}
`;
});
dockHtml = dockHtml + "";
diff --git a/app/src/card/newCardTab.ts b/app/src/card/newCardTab.ts
index ad16398f4..a8d8e8982 100644
--- a/app/src/card/newCardTab.ts
+++ b/app/src/card/newCardTab.ts
@@ -3,6 +3,7 @@ import {Custom} from "../layout/dock/Custom";
import {bindCardEvent, genCardHTML} from "./openCard";
import {fetchPost} from "../util/fetch";
import {Protyle} from "../protyle";
+import {setPanelFocus} from "../layout/util";
export const newCardModel = (options: {
tab: Tab,
@@ -13,7 +14,7 @@ export const newCardModel = (options: {
}
}) => {
let editor: Protyle;
- const custom = new Custom({
+ const customObj = new Custom({
type: "siyuan-card",
tab: options.tab,
data: options.data,
@@ -66,5 +67,8 @@ export const newCardModel = (options: {
});
}
});
- return custom;
+ customObj.element.addEventListener("click", () => {
+ setPanelFocus(customObj.element.parentElement.parentElement);
+ });
+ return customObj;
};
diff --git a/app/src/layout/dock/Backlink.ts b/app/src/layout/dock/Backlink.ts
index 95c8ced76..edf96668f 100644
--- a/app/src/layout/dock/Backlink.ts
+++ b/app/src/layout/dock/Backlink.ts
@@ -325,10 +325,6 @@ export class Backlink extends Model {
});
this.searchBacklinks(true);
-
- if (this.type === "pin") {
- setPanelFocus(this.element);
- }
}
private setFocus() {
diff --git a/app/src/layout/dock/Bookmark.ts b/app/src/layout/dock/Bookmark.ts
index e540ae7ef..2d54983e7 100644
--- a/app/src/layout/dock/Bookmark.ts
+++ b/app/src/layout/dock/Bookmark.ts
@@ -146,7 +146,6 @@ export class Bookmark extends Model {
});
this.update();
- setPanelFocus(this.element);
}
public update() {
diff --git a/app/src/layout/dock/Custom.ts b/app/src/layout/dock/Custom.ts
index b01a87e84..e5c7bfde5 100644
--- a/app/src/layout/dock/Custom.ts
+++ b/app/src/layout/dock/Custom.ts
@@ -1,9 +1,8 @@
import {Tab} from "../Tab";
-import {setPanelFocus} from "../util";
import {Model} from "../Model";
export class Custom extends Model {
- private element: Element;
+ public element: Element;
public data: any;
public type: string;
public init: () => void;
@@ -27,9 +26,6 @@ export class Custom extends Model {
}
this.element = options.tab.panelElement;
this.data = options.data;
- this.element.addEventListener("click", () => {
- setPanelFocus(this.element.parentElement.parentElement);
- });
this.init = options.init;
this.destroy = options.destroy;
this.resize = options.resize;
diff --git a/app/src/layout/dock/Files.ts b/app/src/layout/dock/Files.ts
index 972ff6162..2e2ea03e4 100644
--- a/app/src/layout/dock/Files.ts
+++ b/app/src/layout/dock/Files.ts
@@ -602,7 +602,6 @@ export class Files extends Model {
newElement.classList.remove("dragover", "dragover__bottom", "dragover__top");
});
this.init();
- setPanelFocus(this.element.parentElement);
if (window.siyuan.config.openHelp) {
// 需等待链接建立,不能放在 ongetconfig 中
mountHelp();
diff --git a/app/src/layout/dock/Graph.ts b/app/src/layout/dock/Graph.ts
index b0cd5a32a..4b1d8ce25 100644
--- a/app/src/layout/dock/Graph.ts
+++ b/app/src/layout/dock/Graph.ts
@@ -354,9 +354,6 @@ export class Graph extends Model {
});
});
this.searchGraph(options.type !== "global");
- if (this.type !== "local") {
- setPanelFocus(this.element);
- }
}
private reset(conf: IGraphCommon & ({ dailyNote: boolean } | { minRefs: number, dailyNote: boolean })) {
diff --git a/app/src/layout/dock/Inbox.ts b/app/src/layout/dock/Inbox.ts
index 63bbd7e85..d2e990380 100644
--- a/app/src/layout/dock/Inbox.ts
+++ b/app/src/layout/dock/Inbox.ts
@@ -163,9 +163,6 @@ export class Inbox extends Model {
}
});
this.update();
- /// #if !MOBILE
- setPanelFocus(this.element);
- /// #endif
}
private back() {
diff --git a/app/src/layout/dock/Outline.ts b/app/src/layout/dock/Outline.ts
index 70c3cf787..6b3d7ca92 100644
--- a/app/src/layout/dock/Outline.ts
+++ b/app/src/layout/dock/Outline.ts
@@ -169,10 +169,6 @@ export class Outline extends Model {
}, response => {
this.update(response);
});
-
- if (this.type === "pin") {
- setPanelFocus(options.tab.panelElement);
- }
}
public updateDocTitle(ial?: IObject) {
diff --git a/app/src/layout/dock/Tag.ts b/app/src/layout/dock/Tag.ts
index 4ce255934..8bcb3e9b0 100644
--- a/app/src/layout/dock/Tag.ts
+++ b/app/src/layout/dock/Tag.ts
@@ -181,7 +181,6 @@ export class Tag extends Model {
}
});
this.update();
- setPanelFocus(this.element);
}
public update() {
diff --git a/app/src/layout/dock/index.ts b/app/src/layout/dock/index.ts
index c7e837701..e4f5d2b74 100644
--- a/app/src/layout/dock/index.ts
+++ b/app/src/layout/dock/index.ts
@@ -15,16 +15,26 @@ import {Protyle} from "../../protyle";
import {Backlink} from "./Backlink";
import {resetFloatDockSize} from "./util";
import {hasClosestByClassName} from "../../protyle/util/hasClosest";
+import {App} from "../../index";
+import {Plugin} from "../../plugin";
export class Dock {
public element: HTMLElement;
public layout: Layout;
private position: TDockPosition;
+ private app: App;
public resizeElement: HTMLElement;
public pin = true;
public data: { [key: string]: Model | boolean };
- constructor(options: { data: { pin: boolean, data: IDockTab[][] }, position: TDockPosition }) {
+ constructor(options: {
+ app: App,
+ data: {
+ pin: boolean,
+ data: IDockTab[][]
+ },
+ position: TDockPosition
+ }) {
switch (options.position) {
case "Left":
this.layout = window.siyuan.layout.layout.children[0].children[0] as Layout;
@@ -45,6 +55,7 @@ export class Dock {
this.layout.element.insertAdjacentHTML("beforeend", "");
break;
}
+ this.app = options.app;
this.element = document.getElementById("dock" + options.position);
const dockClass = options.position === "Bottom" ? ' class="fn__flex"' : "";
this.element.innerHTML = ``;
@@ -77,13 +88,13 @@ export class Dock {
this.resizeElement.classList.add("fn__none");
} else {
activeElements.forEach(item => {
- this.toggleModel(item.getAttribute("data-type") as TDockType, true);
+ this.toggleModel(item.getAttribute("data-type"), true);
});
}
this.element.addEventListener("click", (event) => {
let target = event.target as HTMLElement;
while (target && !target.isEqualNode(this.element)) {
- const type = target.getAttribute("data-type") as TDockType;
+ const type = target.getAttribute("data-type");
if (type) {
this.toggleModel(type, false, true);
event.preventDefault();
@@ -256,7 +267,7 @@ export class Dock {
this.layout.element.querySelector(".layout__tab--active")?.classList.remove("layout__tab--active");
}
- public toggleModel(type: TDockType, show = false, close = false) {
+ public toggleModel(type: string, show = false, close = false) {
if (!type) {
return;
}
@@ -389,10 +400,27 @@ export class Dock {
}
});
break;
+ default:
+ tab = new Tab({
+ callback: (tab: Tab) => {
+ let customModel;
+ this.app.plugins.find((item: Plugin) => {
+ if (item.docks[type]) {
+ customModel = item.docks[type].model({tab});
+ return true;
+ }
+ });
+ if (customModel) {
+ tab.addModel(customModel);
+ }
+ }
+ });
+ break;
}
wnd.addTab(tab);
target.setAttribute("data-id", tab.id);
this.data[type] = tab.model;
+ setPanelFocus(tab.panelElement);
} else {
// tab 切换
Array.from(wnd.element.querySelector(".layout-tab-container").children).forEach(item => {
@@ -482,7 +510,7 @@ export class Dock {
public add(index: number, sourceElement: Element) {
sourceElement.setAttribute("data-height", "");
sourceElement.setAttribute("data-width", "");
- const type = sourceElement.getAttribute("data-type") as TDockType;
+ const type = sourceElement.getAttribute("data-type");
const sourceDock = getDockByType(type);
if (sourceDock.element.querySelectorAll(".dock__item").length === 2) {
sourceDock.element.classList.add("fn__none");
@@ -569,7 +597,7 @@ export class Dock {
private genButton(data: IDockTab[], index: number) {
let html = "";
data.forEach(item => {
- html += `
+ html += `
`;
this.data[item.type] = true;
diff --git a/app/src/layout/status.ts b/app/src/layout/status.ts
index d63c2462b..c15837b4f 100644
--- a/app/src/layout/status.ts
+++ b/app/src/layout/status.ts
@@ -126,7 +126,7 @@ export const initStatus = (isWindow = false) => {
event.stopPropagation();
break;
} else if (target.classList.contains("b3-menu__item")) {
- const type = target.getAttribute("data-type") as TDockType;
+ const type = target.getAttribute("data-type");
getDockByType(type).toggleModel(type);
if (type === "file" && getSelection().rangeCount > 0) {
const range = getSelection().getRangeAt(0);
diff --git a/app/src/layout/util.ts b/app/src/layout/util.ts
index 97d466e41..27c636e97 100644
--- a/app/src/layout/util.ts
+++ b/app/src/layout/util.ts
@@ -55,9 +55,9 @@ export const setPanelFocus = (element: Element) => {
element.classList.add("layout__wnd--active");
} else {
element.classList.add("layout__tab--active");
- ["file", "inbox", "backlink", "tag", "bookmark", "graph", "globalGraph", "outline"].find(item => {
- if (element.classList.contains("sy__" + item)) {
- document.querySelector(`.dock__item[data-type="${item}"]`).classList.add("dock__item--activefocus");
+ Array.from(element.classList).find(item => {
+ if (item.startsWith("sy__")) {
+ document.querySelector(`.dock__item[data-type="${item.substring(4)}"]`).classList.add("dock__item--activefocus");
return true;
}
});
@@ -71,7 +71,7 @@ export const setPanelFocus = (element: Element) => {
}
};
-export const getDockByType = (type: TDockType) => {
+export const getDockByType = (type: string) => {
if (!window.siyuan.layout.leftDock) {
return undefined;
}
@@ -154,14 +154,16 @@ const dockToJSON = (dock: Dock) => {
const data: IDockTab[] = [];
dock.element.querySelectorAll(`span[data-index="${index}"]`).forEach(item => {
data.push({
- type: item.getAttribute("data-type") as TDockType,
+ type: item.getAttribute("data-type"),
size: {
height: parseInt(item.getAttribute("data-height")),
width: parseInt(item.getAttribute("data-width")),
},
+ title: item.getAttribute("data-title"),
show: item.classList.contains("dock__item--active"),
icon: item.querySelector("use").getAttribute("xlink:href").substring(1),
- hotkeyLangId: item.getAttribute("data-hotkeylangid")
+ hotkey: item.getAttribute("data-hotkey") || "",
+ hotkeyLangId: item.getAttribute("data-hotkeyLangId") || ""
});
});
return data;
@@ -237,11 +239,56 @@ export const exportLayout = (options: {
});
};
-const JSONToDock = (json: any) => {
+const pushPluginDock = (app: App, dockItem: IDockTab[], position: TPluginDockPosition) => {
+ const needPushData: { [key: string]: IPluginDockTab } = {}
+ app.plugins.forEach((pluginItem) => {
+ let isExist = false;
+ dockItem.forEach(existSubItem => {
+ if (Object.keys(pluginItem.docks).includes(existSubItem.type)) {
+ isExist = true;
+ }
+ })
+ if (!isExist) {
+ Object.keys(pluginItem.docks).forEach(pluginDockKey => {
+ if (pluginItem.docks[pluginDockKey].config.position === position) {
+ needPushData[pluginDockKey] = pluginItem.docks[pluginDockKey].config;
+ }
+ })
+ }
+ })
+ dockItem.forEach(existSubItem => {
+ if (existSubItem.hotkeyLangId) {
+ existSubItem.title = window.siyuan.languages[existSubItem.hotkeyLangId]
+ existSubItem.hotkey = window.siyuan.config.keymap.general[existSubItem.hotkeyLangId].custom
+ }
+ })
+ Object.keys(needPushData).forEach(key => {
+ const item = needPushData[key];
+ dockItem.push({
+ type: key,
+ size: item.size,
+ show: false,
+ icon: item.icon,
+ hotkey: item.hotkey || "",
+ title: item.title,
+ });
+ })
+}
+
+const JSONToDock = (json: any, app: App) => {
+ json.left.data.forEach((existItem: IDockTab[], index: number) => {
+ pushPluginDock(app, existItem, index === 0 ? "LeftTop" : "LeftBottom");
+ });
+ json.right.data.forEach((existItem: IDockTab[], index: number) => {
+ pushPluginDock(app, existItem, index === 0 ? "RightTop" : "RightBottom");
+ });
+ json.bottom.data.forEach((existItem: IDockTab[], index: number) => {
+ pushPluginDock(app, existItem, index === 0 ? "BottomLeft" : "BottomRight");
+ });
window.siyuan.layout.centerLayout = window.siyuan.layout.layout.children[0].children[1] as Layout;
- window.siyuan.layout.leftDock = new Dock({position: "Left", data: json.left});
- window.siyuan.layout.rightDock = new Dock({position: "Right", data: json.right});
- window.siyuan.layout.bottomDock = new Dock({position: "Bottom", data: json.bottom});
+ window.siyuan.layout.leftDock = new Dock({position: "Left", data: json.left, app});
+ window.siyuan.layout.rightDock = new Dock({position: "Right", data: json.right, app});
+ window.siyuan.layout.bottomDock = new Dock({position: "Bottom", data: json.bottom, app});
};
export const JSONToCenter = (app: App, json: ILayoutJSON, layout?: Layout | Wnd | Tab | Model, isStart = false) => {
@@ -387,7 +434,7 @@ export const JSONToCenter = (app: App, json: ILayoutJSON, layout?: Layout | Wnd
export const JSONToLayout = (app: App, isStart: boolean) => {
JSONToCenter(app, window.siyuan.config.uiLayout.layout, undefined, isStart);
- JSONToDock(window.siyuan.config.uiLayout);
+ JSONToDock(window.siyuan.config.uiLayout, app);
// 启动时不打开页签,需要移除没有钉住的页签
if (window.siyuan.config.fileTree.closeTabsOnStart && isStart) {
getAllTabs().forEach(item => {
diff --git a/app/src/menus/workspace.ts b/app/src/menus/workspace.ts
index fcc03d3c3..6e99fc3f3 100644
--- a/app/src/menus/workspace.ts
+++ b/app/src/menus/workspace.ts
@@ -58,8 +58,8 @@ export const workspaceMenu = (app:App, rect: DOMRect) => {
getAllDocks().forEach(item => {
dockMenu.push({
icon: item.icon,
- accelerator: window.siyuan.config.keymap.general[item.hotkeyLangId].custom,
- label: window.siyuan.languages[item.hotkeyLangId],
+ accelerator: item.hotkey,
+ label: item.title,
click() {
getDockByType(item.type).toggleModel(item.type);
}
diff --git a/app/src/plugin/API.ts b/app/src/plugin/API.ts
index 1a85b77da..ea28b232d 100644
--- a/app/src/plugin/API.ts
+++ b/app/src/plugin/API.ts
@@ -9,6 +9,7 @@ import {isMobile} from "../util/functions";
/// #if !MOBILE
import {openFile} from "../editor/util";
/// #endif
+import {updateHotkeyTip} from "../protyle/util/compatibility";
export class Menu {
private menu: SiyuanMenu;
@@ -82,6 +83,7 @@ openTab = openFile;
export const API = {
confirm: confirmDialog,
showMessage,
+ adaptHotkey: updateHotkeyTip,
fetchPost,
fetchSyncPost,
fetchGet,
diff --git a/app/src/plugin/index.ts b/app/src/plugin/index.ts
index 935d4b778..dd4b88e45 100644
--- a/app/src/plugin/index.ts
+++ b/app/src/plugin/index.ts
@@ -6,6 +6,8 @@ import {isMobile, isWindow} from "../util/functions";
import {Custom} from "../layout/dock/Custom";
/// #endif
import {Tab} from "../layout/Tab";
+import {getDockByType, setPanelFocus} from "../layout/util";
+import {hasClosestByAttribute} from "../protyle/util/hasClosest";
export class Plugin {
public i18n: IObject;
@@ -17,6 +19,14 @@ export class Plugin {
[key: string]: (options: { tab: Tab, data: any }) => Custom
/// #endif
} = {};
+ public docks: {
+ /// #if !MOBILE
+ [key: string]: {
+ config: IPluginDockTab,
+ model: (options: { tab: Tab }) => Custom
+ }
+ /// #endif
+ } = {};
constructor(options: {
app: App,
@@ -99,7 +109,7 @@ export class Plugin {
});
}
- public createTab(options: {
+ public addTab(options: {
type: string,
destroy?: () => void,
resize?: () => void,
@@ -108,16 +118,59 @@ export class Plugin {
}) {
/// #if !MOBILE
const type2 = this.name + options.type;
- this.models[type2] = (arg: { data: any, tab: Tab }) => new Custom({
- tab: arg.tab,
- type: type2,
- data: arg.data,
- init: options.init,
- destroy: options.destroy,
- resize: options.resize,
- update: options.update,
- });
+ this.models[type2] = (arg: { data: any, tab: Tab }) => {
+ const customObj = new Custom({
+ tab: arg.tab,
+ type: type2,
+ data: arg.data,
+ init: options.init,
+ destroy: options.destroy,
+ resize: options.resize,
+ update: options.update,
+ });
+ customObj.element.addEventListener("click", () => {
+ setPanelFocus(customObj.element.parentElement.parentElement);
+ });
+ return customObj;
+ };
return this.models[type2];
/// #endif
}
+
+ public addDock(options: {
+ config: IPluginDockTab,
+ data: any,
+ type: string,
+ destroy?: () => void,
+ resize?: () => void,
+ update?: () => void,
+ init: () => void
+ }) {
+ /// #if !MOBILE
+ const type2 = this.name + options.type;
+ this.docks[type2] = {
+ config: options.config,
+ model: (arg: { tab: Tab }) => {
+ const customObj = new Custom({
+ tab: arg.tab,
+ type: type2,
+ data: options.data,
+ init: options.init,
+ destroy: options.destroy,
+ resize: options.resize,
+ update: options.update,
+ })
+ customObj.element.addEventListener("click", (event: MouseEvent) => {
+ setPanelFocus(customObj.element);
+ if (hasClosestByAttribute(event.target as HTMLElement, "data-type", "min")) {
+ getDockByType(type2).toggleModel(type2);
+ }
+ });
+ customObj.element.classList.add("sy__" + type2);
+ return customObj
+ }
+ };
+ return this.docks[type2];
+ /// #endif
+ }
}
diff --git a/app/src/types/index.d.ts b/app/src/types/index.d.ts
index b019dc669..2868ea487 100644
--- a/app/src/types/index.d.ts
+++ b/app/src/types/index.d.ts
@@ -2,16 +2,7 @@ type TLayout = "normal" | "bottom" | "left" | "right" | "center"
type TSearchFilter = "mathBlock" | "table" | "blockquote" | "superBlock" | "paragraph" | "document" | "heading"
| "list" | "listItem" | "codeBlock" | "htmlBlock"
type TDirection = "lr" | "tb"
-type TDockType =
- "file"
- | "outline"
- | "bookmark"
- | "tag"
- | "graph"
- | "globalGraph"
- | "backlink"
- | "backlinkOld"
- | "inbox"
+type TPluginDockPosition = "LeftTop" | "LeftBottom" | "RightTop" | "RightBottom" | "BottomLeft" | "BottomRight"
type TDockPosition = "Left" | "Right" | "Bottom"
type TWS = "main" | "filetree" | "protyle"
type TEditorMode = "preview" | "wysiwyg"
@@ -39,7 +30,7 @@ interface Window {
dataLayer: any[]
siyuan: ISiyuan
webkit: any
- html2canvas: (element: Element, opitons: {useCORS: boolean}) => Promise;
+ html2canvas: (element: Element, opitons: { useCORS: boolean }) => Promise;
JSAndroid: {
returnDesktop(): void
openExternal(url: string): void
@@ -298,11 +289,21 @@ declare interface ILayoutJSON extends ILayoutOptions {
}
declare interface IDockTab {
- type: TDockType;
+ type: string;
size: { width: number, height: number }
show: boolean
icon: string
- hotkeyLangId: string
+ title: string
+ hotkey?: string
+ hotkeyLangId?: string // 常量中无法存变量
+}
+
+declare interface IPluginDockTab {
+ position: TPluginDockPosition,
+ size: { width: number, height: number },
+ icon: string,
+ hotkey?: string,
+ title: string,
}
declare interface IOpenFileOptions {