Vanessa 2023-04-28 22:08:57 +08:00
parent 0cd68fe571
commit e94a534b02
9 changed files with 111 additions and 114 deletions

View file

@ -1,42 +1,9 @@
import {Wnd} from "../layout/Wnd";
import {getInstanceById, getWndByLayout} from "../layout/util";
import {Tab} from "../layout/Tab"; import {Tab} from "../layout/Tab";
import {Custom} from "../layout/dock/Custom"; import {Custom} from "../layout/dock/Custom";
import {bindCardEvent, genCardHTML} from "./openCard"; import {bindCardEvent, genCardHTML} from "./openCard";
import {fetchPost} from "../util/fetch"; import {fetchPost} from "../util/fetch";
import {Protyle} from "../protyle"; 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: { export const newCardModel = (options: {
tab: Tab, tab: Tab,
data: { data: {

View file

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

View file

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

View file

@ -1,7 +1,7 @@
import {Tab} from "../layout/Tab"; import {Tab} from "../layout/Tab";
import {Editor} from "./index"; import {Editor} from "./index";
import {Wnd} from "../layout/Wnd"; 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 {getAllModels, getAllTabs} from "../layout/getAll";
import {highlightById, scrollCenter} from "../util/highlightById"; import {highlightById, scrollCenter} from "../util/highlightById";
import {getDisplayName, pathPosix} from "../util/pathName"; import {getDisplayName, pathPosix} from "../util/pathName";
@ -24,8 +24,10 @@ import {setTitle} from "../dialog/processSystem";
import {zoomOut} from "../menus/protyle"; import {zoomOut} from "../menus/protyle";
import {countBlockWord, countSelectWord} from "../layout/status"; import {countBlockWord, countSelectWord} from "../layout/status";
import {showMessage} from "../dialog/message"; import {showMessage} from "../dialog/message";
import {getSearch} from "../util/functions"; import {getSearch, objEquals} from "../util/functions";
import {resize} from "../protyle/util/resize"; import {resize} from "../protyle/util/resize";
import {newCardModel} from "../card/newCardTab";
import {Search} from "../search";
export const openFileById = async (options: { export const openFileById = async (options: {
id: string, 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(); const allModels = getAllModels();
// 文档已打开 // 文档已打开
if (options.assetPath) { if (options.assetPath) {
@ -94,6 +96,32 @@ const openFile = (options: IOpenFileOptions) => {
} }
return; 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) { } else if (!options.position) {
let editor: Editor; let editor: Editor;
let activeEditor: Editor; let activeEditor: Editor;
@ -347,15 +375,39 @@ const newTab = (options: IOpenFileOptions) => {
icon, icon,
title: getDisplayName(options.assetPath), title: getDisplayName(options.assetPath),
callback(tab) { callback(tab) {
const asset = new Asset({ tab.addModel(new Asset({
tab, tab,
path: options.assetPath, path: options.assetPath,
page: options.page, 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 { } else {
tab = new Tab({ tab = new Tab({
title: getDisplayName(options.fileName, true, true), title: getDisplayName(options.fileName, true, true),

View file

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

View file

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

View file

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

View file

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

View file

@ -46,3 +46,13 @@ export const isFileAnnotation = (text: string) => {
export const looseJsonParse = (text: string) => { export const looseJsonParse = (text: string) => {
return Function(`"use strict";return (${text})`)(); 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]));
};