mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-20 00:20:12 +01:00
This commit is contained in:
parent
875f00398e
commit
99725ea21d
14 changed files with 122 additions and 40 deletions
|
|
@ -53,6 +53,7 @@ import {reloadProtyle} from "../protyle/util/reload";
|
|||
import {fullscreen} from "../protyle/breadcrumb/action";
|
||||
import {setPadding} from "../protyle/ui/initUI";
|
||||
import {openRecentDocs} from "../business/openRecentDocs";
|
||||
import {App} from "../index";
|
||||
|
||||
const getRightBlock = (element: HTMLElement, x: number, y: number) => {
|
||||
let index = 1;
|
||||
|
|
@ -95,7 +96,7 @@ const switchDialogEvent = (event: MouseEvent, switchDialog: Dialog) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const globalShortcut = () => {
|
||||
export const globalShortcut = (app: App) => {
|
||||
document.body.addEventListener("mouseleave", () => {
|
||||
if (window.siyuan.layout.leftDock) {
|
||||
window.siyuan.layout.leftDock.hideDock();
|
||||
|
|
@ -630,7 +631,7 @@ export const globalShortcut = () => {
|
|||
return;
|
||||
}
|
||||
if (!isTabWindow && !window.siyuan.config.readonly && matchHotKey(window.siyuan.config.keymap.general.config.custom, event)) {
|
||||
openSetting();
|
||||
openSetting(app);
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import {initBar} from "../layout/topBar";
|
|||
import {setProxy} from "../config/util/setProxy";
|
||||
import {openChangelog} from "./openChangelog";
|
||||
import {getIdFromSYProtocol, isSYProtocol} from "../util/pathName";
|
||||
import {App} from "../index";
|
||||
|
||||
const matchKeymap = (keymap: Record<string, IKeymapItem>, key1: "general" | "editor", key2?: "general" | "insert" | "heading" | "list" | "table") => {
|
||||
if (key1 === "general") {
|
||||
|
|
@ -84,7 +85,7 @@ const hasKeymap = (keymap: Record<string, IKeymapItem>, key1: "general" | "edito
|
|||
return match;
|
||||
};
|
||||
|
||||
export const onGetConfig = (isStart: boolean) => {
|
||||
export const onGetConfig = (isStart: boolean, app:App) => {
|
||||
const matchKeymap1 = matchKeymap(Constants.SIYUAN_KEYMAP.general, "general");
|
||||
const matchKeymap2 = matchKeymap(Constants.SIYUAN_KEYMAP.editor.general, "editor", "general");
|
||||
const matchKeymap3 = matchKeymap(Constants.SIYUAN_KEYMAP.editor.insert, "editor", "insert");
|
||||
|
|
@ -130,7 +131,7 @@ export const onGetConfig = (isStart: boolean) => {
|
|||
if (!window.siyuan.config.uiLayout || (window.siyuan.config.uiLayout && !window.siyuan.config.uiLayout.left)) {
|
||||
window.siyuan.config.uiLayout = Constants.SIYUAN_EMPTY_LAYOUT;
|
||||
}
|
||||
globalShortcut();
|
||||
globalShortcut(app);
|
||||
fetchPost("/api/system/getEmojiConf", {}, response => {
|
||||
window.siyuan.emojis = response.data as IEmoji[];
|
||||
try {
|
||||
|
|
@ -140,7 +141,7 @@ export const onGetConfig = (isStart: boolean) => {
|
|||
resetLayout();
|
||||
}
|
||||
});
|
||||
initBar();
|
||||
initBar(app);
|
||||
setProxy();
|
||||
initStatus();
|
||||
initWindow();
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import * as path from "path";
|
|||
import {isBrowser} from "../util/functions";
|
||||
import {setStorageVal} from "../protyle/util/compatibility";
|
||||
import {hasClosestByAttribute, hasClosestByClassName} from "../protyle/util/hasClosest";
|
||||
import {Plugin} from "../plugin";
|
||||
import {App} from "../index";
|
||||
|
||||
export const bazaar = {
|
||||
element: undefined as Element,
|
||||
|
|
@ -209,7 +211,7 @@ export const bazaar = {
|
|||
</div>
|
||||
</div>`;
|
||||
},
|
||||
_genMyHTML(bazaarType: TBazaarType) {
|
||||
_genMyHTML(bazaarType: TBazaarType, app: App) {
|
||||
let url = "/api/bazaar/getInstalledTheme";
|
||||
if (bazaarType === "icons") {
|
||||
url = "/api/bazaar/getInstalledIcon";
|
||||
|
|
@ -236,6 +238,16 @@ export const bazaar = {
|
|||
repoHash: item.repoHash,
|
||||
downloaded: true
|
||||
};
|
||||
let hasSetting = false;
|
||||
if (bazaarType === "plugins") {
|
||||
app.plugins.find((item: Plugin) => {
|
||||
if (item.name === dataObj.name) {
|
||||
// @ts-ignore
|
||||
hasSetting = item.__proto__.hasOwnProperty("openSetting");
|
||||
return true;
|
||||
}
|
||||
})
|
||||
}
|
||||
html += `<div data-obj='${JSON.stringify(dataObj)}' class="b3-card${item.current ? " b3-card--current" : ""}">
|
||||
<div class="b3-card__img"><img src="${item.iconURL}" onerror="this.src='${item.previewURLThumb}'"/></div>
|
||||
<div class="fn__flex-1 fn__flex-column">
|
||||
|
|
@ -247,6 +259,10 @@ export const bazaar = {
|
|||
<div class="b3-card__actions">
|
||||
${item.preferredFunding ? `<a target="_blank" href="${item.preferredFunding}" class="b3-tooltips b3-tooltips__ne block__icon block__icon--show" aria-label="${window.siyuan.languages.sponsor} ${item.preferredFunding}"><svg class="ft__pink"><use xlink:href="#iconHeart"></use></svg></a>` : ""}
|
||||
<div class="fn__flex-1"></div>
|
||||
<span class="b3-tooltips b3-tooltips__nw block__icon block__icon--show${hasSetting ? "" : " fn__none"}" data-type="setting" aria-label="${window.siyuan.languages.config}">
|
||||
<svg><use xlink:href="#iconSettings"></use></svg>
|
||||
</span>
|
||||
<span class="fn__space"></span>
|
||||
<span class="b3-tooltips b3-tooltips__nw block__icon block__icon--show" data-type="uninstall" aria-label="${window.siyuan.languages.uninstall}">
|
||||
<svg><use xlink:href="#iconTrashcan"></use></svg>
|
||||
</span>
|
||||
|
|
@ -396,8 +412,8 @@ export const bazaar = {
|
|||
}
|
||||
readmeElement.classList.add("config-bazaar__readme--show");
|
||||
},
|
||||
bindEvent() {
|
||||
this._genMyHTML("themes");
|
||||
bindEvent(app: App) {
|
||||
this._genMyHTML("themes", app);
|
||||
bazaar.element.firstElementChild.addEventListener("click", (event) => {
|
||||
let target = event.target as HTMLElement;
|
||||
const dataElement = hasClosestByAttribute(target, "data-obj", null);
|
||||
|
|
@ -429,7 +445,7 @@ export const bazaar = {
|
|||
}
|
||||
});
|
||||
target.classList.remove("b3-button--outline");
|
||||
this._genMyHTML(type.replace("my", "").toLowerCase() + "s" as TBazaarType);
|
||||
this._genMyHTML(type.replace("my", "").toLowerCase() + "s" as TBazaarType, app);
|
||||
}
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
|
@ -462,7 +478,7 @@ export const bazaar = {
|
|||
exportLayout(true);
|
||||
return;
|
||||
}
|
||||
bazaar._genMyHTML(bazaarType);
|
||||
bazaar._genMyHTML(bazaarType, app);
|
||||
bazaar._onBazaar(response, bazaarType, ["themes", "icons"].includes(bazaarType));
|
||||
});
|
||||
}
|
||||
|
|
@ -494,7 +510,7 @@ export const bazaar = {
|
|||
update: true,
|
||||
}, response => {
|
||||
// 更新主题后不需要对该主题进行切换 https://github.com/siyuan-note/siyuan/issues/4966
|
||||
this._genMyHTML(bazaarType);
|
||||
this._genMyHTML(bazaarType, app);
|
||||
bazaar._onBazaar(response, bazaarType, ["icons"].includes(bazaarType));
|
||||
// https://github.com/siyuan-note/siyuan/issues/5411
|
||||
if (bazaarType === "themes" && (
|
||||
|
|
@ -536,7 +552,7 @@ export const bazaar = {
|
|||
fetchPost(url, {
|
||||
packageName
|
||||
}, response => {
|
||||
this._genMyHTML(bazaarType);
|
||||
this._genMyHTML(bazaarType, app);
|
||||
bazaar._onBazaar(response, bazaarType, ["themes", "icons"].includes(bazaarType));
|
||||
// TODO destroy plugin
|
||||
if (bazaarType === "plugins") {
|
||||
|
|
@ -555,7 +571,7 @@ export const bazaar = {
|
|||
fetchPost("/api/setting/setAppearance", Object.assign({}, window.siyuan.config.appearance, {
|
||||
icon: packageName,
|
||||
}), (appearanceResponse) => {
|
||||
this._genMyHTML(bazaarType);
|
||||
this._genMyHTML(bazaarType, app);
|
||||
fetchPost("/api/bazaar/getBazaarIcon", {}, response => {
|
||||
response.data.appearance = appearanceResponse.data;
|
||||
bazaar._onBazaar(response, "icons", true);
|
||||
|
|
@ -575,7 +591,7 @@ export const bazaar = {
|
|||
window.siyuan.config.appearance.themeJS) {
|
||||
exportLayout(true);
|
||||
} else {
|
||||
this._genMyHTML("themes");
|
||||
this._genMyHTML("themes", app);
|
||||
fetchPost("/api/bazaar/getBazaarTheme", {}, response => {
|
||||
response.data.appearance = appearanceResponse.data;
|
||||
bazaar._onBazaar(response, "themes", true);
|
||||
|
|
@ -587,6 +603,16 @@ export const bazaar = {
|
|||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
break;
|
||||
} else if (type === "setting") {
|
||||
app.plugins.find((item: Plugin) => {
|
||||
if (item.name === dataObj.name) {
|
||||
item.openSetting()
|
||||
return true
|
||||
}
|
||||
})
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
break;
|
||||
} else if (type === "plugin-enable") {
|
||||
const itemElement = hasClosestByClassName(target, "b3-card");
|
||||
if (itemElement) {
|
||||
|
|
|
|||
|
|
@ -13,8 +13,9 @@ import {query} from "./query";
|
|||
import {Dialog} from "../dialog";
|
||||
import {ai} from "./ai";
|
||||
import {flashcard} from "./flashcard";
|
||||
import {App} from "../index";
|
||||
|
||||
export const genItemPanel = (type: string, containerElement:Element) => {
|
||||
export const genItemPanel = (type: string, containerElement:Element, app: App) => {
|
||||
switch (type) {
|
||||
case "filetree":
|
||||
containerElement.innerHTML = fileTree.genHTML();
|
||||
|
|
@ -54,7 +55,7 @@ export const genItemPanel = (type: string, containerElement:Element) => {
|
|||
case "bazaar":
|
||||
bazaar.element = containerElement;
|
||||
containerElement.innerHTML = bazaar.genHTML();
|
||||
bazaar.bindEvent();
|
||||
bazaar.bindEvent(app);
|
||||
break;
|
||||
case "account":
|
||||
containerElement.innerHTML = account.genHTML();
|
||||
|
|
@ -81,7 +82,7 @@ export const genItemPanel = (type: string, containerElement:Element) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const openSetting = () => {
|
||||
export const openSetting = (app:App) => {
|
||||
const exitDialog = window.siyuan.dialogs.find((item) => {
|
||||
if (item.element.querySelector(".config__tab-container")) {
|
||||
item.destroy();
|
||||
|
|
@ -126,7 +127,7 @@ export const openSetting = () => {
|
|||
width: "90vw",
|
||||
});
|
||||
|
||||
initConfigSearch(dialog.element);
|
||||
initConfigSearch(dialog.element, app);
|
||||
(dialog.element.querySelector(".b3-dialog__container") as HTMLElement).style.maxWidth = "1280px";
|
||||
dialog.element.querySelectorAll(".b3-tab-bar .b3-list-item").forEach(item => {
|
||||
item.addEventListener("click", () => {
|
||||
|
|
@ -139,7 +140,7 @@ export const openSetting = () => {
|
|||
item.classList.add("b3-list-item--focus");
|
||||
containerElement.classList.remove("fn__none");
|
||||
if (containerElement.innerHTML === "" || type === "repos" || type === "bazaar") {
|
||||
genItemPanel(type, containerElement);
|
||||
genItemPanel(type, containerElement, app);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import {Constants} from "../constants";
|
||||
import {genItemPanel} from "./index";
|
||||
import {keymap} from "./keymap";
|
||||
import {App} from "../index";
|
||||
|
||||
const getLang = (keys: string[]) => {
|
||||
const langArray: string[] = [];
|
||||
|
|
@ -10,7 +11,7 @@ const getLang = (keys: string[]) => {
|
|||
return langArray;
|
||||
};
|
||||
|
||||
export const initConfigSearch = (element: HTMLElement) => {
|
||||
export const initConfigSearch = (element: HTMLElement, app: App) => {
|
||||
const configIndex = [
|
||||
// 编辑器
|
||||
getLang(["config", "fullWidth",
|
||||
|
|
@ -115,7 +116,7 @@ export const initConfigSearch = (element: HTMLElement) => {
|
|||
// 右侧面板过滤
|
||||
const panelElement = element.querySelector(`.config__tab-container[data-name="${type}"]`);
|
||||
if (panelElement.innerHTML === "") {
|
||||
genItemPanel(type, panelElement);
|
||||
genItemPanel(type, panelElement, app);
|
||||
}
|
||||
if (type === "keymap") {
|
||||
const searchElement = keymap.element.querySelector("#keymapInput") as HTMLInputElement;
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ export class App {
|
|||
fetchPost("/api/setting/getCloudUser", {}, userResponse => {
|
||||
window.siyuan.user = userResponse.data;
|
||||
loadPlugins(siyuanApp);
|
||||
onGetConfig(response.data.start);
|
||||
onGetConfig(response.data.start, siyuanApp);
|
||||
account.onSetaccount();
|
||||
resizeDrag();
|
||||
setTitle(window.siyuan.languages.siyuanNote);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {MenuItem} from "../menus/Menu";
|
|||
import {setMode} from "../util/assets";
|
||||
import {openSetting} from "../config";
|
||||
import {openSearch} from "../search/spread";
|
||||
import {App} from "../index";
|
||||
|
||||
export const updateEditModeElement = () => {
|
||||
const target = document.querySelector("#barReadonly");
|
||||
|
|
@ -23,7 +24,7 @@ export const updateEditModeElement = () => {
|
|||
}
|
||||
};
|
||||
|
||||
export const initBar = () => {
|
||||
export const initBar = (app: App) => {
|
||||
const toolbarElement = document.getElementById("toolbar");
|
||||
toolbarElement.innerHTML = `
|
||||
<div id="barWorkspace" class="toolbar__item">
|
||||
|
|
@ -68,7 +69,7 @@ export const initBar = () => {
|
|||
event.stopPropagation();
|
||||
break;
|
||||
} else if (target.id === "barWorkspace") {
|
||||
workspaceMenu(target.getBoundingClientRect());
|
||||
workspaceMenu(app, target.getBoundingClientRect());
|
||||
event.stopPropagation();
|
||||
break;
|
||||
} else if (target.id === "barReadonly") {
|
||||
|
|
@ -113,7 +114,7 @@ export const initBar = () => {
|
|||
break;
|
||||
} else if (target.id === "toolbarVIP") {
|
||||
if (!window.siyuan.config.readonly) {
|
||||
const dialogSetting = openSetting();
|
||||
const dialogSetting = openSetting(app);
|
||||
dialogSetting.element.querySelector('.b3-tab-bar [data-name="account"]').dispatchEvent(new CustomEvent("click"));
|
||||
}
|
||||
event.stopPropagation();
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import {viewCards} from "../card/viewCards";
|
|||
import {Dialog} from "../dialog";
|
||||
import {hasClosestByClassName} from "../protyle/util/hasClosest";
|
||||
import {confirmDialog} from "../dialog/confirmDialog";
|
||||
import {App} from "../index";
|
||||
|
||||
const togglePinDock = (dock: Dock, icon: string) => {
|
||||
return {
|
||||
|
|
@ -34,7 +35,7 @@ const togglePinDock = (dock: Dock, icon: string) => {
|
|||
};
|
||||
};
|
||||
|
||||
export const workspaceMenu = (rect: DOMRect) => {
|
||||
export const workspaceMenu = (app:App, rect: DOMRect) => {
|
||||
if (!window.siyuan.menus.menu.element.classList.contains("fn__none") &&
|
||||
window.siyuan.menus.menu.element.getAttribute("data-name") === "barWorkspace") {
|
||||
window.siyuan.menus.menu.remove();
|
||||
|
|
@ -49,7 +50,7 @@ export const workspaceMenu = (rect: DOMRect) => {
|
|||
icon: "iconSettings",
|
||||
accelerator: window.siyuan.config.keymap.general.config.custom,
|
||||
click: () => {
|
||||
openSetting();
|
||||
openSetting(app);
|
||||
}
|
||||
}).element);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,26 @@
|
|||
import {App} from "../index";
|
||||
import {EventBus} from "./EventBus";
|
||||
import {fetchPost} from "../util/fetch";
|
||||
|
||||
export class Plugin {
|
||||
public i18n: IObject;
|
||||
public eventBus: EventBus;
|
||||
public data: any = {};
|
||||
public name: string;
|
||||
|
||||
constructor(options: {
|
||||
app: App,
|
||||
id: string,
|
||||
name: string,
|
||||
i18n: IObject
|
||||
}) {
|
||||
this.i18n = options.i18n;
|
||||
this.name = options.name;
|
||||
this.eventBus = new EventBus(options.name);
|
||||
}
|
||||
|
||||
public onload() {
|
||||
}
|
||||
|
||||
public addTopBar(options: {
|
||||
icon: string,
|
||||
title: string,
|
||||
|
|
@ -31,7 +37,36 @@ export class Plugin {
|
|||
return iconElement;
|
||||
}
|
||||
|
||||
public onload() {
|
||||
console.log("Hello, world!");
|
||||
public openSetting() {
|
||||
}
|
||||
|
||||
public loadData(storageName: string) {
|
||||
if (typeof this.data[storageName] === "undefined") {
|
||||
this.data[storageName] = "";
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
fetchPost("/api/file/getFile", {path: `/data/storage/petal/${this.name}/${storageName}`}, (response) => {
|
||||
if (response.code === 404) {
|
||||
this.data[storageName] = "";
|
||||
} else {
|
||||
this.data[storageName] = response;
|
||||
}
|
||||
resolve(this.data[storageName]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public saveData(storageName: string, data: any) {
|
||||
return new Promise((resolve) => {
|
||||
const pathString = `/data/storage/petal/${this.name}/${storageName}`;
|
||||
const file = new File([new Blob([data])], pathString.split('/').pop());
|
||||
const formData = new FormData();
|
||||
formData.append('path', pathString);
|
||||
formData.append('file', file);
|
||||
formData.append('isDir', "false");
|
||||
fetchPost("/api/file/putFile", formData, (response) => {
|
||||
resolve(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ const runCode = (code: string, sourceURL: string) => {
|
|||
export const loadPlugins = (app: App) => {
|
||||
fetchPost("/api/petal/loadPetals", {}, response => {
|
||||
let css = "";
|
||||
response.data.forEach((item: { id: string, name: string, js: string, css: string, i18n: IObject }) => {
|
||||
response.data.forEach((item: { name: string, js: string, css: string, i18n: IObject }) => {
|
||||
const exportsObj: { [key: string]: any } = {};
|
||||
const moduleObj = {exports: exportsObj};
|
||||
try {
|
||||
|
|
@ -39,7 +39,6 @@ export const loadPlugins = (app: App) => {
|
|||
const plugin = new pluginClass({
|
||||
app,
|
||||
name: item.name,
|
||||
id: item.id,
|
||||
i18n: item.i18n
|
||||
});
|
||||
app.plugins.push(plugin);
|
||||
|
|
|
|||
6
app/src/types/index.d.ts
vendored
6
app/src/types/index.d.ts
vendored
|
|
@ -388,12 +388,12 @@ declare interface IEditor {
|
|||
}
|
||||
|
||||
declare interface IWebSocketData {
|
||||
cmd: string
|
||||
cmd?: string
|
||||
callback?: string
|
||||
data: any
|
||||
data?: any
|
||||
msg: string
|
||||
code: number
|
||||
sid: string
|
||||
sid?: string
|
||||
}
|
||||
|
||||
declare interface IAppearance {
|
||||
|
|
|
|||
|
|
@ -28,8 +28,23 @@ export const fetchPost = (url: string, data?: any, cb?: (response: IWebSocketDat
|
|||
init.headers = headers;
|
||||
}
|
||||
fetch(url, init).then((response) => {
|
||||
if (response.status === 404) {
|
||||
cb({
|
||||
data: null,
|
||||
msg: response.statusText,
|
||||
code: response.status,
|
||||
});
|
||||
} else {
|
||||
if (response.headers.get("content-type").indexOf("application/json") > -1) {
|
||||
return response.json();
|
||||
} else {
|
||||
return response.text();
|
||||
}
|
||||
}
|
||||
}).then((response: IWebSocketData) => {
|
||||
if (!response) {
|
||||
return;
|
||||
}
|
||||
if (["/api/search/searchRefBlock", "/api/graph/getGraph", "/api/graph/getLocalGraph"].includes(url)) {
|
||||
if (response.data.reqId && window.siyuan.reqIds[url] && window.siyuan.reqIds[url] > response.data.reqId) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ class App {
|
|||
fetchPost("/api/setting/getCloudUser", {}, userResponse => {
|
||||
window.siyuan.user = userResponse.data;
|
||||
loadPlugins(siyuanApp);
|
||||
init();
|
||||
init(siyuanApp);
|
||||
setTitle(window.siyuan.languages.siyuanNote);
|
||||
initMessage();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -9,10 +9,11 @@ import {initAssets, setInlineStyle} from "../util/assets";
|
|||
import {renderSnippet} from "../config/util/snippets";
|
||||
import {getSearch} from "../util/functions";
|
||||
import {initWindow} from "../boot/onGetConfig";
|
||||
import {App} from "../index";
|
||||
|
||||
export const init = () => {
|
||||
export const init = (app:App) => {
|
||||
webFrame.setZoomFactor(window.siyuan.storage[Constants.LOCAL_ZOOM]);
|
||||
globalShortcut();
|
||||
globalShortcut(app);
|
||||
fetchPost("/api/system/getEmojiConf", {}, response => {
|
||||
window.siyuan.emojis = response.data as IEmoji[];
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue