Browse Source

:art: fix https://github.com/siyuan-note/siyuan/issues/8344

Vanessa 2 years ago
parent
commit
95c64975e8

+ 3 - 1
app/src/assets/scss/base.scss

@@ -101,7 +101,7 @@ html {
   }
 
   .protyle-breadcrumb > .protyle-breadcrumb__space,
-  & > .block__icons > .fn__flex-1{
+  & > .block__icons > .fn__flex-1 {
     -webkit-app-region: drag;
     min-width: 32px;
 
@@ -162,6 +162,8 @@ html {
     white-space: nowrap;
     align-self: center;
     font-size: 12px;
+    min-width: 148px;
+    box-sizing: border-box;
   }
 
   &__item {

+ 2 - 2
app/src/boot/onGetConfig.ts

@@ -1,4 +1,4 @@
-import {exportLayout, JSONToLayout, resetLayout, resizeDrag, resizeTabs} from "../layout/util";
+import {exportLayout, JSONToLayout, resetLayout, resizeTopbar, resizeTabs} from "../layout/util";
 import {hotKey2Electron, setStorageVal} from "../protyle/util/compatibility";
 /// #if !BROWSER
 import {dialog, getCurrentWindow} from "@electron/remote";
@@ -154,7 +154,7 @@ export const onGetConfig = (isStart: boolean, app: App) => {
         window.clearTimeout(resizeTimeout);
         resizeTimeout = window.setTimeout(() => {
             resizeTabs();
-            resizeDrag();
+            resizeTopbar();
         }, 200);
     });
     addGA();

+ 0 - 2
app/src/index.ts

@@ -23,7 +23,6 @@ import {
 } from "./dialog/processSystem";
 import {promiseTransactions} from "./protyle/wysiwyg/transaction";
 import {initMessage} from "./dialog/message";
-import {resizeDrag} from "./layout/util";
 import {getAllTabs} from "./layout/getAll";
 import {getLocalStorage} from "./protyle/util/compatibility";
 import {updateEditModeElement} from "./layout/topBar";
@@ -174,7 +173,6 @@ export class App {
                         window.siyuan.user = userResponse.data;
                         onGetConfig(response.data.start, this);
                         account.onSetaccount();
-                        resizeDrag();
                         setTitle(window.siyuan.languages.siyuanNote);
                         initMessage();
                     });

+ 55 - 11
app/src/layout/topBar.ts

@@ -59,32 +59,70 @@ export const initBar = (app: App) => {
 <div id="barMode" class="toolbar__item b3-tooltips b3-tooltips__sw${window.siyuan.config.readonly ? " fn__none" : ""}" aria-label="${window.siyuan.languages.appearanceMode}">
     <svg><use xlink:href="#icon${window.siyuan.config.appearance.modeOS ? "Mode" : (window.siyuan.config.appearance.mode === 0 ? "Light" : "Dark")}"></use></svg>
 </div>
+<div id="barMore" class="toolbar__item">
+    <svg><use xlink:href="#iconMore"></use></svg>
+</div>
 <div class="fn__flex" id="windowControls"></div>`;
     processSync();
     toolbarElement.addEventListener("click", (event: MouseEvent) => {
         let target = event.target as HTMLElement;
+        if (typeof event.detail === "string") {
+            target = toolbarElement.querySelector("#" + event.detail);
+        }
         while (!target.classList.contains("toolbar")) {
-            if (target.id === "barBack") {
+            const targetId = typeof event.detail === "string" ? event.detail : target.id;
+            if (targetId === "barBack") {
                 goBack(app);
                 event.stopPropagation();
                 break;
-            } else if (target.id === "barForward") {
+            } else if (targetId === "barMore") {
+                if (!window.siyuan.menus.menu.element.classList.contains("fn__none") &&
+                    window.siyuan.menus.menu.element.getAttribute("data-name") === "barmore") {
+                    window.siyuan.menus.menu.remove();
+                    return;
+                }
+                window.siyuan.menus.menu.remove();
+                window.siyuan.menus.menu.element.setAttribute("data-name", "barmore");
+                (target.getAttribute("data-hideids") || "").split(",").forEach((itemId) => {
+                    const hideElement = toolbarElement.querySelector("#" + itemId);
+                    window.siyuan.menus.menu.append(new MenuItem({
+                        label: itemId === "toolbarVIP" ? window.siyuan.languages.account : hideElement.getAttribute("aria-label"),
+                        icon: itemId === "toolbarVIP" ? "iconAccount" : hideElement.querySelector("use").getAttribute("xlink:href").substring(1),
+                        click: () => {
+                            if (itemId.startsWith("plugin")) {
+                                hideElement.dispatchEvent(new CustomEvent("click"));
+                            } else {
+                                toolbarElement.dispatchEvent(new CustomEvent("click", {detail: itemId}));
+                            }
+                            if (!window.siyuan.menus.menu.element.classList.contains("fn__none") &&
+                                window.siyuan.menus.menu.element.getAttribute("data-name") === "barmore") {
+                                return false;
+                            }
+                            return true;
+                        }
+                    }).element);
+                });
+                const rect = target.getBoundingClientRect();
+                window.siyuan.menus.menu.popup({x: rect.right, y: rect.bottom}, true);
+                event.stopPropagation();
+                break;
+            } else if (targetId === "barForward") {
                 goForward(app);
                 event.stopPropagation();
                 break;
-            } else if (target.id === "barSync") {
+            } else if (targetId === "barSync") {
                 syncGuide(app);
                 event.stopPropagation();
                 break;
-            } else if (target.id === "barWorkspace") {
+            } else if (targetId === "barWorkspace") {
                 workspaceMenu(app, target.getBoundingClientRect());
                 event.stopPropagation();
                 break;
-            } else if (target.id === "barReadonly") {
+            } else if (targetId === "barReadonly") {
                 editor.setReadonly();
                 event.stopPropagation();
                 break;
-            } else if (target.id === "barMode") {
+            } else if (targetId === "barMode") {
                 if (!window.siyuan.menus.menu.element.classList.contains("fn__none") &&
                     window.siyuan.menus.menu.element.getAttribute("data-name") === "barmode") {
                     window.siyuan.menus.menu.remove();
@@ -116,25 +154,28 @@ export const initBar = (app: App) => {
                         setMode(2);
                     }
                 }).element);
-                const rect = target.getBoundingClientRect();
+                let rect = target.getBoundingClientRect();
+                if (rect.width === 0) {
+                    rect = toolbarElement.querySelector("#barMore").getBoundingClientRect();
+                }
                 window.siyuan.menus.menu.popup({x: rect.right, y: rect.bottom}, true);
                 event.stopPropagation();
                 break;
-            } else if (target.id === "toolbarVIP") {
+            } else if (targetId === "toolbarVIP") {
                 if (!window.siyuan.config.readonly) {
                     const dialogSetting = openSetting(app);
                     dialogSetting.element.querySelector('.b3-tab-bar [data-name="account"]').dispatchEvent(new CustomEvent("click"));
                 }
                 event.stopPropagation();
                 break;
-            } else if (target.id === "barSearch") {
+            } else if (targetId === "barSearch") {
                 openSearch({
                     app,
                     hotkey: window.siyuan.config.keymap.general.globalSearch.custom
                 });
                 event.stopPropagation();
                 break;
-            } else if (target.id === "barZoom") {
+            } else if (targetId === "barZoom") {
                 if (!window.siyuan.menus.menu.element.classList.contains("fn__none") &&
                     window.siyuan.menus.menu.element.getAttribute("data-name") === "barZoom") {
                     window.siyuan.menus.menu.remove();
@@ -165,7 +206,10 @@ export const initBar = (app: App) => {
                         setZoom("restore");
                     }
                 }).element);
-                const rect = target.getBoundingClientRect();
+                let rect = target.getBoundingClientRect();
+                if (rect.width === 0) {
+                    rect = toolbarElement.querySelector("#barMore").getBoundingClientRect();
+                }
                 window.siyuan.menus.menu.popup({x: rect.right, y: rect.bottom}, true);
                 event.stopPropagation();
                 break;

+ 46 - 6
app/src/layout/util.ts

@@ -444,6 +444,7 @@ export const JSONToLayout = (app: App, isStart: boolean) => {
             tab.parent.switchTab(item, false, false);
         });
     }
+    resizeTopbar();
 };
 
 export const layoutToJSON = (layout: Layout | Wnd | Tab | Model, json: any, dropEditScroll = false) => {
@@ -578,18 +579,57 @@ export const layoutToJSON = (layout: Layout | Wnd | Tab | Model, json: any, drop
     }
 };
 
-export const resizeDrag = () => {
-    const dragElement = document.getElementById("drag");
+export const resizeTopbar = () => {
+    const toolbarElement = document.querySelector("#toolbar");
+    const dragElement = toolbarElement.querySelector("#drag") as HTMLElement;
+
+    dragElement.style.padding = "";
+    const barMoreElement = toolbarElement.querySelector("#barMore")
+    barMoreElement.classList.remove("fn__none")
+    barMoreElement.removeAttribute("data-hideids")
+
+    Array.from(toolbarElement.querySelectorAll('[data-hide="true"]')).forEach((item) => {
+        item.classList.remove("fn__none")
+        item.removeAttribute("data-hide");
+    })
+
+    let afterDragElement = dragElement.nextElementSibling
+    const hideIds: string[] = []
+    while (toolbarElement.scrollWidth > toolbarElement.clientWidth + 2) {
+        hideIds.push(afterDragElement.id)
+        afterDragElement.classList.add("fn__none")
+        afterDragElement.setAttribute("data-hide", "true")
+        afterDragElement = afterDragElement.nextElementSibling
+        if (afterDragElement.id === "barMore") {
+            break;
+        }
+    }
+
+    let beforeDragElement = dragElement.previousElementSibling
+    while (toolbarElement.scrollWidth > toolbarElement.clientWidth + 2) {
+        hideIds.push(beforeDragElement.id)
+        beforeDragElement.classList.add("fn__none")
+        beforeDragElement.setAttribute("data-hide", "true")
+        beforeDragElement = beforeDragElement.previousElementSibling
+        if (beforeDragElement.id === "barWorkspace") {
+            break;
+        }
+    }
+    if (hideIds.length > 0) {
+        barMoreElement.classList.remove("fn__none")
+    } else {
+        barMoreElement.classList.add("fn__none")
+    }
+    barMoreElement.setAttribute("data-hideids", hideIds.join(","))
+
     const width = dragElement.clientWidth;
     const dragRect = dragElement.getBoundingClientRect();
     const left = dragRect.left;
     const right = window.innerWidth - dragRect.right;
-    if (left > right && left - right < width) {
+    if (left > right && left - right < width / 3) {
         dragElement.style.paddingRight = (left - right) + "px";
-    } else if (left < right && right - left < width) {
+    } else if (left < right && right - left < width / 3) {
         dragElement.style.paddingLeft = (right - left) + "px";
-    } else {
-        dragElement.style.padding = "";
     }
 };
 

+ 4 - 2
app/src/menus/Menu.ts

@@ -179,11 +179,13 @@ export class MenuItem {
                 if (this.element.getAttribute("disabled")) {
                     return;
                 }
-                options.click(this.element);
+                const result = options.click(this.element);
                 event.preventDefault();
                 event.stopImmediatePropagation();
                 event.stopPropagation();
-                window.siyuan.menus.menu.remove();
+                if (typeof result === "undefined" || !result) {
+                    window.siyuan.menus.menu.remove();
+                }
             });
         }
         if (options.id) {

+ 4 - 3
app/src/plugin/index.ts

@@ -9,6 +9,7 @@ import {Tab} from "../layout/Tab";
 import {getDockByType, setPanelFocus} from "../layout/util";
 import {hasClosestByAttribute} from "../protyle/util/hasClosest";
 import {BlockPanel} from "../block/Panel";
+import {genUUID} from "../util/genID";
 
 export class Plugin {
     private app: App;
@@ -66,16 +67,16 @@ export class Plugin {
         callback: (evt: MouseEvent) => void
     }) {
         const iconElement = document.createElement("div");
+        iconElement.setAttribute("data-menu", "true");
+        iconElement.addEventListener("click", options.callback);
+        iconElement.id = "plugin" + genUUID();
         if (isMobile()) {
             iconElement.className = "b3-menu__item";
-            iconElement.setAttribute("data-menu", "true");
             iconElement.innerHTML = (options.icon.startsWith("icon") ? `<svg class="b3-menu__icon"><use xlink:href="#${options.icon}"></use></svg>` : options.icon) +
                 `<span class="b3-menu__label">${options.title}</span>`;
-            iconElement.addEventListener("click", options.callback);
         } else if (!isWindow()) {
             iconElement.className = "toolbar__item b3-tooltips b3-tooltips__sw";
             iconElement.setAttribute("aria-label", options.title);
-            iconElement.setAttribute("data-menu", "true");
             iconElement.innerHTML = options.icon.startsWith("icon") ? `<svg><use xlink:href="#${options.icon}"></use></svg>` : options.icon;
             iconElement.addEventListener("click", options.callback);
             iconElement.setAttribute("data-position", options.position);

+ 1 - 1
app/src/types/index.d.ts

@@ -723,7 +723,7 @@ declare interface IModels {
 
 declare interface IMenu {
     label?: string,
-    click?: (element: HTMLElement) => void,
+    click?: (element: HTMLElement) => boolean | void,
     type?: "separator" | "submenu" | "readonly",
     accelerator?: string,
     action?: string,