This commit is contained in:
parent
0cd68fe571
commit
e94a534b02
9 changed files with 111 additions and 114 deletions
|
@ -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: {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
2
app/src/types/index.d.ts
vendored
2
app/src/types/index.d.ts
vendored
|
@ -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, // 文档图标
|
||||||
|
|
|
@ -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]));
|
||||||
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue