A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
1import {fetchPost, fetchSyncPost} from "../../util/fetch";
2import {MenuItem} from "../../menus/Menu";
3import {copySubMenu, exportMd, movePathToMenu, openFileAttr, openFileWechatNotify,} from "../../menus/commonMenuItem";
4import {deleteFile} from "../../editor/deleteFile";
5import {updateHotkeyTip} from "../util/compatibility";
6/// #if !MOBILE
7import {openBacklink, openGraph, openOutline} from "../../layout/dock/util";
8import * as path from "path";
9/// #else
10import {openMobileFileById} from "../../mobile/editor";
11/// #endif
12import {Constants} from "../../constants";
13import {openCardByData} from "../../card/openCard";
14import {viewCards} from "../../card/viewCards";
15import {getDisplayName, getNotebookName, pathPosix, useShell} from "../../util/pathName";
16import {makeCard, quickMakeCard} from "../../card/makeCard";
17import {emitOpenMenu} from "../../plugin/EventBus";
18import * as dayjs from "dayjs";
19import {hideTooltip} from "../../dialog/tooltip";
20import {popSearch} from "../../mobile/menu/search";
21import {openSearch} from "../../search/spread";
22import {openDocHistory} from "../../history/doc";
23import {openNewWindowById} from "../../window/openNewWindow";
24import {transferBlockRef} from "../../menus/block";
25import {addEditorToDatabase} from "../render/av/addToDatabase";
26import {openFileById} from "../../editor/util";
27import {hasTopClosestByClassName} from "../util/hasClosest";
28
29export const openTitleMenu = (protyle: IProtyle, position: IPosition, from: string) => {
30 hideTooltip();
31 if (!window.siyuan.menus.menu.element.classList.contains("fn__none") &&
32 window.siyuan.menus.menu.element.getAttribute("data-name") === Constants.MENU_TITLE) {
33 window.siyuan.menus.menu.remove();
34 return;
35 }
36 fetchPost("/api/block/getDocInfo", {
37 id: protyle.block.rootID
38 }, (response) => {
39 window.siyuan.menus.menu.remove();
40 window.siyuan.menus.menu.element.setAttribute("data-name", Constants.MENU_TITLE);
41 const popoverElement = hasTopClosestByClassName(protyle.element, "block__popover", true);
42 window.siyuan.menus.menu.element.setAttribute("data-from", popoverElement ? popoverElement.dataset.level + "popover-" + from : "app-" + from);
43 window.siyuan.menus.menu.append(new MenuItem({
44 id: "copy",
45 label: window.siyuan.languages.copy,
46 icon: "iconCopy",
47 type: "submenu",
48 submenu: copySubMenu([protyle.block.rootID], true, undefined, protyle.block.showAll ? protyle.block.id : protyle.block.rootID)
49 }).element);
50 if (!protyle.disabled) {
51 window.siyuan.menus.menu.append(movePathToMenu([protyle.path]));
52 const range = getSelection().rangeCount > 0 ? getSelection().getRangeAt(0) : undefined;
53 window.siyuan.menus.menu.append(new MenuItem({
54 id: "addToDatabase",
55 label: window.siyuan.languages.addToDatabase,
56 accelerator: window.siyuan.config.keymap.general.addToDatabase.custom,
57 icon: "iconDatabase",
58 click: () => {
59 addEditorToDatabase(protyle, range, "title");
60 }
61 }).element);
62 window.siyuan.menus.menu.append(new MenuItem({
63 id: "delete",
64 icon: "iconTrashcan",
65 label: window.siyuan.languages.delete,
66 click: () => {
67 deleteFile(protyle.notebookId, protyle.path);
68 }
69 }).element);
70 }
71 /// #if !MOBILE
72 window.siyuan.menus.menu.append(new MenuItem({id: "separator_1", type: "separator"}).element);
73 window.siyuan.menus.menu.append(new MenuItem({
74 id: "outline",
75 icon: "iconAlignCenter",
76 label: window.siyuan.languages.outline,
77 accelerator: window.siyuan.config.keymap.editor.general.outline.custom,
78 click: () => {
79 openOutline({
80 app: protyle.app,
81 rootId: protyle.block.rootID,
82 title: protyle.options.render.title ? (protyle.title.editElement.textContent || window.siyuan.languages.untitled) : "",
83 isPreview: !protyle.preview.element.classList.contains("fn__none")
84 });
85 }
86 }).element);
87 window.siyuan.menus.menu.append(new MenuItem({
88 id: "backlinks",
89 icon: "iconLink",
90 label: window.siyuan.languages.backlinks,
91 accelerator: window.siyuan.config.keymap.editor.general.backlinks.custom,
92 click: () => {
93 openBacklink({
94 app: protyle.app,
95 blockId: protyle.block.id,
96 rootId: protyle.block.rootID,
97 useBlockId: protyle.block.showAll,
98 title: protyle.title ? (protyle.title.editElement.textContent || window.siyuan.languages.untitled) : null
99 });
100 }
101 }).element);
102 window.siyuan.menus.menu.append(new MenuItem({
103 id: "graphView",
104 icon: "iconGraph",
105 label: window.siyuan.languages.graphView,
106 accelerator: window.siyuan.config.keymap.editor.general.graphView.custom,
107 click: () => {
108 openGraph({
109 app: protyle.app,
110 blockId: protyle.block.id,
111 rootId: protyle.block.rootID,
112 useBlockId: protyle.block.showAll,
113 title: protyle.title ? (protyle.title.editElement.textContent || window.siyuan.languages.untitled) : null
114 });
115 }
116 }).element);
117 /// #endif
118 window.siyuan.menus.menu.append(new MenuItem({id: "separator_2", type: "separator"}).element);
119 window.siyuan.menus.menu.append(new MenuItem({
120 id: "attr",
121 label: window.siyuan.languages.attr,
122 icon: "iconAttr",
123 accelerator: window.siyuan.config.keymap.editor.general.attr.custom + "/" + updateHotkeyTip("⇧" + window.siyuan.languages.click),
124 click() {
125 openFileAttr(response.data.ial, "bookmark", protyle);
126 }
127 }).element);
128 if (!window.siyuan.config.readonly) {
129 if (window.siyuan.config.cloudRegion === 0) {
130 window.siyuan.menus.menu.append(new MenuItem({
131 id: "wechatReminder",
132 label: window.siyuan.languages.wechatReminder,
133 icon: "iconMp",
134 click() {
135 openFileWechatNotify(protyle);
136 }
137 }).element);
138 }
139 const isCardMade = !!response.data.ial[Constants.CUSTOM_RIFF_DECKS];
140 const riffCardMenu: IMenu[] = [{
141 id: "spaceRepetition",
142 iconHTML: "",
143 label: window.siyuan.languages.spaceRepetition,
144 accelerator: window.siyuan.config.keymap.editor.general.spaceRepetition.custom,
145 click: () => {
146 fetchPost("/api/riff/getTreeRiffDueCards", {rootID: protyle.block.rootID}, (response) => {
147 openCardByData(protyle.app, response.data, "doc", protyle.block.rootID, response.data.name);
148 });
149 }
150 }, {
151 id: "manage",
152 iconHTML: "",
153 label: window.siyuan.languages.manage,
154 click: () => {
155 fetchPost("/api/filetree/getHPathByID", {
156 id: protyle.block.rootID
157 }, (response) => {
158 viewCards(protyle.app, protyle.block.rootID, pathPosix().join(getNotebookName(protyle.notebookId), (response.data)), "Tree");
159 });
160 }
161 }, {
162 id: isCardMade ? "removeCard" : "quickMakeCard",
163 iconHTML: "",
164 label: isCardMade ? window.siyuan.languages.removeCard : window.siyuan.languages.quickMakeCard,
165 accelerator: window.siyuan.config.keymap.editor.general.quickMakeCard.custom,
166 click: () => {
167 let titleElement = protyle.title?.element;
168 if (!titleElement) {
169 titleElement = document.createElement("div");
170 titleElement.setAttribute("data-node-id", protyle.block.rootID);
171 titleElement.setAttribute(Constants.CUSTOM_RIFF_DECKS, response.data.ial[Constants.CUSTOM_RIFF_DECKS]);
172 }
173 quickMakeCard(protyle, [titleElement]);
174 }
175 }];
176 if (window.siyuan.config.flashcard.deck) {
177 riffCardMenu.push({
178 id: "addToDeck",
179 iconHTML: "",
180 label: window.siyuan.languages.addToDeck,
181 click: () => {
182 makeCard(protyle.app, [protyle.block.rootID]);
183 }
184 });
185 }
186 window.siyuan.menus.menu.append(new MenuItem({
187 id: "riffCard",
188 label: window.siyuan.languages.riffCard,
189 type: "submenu",
190 icon: "iconRiffCard",
191 submenu: riffCardMenu,
192 }).element);
193 }
194 window.siyuan.menus.menu.append(new MenuItem({
195 id: "search",
196 label: window.siyuan.languages.search,
197 icon: "iconSearch",
198 accelerator: window.siyuan.config.keymap.general.search.custom,
199 async click() {
200 const searchPath = getDisplayName(protyle.path, false, true);
201 /// #if MOBILE
202 const pathResponse = await fetchSyncPost("/api/filetree/getHPathByPath", {
203 notebook: protyle.notebookId,
204 path: searchPath + ".sy"
205 });
206 popSearch(protyle.app, {
207 hasReplace: false,
208 hPath: pathPosix().join(getNotebookName(protyle.notebookId), pathResponse.data),
209 idPath: [pathPosix().join(protyle.notebookId, searchPath)],
210 page: 1,
211 });
212 /// #else
213 openSearch({
214 app: protyle.app,
215 hotkey: Constants.DIALOG_SEARCH,
216 notebookId: protyle.notebookId,
217 searchPath
218 });
219 /// #endif
220 }
221 }).element);
222 if (!protyle.disabled) {
223 transferBlockRef(protyle.block.rootID);
224 }
225 window.siyuan.menus.menu.append(new MenuItem({id: "separator_3", type: "separator"}).element);
226 if (!protyle.model) {
227 window.siyuan.menus.menu.append(new MenuItem({
228 id: "openBy",
229 label: window.siyuan.languages.openBy,
230 icon: "iconOpen",
231 click() {
232 /// #if !MOBILE
233 openFileById({
234 app: protyle.app,
235 id: protyle.block.id,
236 action: protyle.block.rootID !== protyle.block.id ? [Constants.CB_GET_ALL, Constants.CB_GET_FOCUS] : [Constants.CB_GET_CONTEXT],
237 });
238 /// #else
239 openMobileFileById(protyle.app, protyle.block.id, protyle.block.rootID !== protyle.block.id ? [Constants.CB_GET_ALL] : [Constants.CB_GET_CONTEXT]);
240 /// #endif
241 }
242 }).element);
243 }
244 /// #if !BROWSER
245 window.siyuan.menus.menu.append(new MenuItem({
246 id: "openByNewWindow",
247 label: window.siyuan.languages.openByNewWindow,
248 icon: "iconOpenWindow",
249 click() {
250 openNewWindowById(protyle.block.rootID);
251 }
252 }).element);
253 window.siyuan.menus.menu.append(new MenuItem({
254 id: "showInFolder",
255 icon: "iconFolder",
256 label: window.siyuan.languages.showInFolder,
257 click: () => {
258 useShell("showItemInFolder", path.join(window.siyuan.config.system.dataDir, protyle.notebookId, protyle.path));
259 }
260 }).element);
261 /// #endif
262 if (!protyle.disabled) {
263 window.siyuan.menus.menu.append(new MenuItem({
264 id: "fileHistory",
265 label: window.siyuan.languages.fileHistory,
266 icon: "iconHistory",
267 click() {
268 openDocHistory({
269 app: protyle.app,
270 id: protyle.block.rootID,
271 notebookId: protyle.notebookId,
272 pathString: response.data.name
273 });
274 }
275 }).element);
276 }
277 window.siyuan.menus.menu.append(exportMd(protyle.block.showAll ? protyle.block.id : protyle.block.rootID));
278
279 window.siyuan.menus.menu.append(new MenuItem({id: "separator_4", type: "separator"}).element);
280 if (protyle?.app?.plugins) {
281 emitOpenMenu({
282 plugins: protyle.app.plugins,
283 type: "click-editortitleicon",
284 detail: {
285 protyle,
286 data: response.data,
287 },
288 separatorPosition: "bottom",
289 });
290 }
291 window.siyuan.menus.menu.append(new MenuItem({
292 id: "updateAndCreatedAt",
293 iconHTML: "",
294 type: "readonly",
295 // 不能换行,否则移动端间距过大
296 label: `${window.siyuan.languages.modifiedAt} ${dayjs(response.data.ial.updated).format("YYYY-MM-DD HH:mm:ss")}<br>${window.siyuan.languages.createdAt} ${dayjs(response.data.ial.id.substr(0, 14)).format("YYYY-MM-DD HH:mm:ss")}`
297 }).element);
298 /// #if MOBILE
299 window.siyuan.menus.menu.fullscreen();
300 /// #else
301 window.siyuan.menus.menu.popup(position);
302 /// #endif
303 });
304};