diff --git a/app/electron/main.js b/app/electron/main.js index 00003a68a..847b39bda 100644 --- a/app/electron/main.js +++ b/app/electron/main.js @@ -884,6 +884,10 @@ app.on('open-url', (event, url) => { // for macOS } }) +app.on('browser-window-created', (_, window) => { + require("@electron/remote/main").enable(window.webContents) +}) + app.on('second-instance', (event, argv) => { writeLog('second-instance [' + argv + ']') let workspace = argv.find((arg) => arg.startsWith('--workspace=')) diff --git a/app/src/config/appearance.ts b/app/src/config/appearance.ts index cd45eaa0f..eb857be72 100644 --- a/app/src/config/appearance.ts +++ b/app/src/config/appearance.ts @@ -277,6 +277,6 @@ export const appearance = { } } loadAssets(data); - document.querySelector("#barMode use").setAttribute("xlink:href", `#icon${window.siyuan.config.appearance.modeOS ? "Mode" : (window.siyuan.config.appearance.mode === 0 ? "Light" : "Dark")}`); + document.querySelector("#barMode use")?.setAttribute("xlink:href", `#icon${window.siyuan.config.appearance.modeOS ? "Mode" : (window.siyuan.config.appearance.mode === 0 ? "Light" : "Dark")}`); } }; diff --git a/app/src/layout/Wnd.ts b/app/src/layout/Wnd.ts index 55e6dde8d..2624c7228 100644 --- a/app/src/layout/Wnd.ts +++ b/app/src/layout/Wnd.ts @@ -29,6 +29,8 @@ import {Asset} from "../asset"; import {newFile} from "../util/newFile"; import {MenuItem} from "../menus/Menu"; import {escapeHtml} from "../util/escape"; +import {isWindow} from "../util/functions"; +import {setTabPosition} from "../window/setHeader"; export class Wnd { public id: string; @@ -319,6 +321,7 @@ export class Wnd { switchWnd(newWnd, targetWnd); } } + setTabPosition(); return; } @@ -370,7 +373,7 @@ export class Wnd { } } }); - if (currentTab) { + if (currentTab && currentTab.headElement) { const initData = currentTab.headElement.getAttribute("data-initdata"); if (initData) { const json = JSON.parse(initData); @@ -495,6 +498,8 @@ export class Wnd { } else if (this.children.length > window.siyuan.config.fileTree.maxOpenTabCount) { this.removeOverCounter(oldFocusIndex); } + + setTabPosition(); } private renderTabList(event: MouseEvent) { @@ -652,6 +657,12 @@ export class Wnd { if (window.siyuan.layout.centerLayout) { const wnd = getWndByLayout(window.siyuan.layout.centerLayout); if (!wnd) { + /// #if !BROWSER + if (isWindow()) { + getCurrentWindow().destroy(); + return; + } + /// #endif const wnd = new Wnd(); window.siyuan.layout.centerLayout.addWnd(wnd); wnd.addTab(newCenterEmptyTab()); diff --git a/app/src/layout/status.ts b/app/src/layout/status.ts index ad11b2add..a57c22d09 100644 --- a/app/src/layout/status.ts +++ b/app/src/layout/status.ts @@ -12,21 +12,25 @@ import {getCurrentWindow} from "@electron/remote"; import {MenuItem} from "../menus/Menu"; import {Constants} from "../constants"; -export const initStatus = () => { +export const initStatus = (isWindow = false) => { /// #if !MOBILE const allDocks = getAllDocks(); let menuHTML = ""; allDocks.forEach(item => { menuHTML += ``; }); - document.getElementById("status").innerHTML = `
+ let barDockHTML = ""; + if (!isWindow) { + barDockHTML = `
${menuHTML}
-
+
` + } + document.getElementById("status").innerHTML = `${barDockHTML}
@@ -34,13 +38,16 @@ export const initStatus = () => {
`; - const dockElement = document.getElementById("barDock"); - dockElement.addEventListener("mousemove", () => { - dockElement.querySelector(".b3-menu").classList.remove("fn__none"); - }); - dockElement.addEventListener("mouseleave", () => { - dockElement.querySelector(".b3-menu").classList.add("fn__none"); - }); + if (!isWindow) { + const dockElement = document.getElementById("barDock"); + dockElement.addEventListener("mousemove", () => { + dockElement.querySelector(".b3-menu").classList.remove("fn__none"); + }); + dockElement.addEventListener("mouseleave", () => { + dockElement.querySelector(".b3-menu").classList.add("fn__none"); + }); + } + document.querySelector("#status").addEventListener("click", (event) => { let target = event.target as HTMLElement; while (target.id !== "status") { diff --git a/app/src/layout/util.ts b/app/src/layout/util.ts index 9441640cf..798a5ac38 100644 --- a/app/src/layout/util.ts +++ b/app/src/layout/util.ts @@ -27,7 +27,8 @@ import {saveScroll} from "../protyle/scroll/saveScroll"; import {pdfResize} from "../asset/renderAssets"; import {Backlink} from "./dock/Backlink"; import {openFileById} from "../editor/util"; -import {getSearch} from "../util/functions"; +import {getSearch, isWindow} from "../util/functions"; +import {setTabPosition} from "../window/setHeader"; export const setPanelFocus = (element: Element) => { if (element.classList.contains("layout__tab--active") || element.classList.contains("layout__wnd--active")) { @@ -175,11 +176,17 @@ const JSONToDock = (json: any) => { window.siyuan.layout.bottomDock = new Dock({position: "Bottom", data: json.bottom}); }; -const JSONToCenter = (json: any, layout?: Layout | Wnd | Tab | Model) => { +export const JSONToCenter = (json: any, layout?: Layout | Wnd | Tab | Model) => { let child: Layout | Wnd | Tab | Model; if (json.instance === "Layout") { if (!layout) { - window.siyuan.layout.layout = new Layout({element: document.getElementById("layouts")}); + window.siyuan.layout.layout = new Layout({ + element: document.getElementById("layouts"), + direction: json.direction, + size: json.size, + type: json.type, + resize: json.resize + }); } else { child = new Layout({ direction: json.direction, @@ -635,10 +642,10 @@ export const addResize = (obj: Layout | Wnd) => { if (previousNowSize < 8 || nextNowSize < 8) { return; } - if (window.siyuan.layout.leftDock.layout.element.contains(previousElement) && previousNowSize < 188) { + if (window.siyuan.layout.leftDock?.layout.element.contains(previousElement) && previousNowSize < 188) { return; } - if (window.siyuan.layout.rightDock.layout.element.contains(nextElement) && nextNowSize < 188) { + if (window.siyuan.layout.rightDock?.layout.element.contains(nextElement) && nextNowSize < 188) { return; } previousElement.style[direction === "lr" ? "width" : "height"] = previousNowSize + "px"; @@ -666,10 +673,12 @@ export const addResize = (obj: Layout | Wnd) => { nextElement.classList.add("fn__flex-1"); } resizeTabs(); - window.siyuan.layout.leftDock.setSize(); - window.siyuan.layout.topDock.setSize(); - window.siyuan.layout.bottomDock.setSize(); - window.siyuan.layout.rightDock.setSize(); + if (!isWindow()) { + window.siyuan.layout.leftDock.setSize(); + window.siyuan.layout.topDock.setSize(); + window.siyuan.layout.bottomDock.setSize(); + window.siyuan.layout.rightDock.setSize(); + } if (range) { focusByRange(range); } diff --git a/app/src/menus/tab.ts b/app/src/menus/tab.ts index 13cf4e712..a8a27b622 100644 --- a/app/src/menus/tab.ts +++ b/app/src/menus/tab.ts @@ -2,7 +2,12 @@ import {Tab} from "../layout/Tab"; import {MenuItem} from "./Menu"; import {Editor} from "../editor"; import {copyTab} from "../layout/util"; +/// #if !BROWSER +import {BrowserWindow} from "@electron/remote"; +import * as path from "path"; +/// #endif import {copySubMenu} from "./commonMenuItem"; +import {Constants} from "../constants"; const closeMenu = (tab: Tab) => { const allTabs: Tab[] = []; @@ -163,7 +168,7 @@ export const initTabMenu = (tab: Tab) => { submenu: splitSubMenu(tab) }).element); const model = tab.model; - let rootId; + let rootId:string; if ((model && model instanceof Editor)) { rootId = model.editor.protyle.block.rootID; } else { @@ -198,5 +203,27 @@ export const initTabMenu = (tab: Tab) => { } }).element); } + /// #if !BROWSER + window.siyuan.menus.menu.append(new MenuItem({ + label: "new window", + click: () => { + const win = new BrowserWindow({ + show: true, + width: 1032, + height: 650, + frame: "darwin" === window.siyuan.config.system.os, + icon: path.join(window.siyuan.config.system.appDir, "stage", "icon-large.png"), + titleBarStyle: "hidden", + webPreferences: { + contextIsolation: false, + nodeIntegration: true, + webviewTag: true, + webSecurity: false, + }, + }); + win.loadURL(`${window.location.protocol}//${window.location.host}/stage/build/app/window.html?v=${Constants.SIYUAN_VERSION}&id=${rootId}`) + } + }).element); + /// #endif return window.siyuan.menus.menu; }; diff --git a/app/src/util/backForward.ts b/app/src/util/backForward.ts index b07ed4411..76923c2cb 100644 --- a/app/src/util/backForward.ts +++ b/app/src/util/backForward.ts @@ -192,7 +192,7 @@ export const goBack = async () => { } return; } - document.querySelector("#barForward").classList.remove("toolbar__item--disabled"); + document.querySelector("#barForward")?.classList.remove("toolbar__item--disabled"); if (!previousIsBack) { forwardStack.push(window.siyuan.backStack.pop()); } @@ -208,7 +208,7 @@ export const goBack = async () => { } previousIsBack = true; if (window.siyuan.backStack.length === 0) { - document.querySelector("#barBack").classList.add("toolbar__item--disabled"); + document.querySelector("#barBack")?.classList.add("toolbar__item--disabled"); } }; @@ -219,7 +219,7 @@ export const goForward = async () => { } return; } - document.querySelector("#barBack").classList.remove("toolbar__item--disabled"); + document.querySelector("#barBack")?.classList.remove("toolbar__item--disabled"); if (previousIsBack) { window.siyuan.backStack.push(forwardStack.pop()); } @@ -236,7 +236,7 @@ export const goForward = async () => { } previousIsBack = false; if (forwardStack.length === 0) { - document.querySelector("#barForward").classList.add("toolbar__item--disabled"); + document.querySelector("#barForward")?.classList.add("toolbar__item--disabled"); } }; @@ -269,7 +269,7 @@ export const pushBack = (protyle: IProtyle, range?: Range, blockElement?: Elemen window.siyuan.backStack.push(forwardStack.pop()); } forwardStack = []; - document.querySelector("#barForward").classList.add("toolbar__item--disabled"); + document.querySelector("#barForward")?.classList.add("toolbar__item--disabled"); } window.siyuan.backStack.push({ position, @@ -283,7 +283,7 @@ export const pushBack = (protyle: IProtyle, range?: Range, blockElement?: Elemen previousIsBack = false; } if (window.siyuan.backStack.length > 1) { - document.querySelector("#barBack").classList.remove("toolbar__item--disabled"); + document.querySelector("#barBack")?.classList.remove("toolbar__item--disabled"); } } }; diff --git a/app/src/util/functions.ts b/app/src/util/functions.ts index 6e9beb004..e566541c4 100644 --- a/app/src/util/functions.ts +++ b/app/src/util/functions.ts @@ -1,5 +1,9 @@ export const isMobile = () => { - return !document.getElementById("dockBottom"); + return document.getElementById("sidebar") ? true : false; +}; + +export const isWindow = () => { + return document.getElementById("toolbar") ? false : true; }; export const isTouchDevice = () => { diff --git a/app/src/util/onGetConfig.ts b/app/src/util/onGetConfig.ts index 2cfced36b..3e14ffd05 100644 --- a/app/src/util/onGetConfig.ts +++ b/app/src/util/onGetConfig.ts @@ -118,8 +118,9 @@ export const onGetConfig = (isStart: boolean) => { const hasKeymap4 = hasKeymap(Constants.SIYUAN_KEYMAP.editor.heading, "editor", "heading"); const hasKeymap5 = hasKeymap(Constants.SIYUAN_KEYMAP.editor.list, "editor", "list"); const hasKeymap6 = hasKeymap(Constants.SIYUAN_KEYMAP.editor.table, "editor", "table"); - if (!window.siyuan.config.readonly && (!matchKeymap1 || !matchKeymap2 || !matchKeymap3 || !matchKeymap4 || !matchKeymap5 || !matchKeymap6) && - (!hasKeymap1 || !hasKeymap2 || !hasKeymap3 || !hasKeymap4 || !hasKeymap5 || !hasKeymap6)) { + if (!window.siyuan.config.readonly && + (!matchKeymap1 || !matchKeymap2 || !matchKeymap3 || !matchKeymap4 || !matchKeymap5 || !matchKeymap6 || + !hasKeymap1 || !hasKeymap2 || !hasKeymap3 || !hasKeymap4 || !hasKeymap5 || !hasKeymap6)) { fetchPost("/api/setting/setKeymap", { data: window.siyuan.config.keymap }, () => { @@ -179,7 +180,7 @@ export const onGetConfig = (isStart: boolean) => { addGA(); }; -const initBar = () => { +export const initBar = () => { const toolbar = document.getElementById("toolbar"); toolbar.innerHTML = `
@@ -325,7 +326,7 @@ const winOnClose = (currentWindow: Electron.BrowserWindow, close = false) => { /// #endif }; -const initWindow = () => { +export const initWindow = () => { /// #if !BROWSER const currentWindow = getCurrentWindow(); currentWindow.on("focus", winOnFocus); @@ -451,8 +452,8 @@ const initWindow = () => { window.addEventListener("beforeunload", () => { currentWindow.off("focus", winOnFocus); }, false); - if ("windows" !== window.siyuan.config.system.os && "linux" !== window.siyuan.config.system.os) { - document.getElementById("drag").addEventListener("dblclick", () => { + if ( "darwin" === window.siyuan.config.system.os) { + document.getElementById("drag")?.addEventListener("dblclick", () => { if (currentWindow.isMaximized()) { currentWindow.unmaximize(); } else { @@ -474,7 +475,7 @@ const initWindow = () => { } document.body.classList.add("body--win32"); - //添加应用图标 + // 添加应用图标 const toolbar = document.getElementById("toolbar"); toolbar.insertAdjacentHTML("afterbegin", `
@@ -482,7 +483,7 @@ const initWindow = () => {
`); - //添加窗口控件 + // 添加窗口控件 const controlsElement = document.getElementById("windowControls"); controlsElement.innerHTML = `
diff --git a/app/webpack.config.js b/app/webpack.config.js index 070b9c5fb..1b031b1a6 100644 --- a/app/webpack.config.js +++ b/app/webpack.config.js @@ -19,6 +19,7 @@ module.exports = (env, argv) => { }, entry: { 'main': './src/index.ts', + 'window': './src/window.ts', }, resolve: { extensions: ['.ts', '.js', '.tpl', '.scss', '.png', '.svg'], @@ -41,7 +42,8 @@ module.exports = (env, argv) => { { test: /\.tpl/, include: [ - path.resolve(__dirname, 'src/assets/template/app/index.tpl')], + path.resolve(__dirname, 'src/assets/template/app/index.tpl'), + path.resolve(__dirname, 'src/assets/template/app/window.tpl')], loader: 'html-loader', options: { sources: false, @@ -117,6 +119,12 @@ module.exports = (env, argv) => { filename: 'index.html', template: 'src/assets/template/app/index.tpl', }), + new HtmlWebpackPlugin({ + inject: 'head', + chunks: ['window'], + filename: 'window.html', + template: 'src/assets/template/app/window.tpl', + }), ], } }