Browse Source

:art: https://github.com/siyuan-note/siyuan/issues/8139

Vanessa 2 years ago
parent
commit
e94a534b02

+ 0 - 33
app/src/card/newCardTab.ts

@@ -1,42 +1,9 @@
-import {Wnd} from "../layout/Wnd";
-import {getInstanceById, getWndByLayout} from "../layout/util";
 import {Tab} from "../layout/Tab";
 import {Custom} from "../layout/dock/Custom";
 import {bindCardEvent, genCardHTML} from "./openCard";
 import {fetchPost} from "../util/fetch";
 import {Protyle} from "../protyle";
 
-export const newCardTab = (options: {
-    cardType: TCardType,
-    id: string,
-    title?: string
-}) => {
-    let wnd: Wnd;
-    const element = document.querySelector(".layout__wnd--active");
-    if (element) {
-        wnd = getInstanceById(element.getAttribute("data-id")) as Wnd;
-    }
-    if (!wnd) {
-        wnd = getWndByLayout(window.siyuan.layout.centerLayout);
-    }
-
-    const tab = new Tab({
-        icon: "iconRiffCard",
-        title: window.siyuan.languages.spaceRepetition,
-        callback(tab) {
-            tab.addModel(newCardModel({
-                tab,
-                data: {
-                    cardType: options.cardType,
-                    id: options.id,
-                    title: options.title
-                }
-            }));
-        }
-    });
-    wnd.split("lr").addTab(tab);
-}
-
 export const newCardModel = (options: {
     tab: Tab,
     data: {

+ 8 - 5
app/src/card/openCard.ts

@@ -11,7 +11,7 @@ import {fullscreen} from "../protyle/breadcrumb/action";
 import {MenuItem} from "../menus/Menu";
 import {escapeHtml} from "../util/escape";
 /// #if !MOBILE
-import {newCardTab} from "./newCardTab";
+import {openFile} from "../editor/util";
 /// #endif
 import {getDisplayName, movePathTo} from "../util/pathName";
 
@@ -203,10 +203,13 @@ export const bindCardEvent = (options: {
             /// #if !MOBILE
             const sticktabElement = hasClosestByAttribute(target, "data-type", "sticktab");
             if (sticktabElement) {
-                newCardTab({
-                    cardType: filterElement.getAttribute("data-cardtype") as TCardType,
-                    id: filterElement.getAttribute("data-id"),
-                    title: options.title
+                openFile({
+                    position: "right",
+                    customData:{
+                        cardType: filterElement.getAttribute("data-cardtype") as TCardType,
+                        id: filterElement.getAttribute("data-id"),
+                        title: options.title
+                    }
                 });
                 if (options.dialog) {
                     options.dialog.destroy();

+ 4 - 4
app/src/dialog/index.ts

@@ -2,7 +2,7 @@ import {genUUID} from "../util/genID";
 import {isMobile} from "../util/functions";
 
 export class Dialog {
-    private destroyCallback: () => void;
+    private destroyCallback: (options?:IObject) => void;
     public element: HTMLElement;
     private id: string;
     private disableClose: boolean;
@@ -13,7 +13,7 @@ export class Dialog {
         content: string,
         width?: string
         height?: string,
-        destroyCallback?: () => void
+        destroyCallback?: (options?:IObject) => void
         disableClose?: boolean
         disableAnimation?: boolean
     }) {
@@ -59,12 +59,12 @@ export class Dialog {
         window.siyuan.menus.menu.remove();
     }
 
-    public destroy() {
+    public destroy(options?:IObject) {
         this.element.remove();
         // https://github.com/siyuan-note/siyuan/issues/6783
         window.siyuan.menus.menu.remove();
         if (this.destroyCallback) {
-            this.destroyCallback();
+            this.destroyCallback(options);
         }
         window.siyuan.dialogs.find((item, index) => {
             if (item.id === this.id) {

+ 58 - 6
app/src/editor/util.ts

@@ -1,7 +1,7 @@
 import {Tab} from "../layout/Tab";
 import {Editor} from "./index";
 import {Wnd} from "../layout/Wnd";
-import {getDockByType, getInstanceById, getWndByLayout, pdfIsLoading} from "../layout/util";
+import {getDockByType, getInstanceById, getWndByLayout, pdfIsLoading, resizeTabs, setPanelFocus} from "../layout/util";
 import {getAllModels, getAllTabs} from "../layout/getAll";
 import {highlightById, scrollCenter} from "../util/highlightById";
 import {getDisplayName, pathPosix} from "../util/pathName";
@@ -24,8 +24,10 @@ import {setTitle} from "../dialog/processSystem";
 import {zoomOut} from "../menus/protyle";
 import {countBlockWord, countSelectWord} from "../layout/status";
 import {showMessage} from "../dialog/message";
-import {getSearch} from "../util/functions";
+import {getSearch, objEquals} from "../util/functions";
 import {resize} from "../protyle/util/resize";
+import {newCardModel} from "../card/newCardTab";
+import {Search} from "../search";
 
 export const openFileById = async (options: {
     id: string,
@@ -74,7 +76,7 @@ export const openAsset = (assetPath: string, page: number | string, position?: s
     });
 };
 
-const openFile = (options: IOpenFileOptions) => {
+export const openFile = (options: IOpenFileOptions) => {
     const allModels = getAllModels();
     // 文档已打开
     if (options.assetPath) {
@@ -94,6 +96,32 @@ const openFile = (options: IOpenFileOptions) => {
             }
             return;
         }
+    } else if (options.customData) {
+        const custom = allModels.custom.find((item) => {
+            if (objEquals(item.data, options.customData)) {
+                if (!pdfIsLoading(item.parent.parent.element)) {
+                    item.parent.parent.switchTab(item.parent.headElement);
+                    item.parent.parent.showHeading();
+                }
+                return true;
+            }
+        });
+        if (custom) {
+            return;
+        }
+    } else if (options.searchData) {
+        const search = allModels.search.find((item) => {
+            if (objEquals(item.config, options.searchData)) {
+                if (!pdfIsLoading(item.parent.parent.element)) {
+                    item.parent.parent.switchTab(item.parent.headElement);
+                    item.parent.parent.showHeading();
+                }
+                return true;
+            }
+        });
+        if (search) {
+            return;
+        }
     } else if (!options.position) {
         let editor: Editor;
         let activeEditor: Editor;
@@ -347,15 +375,39 @@ const newTab = (options: IOpenFileOptions) => {
                 icon,
                 title: getDisplayName(options.assetPath),
                 callback(tab) {
-                    const asset = new Asset({
+                    tab.addModel(new Asset({
                         tab,
                         path: options.assetPath,
                         page: options.page,
-                    });
-                    tab.addModel(asset);
+                    }));
+                    setPanelFocus(tab.panelElement.parentElement.parentElement);
                 }
             });
         }
+    } else if (options.customData) {
+        tab = new Tab({
+            icon: "iconRiffCard",
+            title: window.siyuan.languages.spaceRepetition,
+            callback(tab) {
+                tab.addModel(newCardModel({
+                    tab,
+                    data: options.customData
+                }));
+                setPanelFocus(tab.panelElement.parentElement.parentElement);
+            }
+        });
+    } else if (options.searchData) {
+        tab = new Tab({
+            icon: "iconSearch",
+            title: window.siyuan.languages.search,
+            callback(tab) {
+                tab.addModel(new Search({
+                    tab,
+                    config: options.searchData
+                }));
+                setPanelFocus(tab.panelElement.parentElement.parentElement);
+            }
+        });
     } else {
         tab = new Tab({
             title: getDisplayName(options.fileName, true, true),

+ 4 - 0
app/src/search/index.ts

@@ -2,6 +2,7 @@ import {Model} from "../layout/Model";
 import {Tab} from "../layout/Tab";
 import {Protyle} from "../protyle";
 import {genSearch} from "./util";
+import {setPanelFocus} from "../layout/util";
 
 export class Search extends Model {
     private element: HTMLElement;
@@ -15,6 +16,9 @@ export class Search extends Model {
         this.element = options.tab.panelElement as HTMLElement;
         this.config = options.config;
         this.edit = genSearch(this.config, this.element);
+        this.element.addEventListener("click", () => {
+            setPanelFocus(this.element.parentElement.parentElement);
+        });
     }
 
     public updateSearch(text: string, replace: boolean) {

+ 3 - 3
app/src/search/spread.ts

@@ -75,8 +75,8 @@ export const openSearch = async (hotkey: string, key?: string, notebookId?: stri
         content: "",
         width: "80vw",
         height: "90vh",
-        destroyCallback: () => {
-            if (range) {
+        destroyCallback(options: IObject) {
+            if (range && !options) {
                 focusByRange(range);
             }
             if (edit) {
@@ -98,7 +98,7 @@ export const openSearch = async (hotkey: string, key?: string, notebookId?: stri
         types: Object.assign({}, localData.types),
         page: key ? 1 : localData.page
     }, dialog.element.querySelector(".b3-dialog__container").lastElementChild, () => {
-        dialog.destroy();
+        dialog.destroy({focus: "false"});
     });
     // 搜索面板层级需高于 201(.protyle-hint) 且小于205(.block__popover)
     dialog.element.firstElementChild.setAttribute("style", "z-index:202"); // https://github.com/siyuan-note/siyuan/issues/3515

+ 22 - 63
app/src/search/util.ts

@@ -1,12 +1,8 @@
 import {getAllModels} from "../layout/getAll";
-import {getInstanceById, getWndByLayout, resizeTabs, setPanelFocus} from "../layout/util";
-import {Tab} from "../layout/Tab";
-import {Search} from "./index";
-import {Wnd} from "../layout/Wnd";
 import {Constants} from "../constants";
 import {escapeAttr, escapeGreat, escapeHtml} from "../util/escape";
 import {fetchPost} from "../util/fetch";
-import {openFileById} from "../editor/util";
+import {openFile, openFileById} from "../editor/util";
 import {showMessage} from "../dialog/message";
 import {reloadProtyle} from "../protyle/util/reload";
 import {MenuItem} from "../menus/Menu";
@@ -36,48 +32,31 @@ const saveKeyList = (type: "keys" | "replaceKeys", value: string) => {
 
 export const openGlobalSearch = (text: string, replace: boolean) => {
     text = text.trim();
-    let wnd: Wnd;
-    const searchModel = getAllModels().search.find((item, index) => {
-        if (index === 0) {
-            wnd = item.parent.parent;
-        }
-        wnd.switchTab(item.parent.headElement);
+    const searchModel = getAllModels().search.find((item) => {
+        item.parent.parent.switchTab(item.parent.headElement);
         item.updateSearch(text, replace);
         return true;
     });
     if (searchModel) {
         return;
     }
-    if (!wnd) {
-        wnd = getWndByLayout(window.siyuan.layout.centerLayout);
-    }
-    const tab = new Tab({
-        icon: "iconSearch",
-        title: window.siyuan.languages.search,
-        callback(tab) {
-            const localData = window.siyuan.storage[Constants.LOCAL_SEARCHDATA];
-            const asset = new Search({
-                tab,
-                config: {
-                    k: text,
-                    r: "",
-                    hasReplace: false,
-                    method: localData.method,
-                    hPath: "",
-                    idPath: [],
-                    group: localData.group,
-                    sort: localData.sort,
-                    types: Object.assign({}, localData.types),
-                    removed: localData.removed,
-                    page: 1
-                }
-            });
-            tab.addModel(asset);
-            resizeTabs();
-        }
+    const localData = window.siyuan.storage[Constants.LOCAL_SEARCHDATA];
+    openFile({
+        searchData: {
+            k: text,
+            r: "",
+            hasReplace: false,
+            method: localData.method,
+            hPath: "",
+            idPath: [],
+            group: localData.group,
+            sort: localData.sort,
+            types: Object.assign({}, localData.types),
+            removed: localData.removed,
+            page: 1
+        },
+        position: "right"
     });
-    wnd.split("lr").addTab(tab);
-    setPanelFocus(tab.panelElement);
 };
 
 // closeCB 不存在为页签搜索
@@ -428,29 +407,9 @@ export const genSearch = (config: ISearchOption, element: Element, closeCB?: ()
                 event.preventDefault();
                 break;
             } else if (target.id === "searchOpen") {
-                let wnd: Wnd;
-                const element = document.querySelector(".layout__wnd--active");
-                if (element) {
-                    wnd = getInstanceById(element.getAttribute("data-id")) as Wnd;
-                }
-                if (!wnd) {
-                    wnd = getWndByLayout(window.siyuan.layout.centerLayout);
-                }
-                const tab = new Tab({
-                    icon: "iconSearch",
-                    title: window.siyuan.languages.search,
-                    callback(tab) {
-                        config.k = searchInputElement.value;
-                        config.r = replaceInputElement.value;
-                        const asset = new Search({
-                            tab,
-                            config
-                        });
-                        tab.addModel(asset);
-                        resizeTabs();
-                    }
-                });
-                wnd.split("lr").addTab(tab);
+                config.k = searchInputElement.value;
+                config.r = replaceInputElement.value;
+                openFile({searchData: config, position: "right"});
                 if (closeCB) {
                     closeCB();
                 }

+ 2 - 0
app/src/types/index.d.ts

@@ -280,6 +280,8 @@ declare interface IDockTab {
 }
 
 declare interface IOpenFileOptions {
+    searchData?: ISearchOption, // 搜索必填
+    customData?: any, // card 必填
     assetPath?: string, // asset 必填
     fileName?: string, // file 必填
     rootIcon?: string, // 文档图标

+ 10 - 0
app/src/util/functions.ts

@@ -46,3 +46,13 @@ export const isFileAnnotation = (text: string) => {
 export const looseJsonParse = (text: string) => {
     return Function(`"use strict";return (${text})`)();
 };
+
+export const objEquals = (a: any, b: any): boolean => {
+    if (a === b) return true;
+    if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
+    if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b;
+    if (a.prototype !== b.prototype) return false;
+    const keys = Object.keys(a);
+    if (keys.length !== Object.keys(b).length) return false;
+    return keys.every(k => objEquals(a[k], b[k]));
+};