import {
Plugin,
showMessage,
confirm,
Dialog,
Menu,
openTab,
adaptHotkey,
getFrontend,
getBackend,
IModel,
Setting
} from "siyuan";
import "@/index.scss";
import HelloExample from "@/hello.svelte";
import SettingPannel from "@/libs/setting-panel.svelte";
const STORAGE_NAME = "menu-config";
const TAB_TYPE = "custom_tab";
const DOCK_TYPE = "dock_tab";
export default class PluginSample extends Plugin {
private customTab: () => IModel;
private isMobile: boolean;
async onload() {
this.data[STORAGE_NAME] = {readonlyText: "Readonly"};
console.log("loading plugin-sample", this.i18n);
const frontEnd = getFrontend();
this.isMobile = frontEnd === "mobile" || frontEnd === "browser-mobile";
// 图标的制作参见帮助文档
this.addIcons(`
`);
const topBarElement = this.addTopBar({
icon: "iconFace",
title: this.i18n.addTopBarIcon,
position: "right",
callback: () => {
let rect = topBarElement.getBoundingClientRect();
// 如果被隐藏,则使用更多按钮
if (rect.width === 0) {
rect = document.querySelector("#barMore").getBoundingClientRect();
}
this.addMenu(rect);
}
});
const statusIconTemp = document.createElement("template");
statusIconTemp.innerHTML = `
`;
statusIconTemp.content.firstElementChild.addEventListener("click", () => {
confirm("⚠️", this.i18n.confirmRemove.replace("${name}", this.name), () => {
this.removeData(STORAGE_NAME).then(() => {
this.data[STORAGE_NAME] = {readonlyText: "Readonly"};
showMessage(`[${this.name}]: ${this.i18n.removedData}`);
});
});
});
this.addStatusBar({
element: statusIconTemp.content.firstElementChild as HTMLElement,
});
let tabDiv = document.createElement("div");
new HelloExample({
target: tabDiv,
props: {
name: this.i18n.name,
i18n: this.i18n.hello
}
});
this.customTab = this.addTab({
type: TAB_TYPE,
init() {
this.element.appendChild(tabDiv);
console.log(this.element);
},
destroy() {
console.log("destroy tab:", TAB_TYPE);
}
});
this.addCommand({
langKey: "showDialog",
hotkey: "⇧⌘M",
callback: () => {
this.showDialog();
}
});
this.addDock({
config: {
position: "LeftBottom",
size: {width: 200, height: 0},
icon: "iconSaving",
title: "Custom Dock",
},
data: {
text: "This is my custom dock"
},
type: DOCK_TYPE,
init() {
this.element.innerHTML = ``;
},
destroy() {
console.log("destroy dock:", DOCK_TYPE);
}
});
const textareaElement = document.createElement("textarea");
this.setting = new Setting({
confirmCallback: () => {
this.saveData(STORAGE_NAME, {readonlyText: textareaElement.value});
}
})
this.setting.addItem({
title: "Readonly text",
createActionElement: () => {
textareaElement.className = "b3-text-field fn__block";
textareaElement.placeholder = "Readonly text in the menu";
textareaElement.value = this.data[STORAGE_NAME].readonlyText;
return textareaElement;
},
})
const btnaElement = document.createElement("button");
btnaElement.className = "b3-button b3-button--outline fn__flex-center";
btnaElement.textContent = "Open";
btnaElement.addEventListener("click", () => {
window.open("https://github.com/siyuan-note/plugin-sample-vite-svelte")
});
this.setting.addItem({
title: "Open plugin url",
description: "Open plugin url in browser",
actionElement: btnaElement,
})
console.log(this.i18n.helloPlugin);
}
onLayoutReady() {
this.loadData(STORAGE_NAME);
console.log(`frontend: ${getFrontend()}; backend: ${getBackend()}`);
}
onunload() {
console.log(this.i18n.byePlugin);
showMessage("Goodbye SiYuan Plugin");
console.log("onunload");
}
/**
* A custom setting pannel provided by svelte
*/
openDIYSetting(): void {
let dialog = new Dialog({
title: "SettingPannel",
content: ``,
width: "600px",
destroyCallback: (options) => {
console.log("destroyCallback", options);
//You'd better destroy the component when the dialog is closed
pannel.$destroy();
}
});
let pannel = new SettingPannel({
target: dialog.element.querySelector("#SettingPanel"),
});
}
private eventBusLog({detail}: any) {
console.log(detail);
}
private blockIconEvent({detail}: any) {
const ids: string[] = [];
detail.blockElements.forEach((item: HTMLElement) => {
ids.push(item.getAttribute("data-node-id"));
});
detail.menu.addItem({
iconHTML: "",
type: "readonly",
label: "IDs
" + ids.join("
"),
});
}
private showDialog() {
let dialog = new Dialog({
title: "Hello World",
content: ``,
width: this.isMobile ? "92vw" : "720px",
destroyCallback(options) {
// hello.$destroy();
},
});
let hello = new HelloExample({
target: dialog.element.querySelector("#helloPanel"),
props: {
name: this.i18n.name,
i18n: this.i18n.hello
}
});
}
private addMenu(rect: DOMRect) {
const menu = new Menu("topBarSample", () => {
console.log(this.i18n.byeMenu);
});
menu.addItem({
icon: "iconInfo",
label: "Dialog",
accelerator: this.commands[0].customHotkey,
click: () => this.showDialog()
});
if (!this.isMobile) {
menu.addItem({
icon: "iconLayoutBottom",
label: "Open Custom Tab",
click: () => {
const tab = openTab({
app: this.app,
custom: {
icon: "iconFace",
title: "Custom Tab",
data: {
text: "This is my custom tab",
},
fn: this.customTab
},
});
console.log(tab)
}
});
menu.addItem({
icon: "iconLayoutBottom",
label: "Open Asset Tab(open help first)",
click: () => {
const tab = openTab({
app: this.app,
asset: {
path: "assets/paragraph-20210512165953-ag1nib4.svg"
}
});
console.log(tab)
}
});
menu.addItem({
icon: "iconLayoutBottom",
label: "Open Doc Tab(open help first)",
click: async () => {
const tab = await openTab({
app: this.app,
doc: {
id: "20200812220555-lj3enxa",
}
});
console.log(tab)
}
});
menu.addItem({
icon: "iconLayoutBottom",
label: "Open Search Tab",
click: () => {
const tab = openTab({
app: this.app,
search: {
k: "SiYuan"
}
});
console.log(tab)
}
});
menu.addItem({
icon: "iconLayoutBottom",
label: "Open Card Tab",
click: () => {
const tab = openTab({
app: this.app,
card: {
type: "all"
}
});
console.log(tab)
}
});
menu.addItem({
icon: "iconLayout",
label: "Open Float Layer(open help first)",
click: () => {
this.addFloatLayer({
ids: ["20210428212840-8rqwn5o", "20201225220955-l154bn4"],
defIds: ["20230415111858-vgohvf3", "20200813131152-0wk5akh"],
x: window.innerWidth - 768 - 120,
y: 32
});
}
});
}
menu.addItem({
icon: "iconScrollHoriz",
label: "Event Bus",
type: "submenu",
submenu: [{
icon: "iconSelect",
label: "On ws-main",
click: () => {
this.eventBus.on("ws-main", this.eventBusLog);
}
}, {
icon: "iconClose",
label: "Off ws-main",
click: () => {
this.eventBus.off("ws-main", this.eventBusLog);
}
}, {
icon: "iconSelect",
label: "On click-blockicon",
click: () => {
this.eventBus.on("click-blockicon", this.blockIconEvent);
}
}, {
icon: "iconClose",
label: "Off click-blockicon",
click: () => {
this.eventBus.off("click-blockicon", this.blockIconEvent);
}
}, {
icon: "iconSelect",
label: "On click-pdf",
click: () => {
this.eventBus.on("click-pdf", this.eventBusLog);
}
}, {
icon: "iconClose",
label: "Off click-pdf",
click: () => {
this.eventBus.off("click-pdf", this.eventBusLog);
}
}, {
icon: "iconSelect",
label: "On click-editorcontent",
click: () => {
this.eventBus.on("click-editorcontent", this.eventBusLog);
}
}, {
icon: "iconClose",
label: "Off click-editorcontent",
click: () => {
this.eventBus.off("click-editorcontent", this.eventBusLog);
}
}, {
icon: "iconSelect",
label: "On click-editortitleicon",
click: () => {
this.eventBus.on("click-editortitleicon", this.eventBusLog);
}
}, {
icon: "iconClose",
label: "Off click-editortitleicon",
click: () => {
this.eventBus.off("click-editortitleicon", this.eventBusLog);
}
}, {
icon: "iconSelect",
label: "On open-noneditableblock",
click: () => {
this.eventBus.on("open-noneditableblock", this.eventBusLog);
}
}, {
icon: "iconClose",
label: "Off open-noneditableblock",
click: () => {
this.eventBus.off("open-noneditableblock", this.eventBusLog);
}
}, {
icon: "iconSelect",
label: "On loaded-protyle",
click: () => {
this.eventBus.on("loaded-protyle", this.eventBusLog);
}
}, {
icon: "iconClose",
label: "Off loaded-protyle",
click: () => {
this.eventBus.off("loaded-protyle", this.eventBusLog);
}
}]
});
menu.addSeparator();
menu.addItem({
icon: "iconSettings",
label: "Official Setting Dialog",
click: () => {
this.openSetting();
}
});
menu.addItem({
icon: "iconSettings",
label: "A custom setting dialog (by svelte)",
click: () => {
this.openDIYSetting();
}
});
menu.addItem({
icon: "iconSparkles",
label: this.data[STORAGE_NAME].readonlyText || "Readonly",
type: "readonly",
});
if (this.isMobile) {
menu.fullscreen();
} else {
menu.open({
x: rect.right,
y: rect.bottom,
isLeft: true,
});
}
}
}