This commit is contained in:
Vanessa 2023-05-12 17:11:43 +08:00
parent 5c14d38dfd
commit 2976349c27
18 changed files with 192 additions and 78 deletions

View file

@ -76,7 +76,7 @@ const switchDialogEvent = (event: MouseEvent, switchDialog: Dialog) => {
if (currentType === "riffCard") {
openCard();
} else {
getDockByType(currentType as TDockType).toggleModel(currentType as TDockType, true);
getDockByType(currentType).toggleModel(currentType, true);
}
} else {
const currentId = target.getAttribute("data-id");
@ -369,7 +369,7 @@ export const globalShortcut = (app: App) => {
if (currentType === "riffCard") {
openCard();
} else {
getDockByType(currentType as TDockType).toggleModel(currentType as TDockType, true);
getDockByType(currentType).toggleModel(currentType, true);
}
if (document.activeElement) {
(document.activeElement as HTMLElement).blur();
@ -492,8 +492,8 @@ export const globalShortcut = (app: App) => {
getAllDocks().forEach((item, index) => {
dockHtml += `<li data-type="${item.type}" data-index="${index + 1}" class="b3-list-item">
<svg class="b3-list-item__graphic"><use xlink:href="#${item.icon}"></use></svg>
<span class="b3-list-item__text">${window.siyuan.languages[item.hotkeyLangId]}</span>
<span class="b3-list-item__meta">${updateHotkeyTip(window.siyuan.config.keymap.general[item.hotkeyLangId].custom)}</span>
<span class="b3-list-item__text">${item.title}</span>
<span class="b3-list-item__meta">${updateHotkeyTip(item.hotkey || "")}</span>
</li>`;
});
dockHtml = dockHtml + "</ul>";
@ -623,7 +623,7 @@ export const globalShortcut = (app: App) => {
return;
}
const matchDock = getAllDocks().find(item => {
if (matchHotKey(window.siyuan.config.keymap.general[item.hotkeyLangId].custom, event)) {
if (matchHotKey(item.hotkey, event)) {
getDockByType(item.type).toggleModel(item.type);
if (document.activeElement) {
(document.activeElement as HTMLElement).blur();
@ -751,15 +751,15 @@ export const globalShortcut = (app: App) => {
event.preventDefault();
let activeTabElement = document.querySelector(".layout__tab--active");
if (activeTabElement && activeTabElement.getBoundingClientRect().width > 0) {
let type: TDockType;
let type = "";
Array.from(activeTabElement.classList).find(item => {
if (item.startsWith("sy__")) {
type = item.replace("sy__", "") as TDockType;
type = item.replace("sy__", "");
return true;
}
});
if (type) {
getDockByType(type).toggleModel(type, false, true);
getDockByType(type)?.toggleModel(type, false, true);
}
return;
}
@ -932,7 +932,7 @@ const dialogArrow = (element: HTMLElement, event: KeyboardEvent) => {
if (currentType === "riffCard") {
openCard();
} else {
getDockByType(currentType as TDockType).toggleModel(currentType as TDockType, true);
getDockByType(currentType).toggleModel(currentType, true);
}
} else {
openFileById({

View file

@ -33,8 +33,8 @@ ${unicode2Emoji(item.icon || Constants.SIYUAN_IMAGE_FILE, false, "b3-list-item__
getAllDocks().forEach((item, index) => {
dockHtml += `<li data-type="${item.type}" data-index="${index + 1}" class="b3-list-item">
<svg class="b3-list-item__graphic"><use xlink:href="#${item.icon}"></use></svg>
<span class="b3-list-item__text">${window.siyuan.languages[item.hotkeyLangId]}</span>
<span class="b3-list-item__meta">${updateHotkeyTip(window.siyuan.config.keymap.general[item.hotkeyLangId].custom)}</span>
<span class="b3-list-item__text">${item.title}</span>
<span class="b3-list-item__meta">${updateHotkeyTip(item.hotkey || "")}</span>
</li>`;
});
dockHtml = dockHtml + "</ul>";

View file

@ -3,6 +3,7 @@ import {Custom} from "../layout/dock/Custom";
import {bindCardEvent, genCardHTML} from "./openCard";
import {fetchPost} from "../util/fetch";
import {Protyle} from "../protyle";
import {setPanelFocus} from "../layout/util";
export const newCardModel = (options: {
tab: Tab,
@ -13,7 +14,7 @@ export const newCardModel = (options: {
}
}) => {
let editor: Protyle;
const custom = new Custom({
const customObj = new Custom({
type: "siyuan-card",
tab: options.tab,
data: options.data,
@ -66,5 +67,8 @@ export const newCardModel = (options: {
});
}
});
return custom;
customObj.element.addEventListener("click", () => {
setPanelFocus(customObj.element.parentElement.parentElement);
});
return customObj;
};

View file

@ -325,10 +325,6 @@ export class Backlink extends Model {
});
this.searchBacklinks(true);
if (this.type === "pin") {
setPanelFocus(this.element);
}
}
private setFocus() {

View file

@ -146,7 +146,6 @@ export class Bookmark extends Model {
});
this.update();
setPanelFocus(this.element);
}
public update() {

View file

@ -1,9 +1,8 @@
import {Tab} from "../Tab";
import {setPanelFocus} from "../util";
import {Model} from "../Model";
export class Custom extends Model {
private element: Element;
public element: Element;
public data: any;
public type: string;
public init: () => void;
@ -27,9 +26,6 @@ export class Custom extends Model {
}
this.element = options.tab.panelElement;
this.data = options.data;
this.element.addEventListener("click", () => {
setPanelFocus(this.element.parentElement.parentElement);
});
this.init = options.init;
this.destroy = options.destroy;
this.resize = options.resize;

View file

@ -602,7 +602,6 @@ export class Files extends Model {
newElement.classList.remove("dragover", "dragover__bottom", "dragover__top");
});
this.init();
setPanelFocus(this.element.parentElement);
if (window.siyuan.config.openHelp) {
// 需等待链接建立,不能放在 ongetconfig 中
mountHelp();

View file

@ -354,9 +354,6 @@ export class Graph extends Model {
});
});
this.searchGraph(options.type !== "global");
if (this.type !== "local") {
setPanelFocus(this.element);
}
}
private reset(conf: IGraphCommon & ({ dailyNote: boolean } | { minRefs: number, dailyNote: boolean })) {

View file

@ -163,9 +163,6 @@ export class Inbox extends Model {
}
});
this.update();
/// #if !MOBILE
setPanelFocus(this.element);
/// #endif
}
private back() {

View file

@ -169,10 +169,6 @@ export class Outline extends Model {
}, response => {
this.update(response);
});
if (this.type === "pin") {
setPanelFocus(options.tab.panelElement);
}
}
public updateDocTitle(ial?: IObject) {

View file

@ -181,7 +181,6 @@ export class Tag extends Model {
}
});
this.update();
setPanelFocus(this.element);
}
public update() {

View file

@ -15,16 +15,26 @@ import {Protyle} from "../../protyle";
import {Backlink} from "./Backlink";
import {resetFloatDockSize} from "./util";
import {hasClosestByClassName} from "../../protyle/util/hasClosest";
import {App} from "../../index";
import {Plugin} from "../../plugin";
export class Dock {
public element: HTMLElement;
public layout: Layout;
private position: TDockPosition;
private app: App;
public resizeElement: HTMLElement;
public pin = true;
public data: { [key: string]: Model | boolean };
constructor(options: { data: { pin: boolean, data: IDockTab[][] }, position: TDockPosition }) {
constructor(options: {
app: App,
data: {
pin: boolean,
data: IDockTab[][]
},
position: TDockPosition
}) {
switch (options.position) {
case "Left":
this.layout = window.siyuan.layout.layout.children[0].children[0] as Layout;
@ -45,6 +55,7 @@ export class Dock {
this.layout.element.insertAdjacentHTML("beforeend", "<div class=\"layout__dockresize\"></div>");
break;
}
this.app = options.app;
this.element = document.getElementById("dock" + options.position);
const dockClass = options.position === "Bottom" ? ' class="fn__flex"' : "";
this.element.innerHTML = `<div${dockClass}></div><div class="fn__flex-1"></div><div${dockClass}></div>`;
@ -77,13 +88,13 @@ export class Dock {
this.resizeElement.classList.add("fn__none");
} else {
activeElements.forEach(item => {
this.toggleModel(item.getAttribute("data-type") as TDockType, true);
this.toggleModel(item.getAttribute("data-type"), true);
});
}
this.element.addEventListener("click", (event) => {
let target = event.target as HTMLElement;
while (target && !target.isEqualNode(this.element)) {
const type = target.getAttribute("data-type") as TDockType;
const type = target.getAttribute("data-type");
if (type) {
this.toggleModel(type, false, true);
event.preventDefault();
@ -256,7 +267,7 @@ export class Dock {
this.layout.element.querySelector(".layout__tab--active")?.classList.remove("layout__tab--active");
}
public toggleModel(type: TDockType, show = false, close = false) {
public toggleModel(type: string, show = false, close = false) {
if (!type) {
return;
}
@ -389,10 +400,27 @@ export class Dock {
}
});
break;
default:
tab = new Tab({
callback: (tab: Tab) => {
let customModel;
this.app.plugins.find((item: Plugin) => {
if (item.docks[type]) {
customModel = item.docks[type].model({tab});
return true;
}
});
if (customModel) {
tab.addModel(customModel);
}
}
});
break;
}
wnd.addTab(tab);
target.setAttribute("data-id", tab.id);
this.data[type] = tab.model;
setPanelFocus(tab.panelElement);
} else {
// tab 切换
Array.from(wnd.element.querySelector(".layout-tab-container").children).forEach(item => {
@ -482,7 +510,7 @@ export class Dock {
public add(index: number, sourceElement: Element) {
sourceElement.setAttribute("data-height", "");
sourceElement.setAttribute("data-width", "");
const type = sourceElement.getAttribute("data-type") as TDockType;
const type = sourceElement.getAttribute("data-type");
const sourceDock = getDockByType(type);
if (sourceDock.element.querySelectorAll(".dock__item").length === 2) {
sourceDock.element.classList.add("fn__none");
@ -569,7 +597,7 @@ export class Dock {
private genButton(data: IDockTab[], index: number) {
let html = "";
data.forEach(item => {
html += `<span data-height="${item.size.height}" data-width="${item.size.width}" data-type="${item.type}" data-index="${index}" data-hotkeylangid="${item.hotkeyLangId}" class="dock__item${item.show ? " dock__item--active" : ""} b3-tooltips b3-tooltips__${this.getClassDirect(index)}" aria-label="${window.siyuan.languages[item.hotkeyLangId] + " " + updateHotkeyTip(window.siyuan.config.keymap.general[item.hotkeyLangId].custom)}${window.siyuan.languages.dockTip}">
html += `<span data-height="${item.size.height}" data-width="${item.size.width}" data-type="${item.type}" data-index="${index}" data-hotkey="${item.hotkey || ""}" data-hotkeyLangId="${item.hotkeyLangId || ""}" data-title="${item.title}" class="dock__item${item.show ? " dock__item--active" : ""} b3-tooltips b3-tooltips__${this.getClassDirect(index)}" aria-label="${item.title} ${item.hotkey ? updateHotkeyTip(item.hotkey) : ""}${window.siyuan.languages.dockTip}">
<svg><use xlink:href="#${item.icon}"></use></svg>
</span>`;
this.data[item.type] = true;

View file

@ -126,7 +126,7 @@ export const initStatus = (isWindow = false) => {
event.stopPropagation();
break;
} else if (target.classList.contains("b3-menu__item")) {
const type = target.getAttribute("data-type") as TDockType;
const type = target.getAttribute("data-type");
getDockByType(type).toggleModel(type);
if (type === "file" && getSelection().rangeCount > 0) {
const range = getSelection().getRangeAt(0);

View file

@ -55,9 +55,9 @@ export const setPanelFocus = (element: Element) => {
element.classList.add("layout__wnd--active");
} else {
element.classList.add("layout__tab--active");
["file", "inbox", "backlink", "tag", "bookmark", "graph", "globalGraph", "outline"].find(item => {
if (element.classList.contains("sy__" + item)) {
document.querySelector(`.dock__item[data-type="${item}"]`).classList.add("dock__item--activefocus");
Array.from(element.classList).find(item => {
if (item.startsWith("sy__")) {
document.querySelector(`.dock__item[data-type="${item.substring(4)}"]`).classList.add("dock__item--activefocus");
return true;
}
});
@ -71,7 +71,7 @@ export const setPanelFocus = (element: Element) => {
}
};
export const getDockByType = (type: TDockType) => {
export const getDockByType = (type: string) => {
if (!window.siyuan.layout.leftDock) {
return undefined;
}
@ -154,14 +154,16 @@ const dockToJSON = (dock: Dock) => {
const data: IDockTab[] = [];
dock.element.querySelectorAll(`span[data-index="${index}"]`).forEach(item => {
data.push({
type: item.getAttribute("data-type") as TDockType,
type: item.getAttribute("data-type"),
size: {
height: parseInt(item.getAttribute("data-height")),
width: parseInt(item.getAttribute("data-width")),
},
title: item.getAttribute("data-title"),
show: item.classList.contains("dock__item--active"),
icon: item.querySelector("use").getAttribute("xlink:href").substring(1),
hotkeyLangId: item.getAttribute("data-hotkeylangid")
hotkey: item.getAttribute("data-hotkey") || "",
hotkeyLangId: item.getAttribute("data-hotkeyLangId") || ""
});
});
return data;
@ -237,11 +239,56 @@ export const exportLayout = (options: {
});
};
const JSONToDock = (json: any) => {
const pushPluginDock = (app: App, dockItem: IDockTab[], position: TPluginDockPosition) => {
const needPushData: { [key: string]: IPluginDockTab } = {}
app.plugins.forEach((pluginItem) => {
let isExist = false;
dockItem.forEach(existSubItem => {
if (Object.keys(pluginItem.docks).includes(existSubItem.type)) {
isExist = true;
}
})
if (!isExist) {
Object.keys(pluginItem.docks).forEach(pluginDockKey => {
if (pluginItem.docks[pluginDockKey].config.position === position) {
needPushData[pluginDockKey] = pluginItem.docks[pluginDockKey].config;
}
})
}
})
dockItem.forEach(existSubItem => {
if (existSubItem.hotkeyLangId) {
existSubItem.title = window.siyuan.languages[existSubItem.hotkeyLangId]
existSubItem.hotkey = window.siyuan.config.keymap.general[existSubItem.hotkeyLangId].custom
}
})
Object.keys(needPushData).forEach(key => {
const item = needPushData[key];
dockItem.push({
type: key,
size: item.size,
show: false,
icon: item.icon,
hotkey: item.hotkey || "",
title: item.title,
});
})
}
const JSONToDock = (json: any, app: App) => {
json.left.data.forEach((existItem: IDockTab[], index: number) => {
pushPluginDock(app, existItem, index === 0 ? "LeftTop" : "LeftBottom");
});
json.right.data.forEach((existItem: IDockTab[], index: number) => {
pushPluginDock(app, existItem, index === 0 ? "RightTop" : "RightBottom");
});
json.bottom.data.forEach((existItem: IDockTab[], index: number) => {
pushPluginDock(app, existItem, index === 0 ? "BottomLeft" : "BottomRight");
});
window.siyuan.layout.centerLayout = window.siyuan.layout.layout.children[0].children[1] as Layout;
window.siyuan.layout.leftDock = new Dock({position: "Left", data: json.left});
window.siyuan.layout.rightDock = new Dock({position: "Right", data: json.right});
window.siyuan.layout.bottomDock = new Dock({position: "Bottom", data: json.bottom});
window.siyuan.layout.leftDock = new Dock({position: "Left", data: json.left, app});
window.siyuan.layout.rightDock = new Dock({position: "Right", data: json.right, app});
window.siyuan.layout.bottomDock = new Dock({position: "Bottom", data: json.bottom, app});
};
export const JSONToCenter = (app: App, json: ILayoutJSON, layout?: Layout | Wnd | Tab | Model, isStart = false) => {
@ -387,7 +434,7 @@ export const JSONToCenter = (app: App, json: ILayoutJSON, layout?: Layout | Wnd
export const JSONToLayout = (app: App, isStart: boolean) => {
JSONToCenter(app, window.siyuan.config.uiLayout.layout, undefined, isStart);
JSONToDock(window.siyuan.config.uiLayout);
JSONToDock(window.siyuan.config.uiLayout, app);
// 启动时不打开页签,需要移除没有钉住的页签
if (window.siyuan.config.fileTree.closeTabsOnStart && isStart) {
getAllTabs().forEach(item => {

View file

@ -58,8 +58,8 @@ export const workspaceMenu = (app:App, rect: DOMRect) => {
getAllDocks().forEach(item => {
dockMenu.push({
icon: item.icon,
accelerator: window.siyuan.config.keymap.general[item.hotkeyLangId].custom,
label: window.siyuan.languages[item.hotkeyLangId],
accelerator: item.hotkey,
label: item.title,
click() {
getDockByType(item.type).toggleModel(item.type);
}

View file

@ -9,6 +9,7 @@ import {isMobile} from "../util/functions";
/// #if !MOBILE
import {openFile} from "../editor/util";
/// #endif
import {updateHotkeyTip} from "../protyle/util/compatibility";
export class Menu {
private menu: SiyuanMenu;
@ -82,6 +83,7 @@ openTab = openFile;
export const API = {
confirm: confirmDialog,
showMessage,
adaptHotkey: updateHotkeyTip,
fetchPost,
fetchSyncPost,
fetchGet,

View file

@ -6,6 +6,8 @@ import {isMobile, isWindow} from "../util/functions";
import {Custom} from "../layout/dock/Custom";
/// #endif
import {Tab} from "../layout/Tab";
import {getDockByType, setPanelFocus} from "../layout/util";
import {hasClosestByAttribute} from "../protyle/util/hasClosest";
export class Plugin {
public i18n: IObject;
@ -17,6 +19,14 @@ export class Plugin {
[key: string]: (options: { tab: Tab, data: any }) => Custom
/// #endif
} = {};
public docks: {
/// #if !MOBILE
[key: string]: {
config: IPluginDockTab,
model: (options: { tab: Tab }) => Custom
}
/// #endif
} = {};
constructor(options: {
app: App,
@ -99,7 +109,7 @@ export class Plugin {
});
}
public createTab(options: {
public addTab(options: {
type: string,
destroy?: () => void,
resize?: () => void,
@ -108,7 +118,8 @@ export class Plugin {
}) {
/// #if !MOBILE
const type2 = this.name + options.type;
this.models[type2] = (arg: { data: any, tab: Tab }) => new Custom({
this.models[type2] = (arg: { data: any, tab: Tab }) => {
const customObj = new Custom({
tab: arg.tab,
type: type2,
data: arg.data,
@ -117,7 +128,49 @@ export class Plugin {
resize: options.resize,
update: options.update,
});
customObj.element.addEventListener("click", () => {
setPanelFocus(customObj.element.parentElement.parentElement);
});
return customObj;
};
return this.models[type2];
/// #endif
}
public addDock(options: {
config: IPluginDockTab,
data: any,
type: string,
destroy?: () => void,
resize?: () => void,
update?: () => void,
init: () => void
}) {
/// #if !MOBILE
const type2 = this.name + options.type;
this.docks[type2] = {
config: options.config,
model: (arg: { tab: Tab }) => {
const customObj = new Custom({
tab: arg.tab,
type: type2,
data: options.data,
init: options.init,
destroy: options.destroy,
resize: options.resize,
update: options.update,
})
customObj.element.addEventListener("click", (event: MouseEvent) => {
setPanelFocus(customObj.element);
if (hasClosestByAttribute(event.target as HTMLElement, "data-type", "min")) {
getDockByType(type2).toggleModel(type2);
}
});
customObj.element.classList.add("sy__" + type2);
return customObj
}
};
return this.docks[type2];
/// #endif
}
}

View file

@ -2,16 +2,7 @@ type TLayout = "normal" | "bottom" | "left" | "right" | "center"
type TSearchFilter = "mathBlock" | "table" | "blockquote" | "superBlock" | "paragraph" | "document" | "heading"
| "list" | "listItem" | "codeBlock" | "htmlBlock"
type TDirection = "lr" | "tb"
type TDockType =
"file"
| "outline"
| "bookmark"
| "tag"
| "graph"
| "globalGraph"
| "backlink"
| "backlinkOld"
| "inbox"
type TPluginDockPosition = "LeftTop" | "LeftBottom" | "RightTop" | "RightBottom" | "BottomLeft" | "BottomRight"
type TDockPosition = "Left" | "Right" | "Bottom"
type TWS = "main" | "filetree" | "protyle"
type TEditorMode = "preview" | "wysiwyg"
@ -298,11 +289,21 @@ declare interface ILayoutJSON extends ILayoutOptions {
}
declare interface IDockTab {
type: TDockType;
type: string;
size: { width: number, height: number }
show: boolean
icon: string
hotkeyLangId: string
title: string
hotkey?: string
hotkeyLangId?: string // 常量中无法存变量
}
declare interface IPluginDockTab {
position: TPluginDockPosition,
size: { width: number, height: number },
icon: string,
hotkey?: string,
title: string,
}
declare interface IOpenFileOptions {