This repository was archived by the owner on Jun 24, 2025. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 151
Expand file tree
/
Copy pathnote_create.ts
More file actions
167 lines (138 loc) · 5.46 KB
/
note_create.ts
File metadata and controls
167 lines (138 loc) · 5.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import appContext from "../components/app_context.js";
import protectedSessionHolder from "./protected_session_holder.js";
import server from "./server.js";
import ws from "./ws.js";
import froca from "./froca.js";
import treeService from "./tree.js";
import toastService from "./toast.js";
import { t } from "./i18n.js";
import type FNote from "../entities/fnote.js";
import type FBranch from "../entities/fbranch.js";
import type { ChooseNoteTypeResponse } from "../widgets/dialogs/note_type_chooser.js";
import type { CKTextEditor } from "@triliumnext/ckeditor5";
interface CreateNoteOpts {
isProtected?: boolean;
saveSelection?: boolean;
title?: string | null;
content?: string | null;
type?: string;
mime?: string;
templateNoteId?: string;
activate?: boolean;
focus?: "title" | "content";
target?: string;
targetBranchId?: string;
textEditor?: CKTextEditor;
}
interface Response {
// TODO: Deduplicate with server once we have client/server architecture.
note: FNote;
branch: FBranch;
}
interface DuplicateResponse {
// TODO: Deduplicate with server once we have client/server architecture.
note: FNote;
}
async function createNote(parentNotePath: string | undefined, options: CreateNoteOpts = {}) {
options = Object.assign(
{
activate: true,
focus: "title",
target: "into"
},
options
);
// if isProtected isn't available (user didn't enter password yet), then note is created as unencrypted,
// but this is quite weird since the user doesn't see WHERE the note is being created, so it shouldn't occur often
if (!options.isProtected || !protectedSessionHolder.isProtectedSessionAvailable()) {
options.isProtected = false;
}
if (appContext.tabManager.getActiveContextNoteType() !== "text") {
options.saveSelection = false;
}
if (options.saveSelection && options.textEditor) {
[options.title, options.content] = parseSelectedHtml(options.textEditor.getSelectedHtml());
}
const parentNoteId = treeService.getNoteIdFromUrl(parentNotePath);
if (options.type === "mermaid" && !options.content && !options.templateNoteId) {
options.content = `graph TD;
A-->B;
A-->C;
B-->D;
C-->D;`;
}
const { note, branch } = await server.post<Response>(`notes/${parentNoteId}/children?target=${options.target}&targetBranchId=${options.targetBranchId || ""}`, {
title: options.title,
content: options.content || "",
isProtected: options.isProtected,
type: options.type,
mime: options.mime,
templateNoteId: options.templateNoteId
});
if (options.saveSelection) {
// we remove the selection only after it was saved to server to make sure we don't lose anything
options.textEditor?.removeSelection();
}
await ws.waitForMaxKnownEntityChangeId();
const activeNoteContext = appContext.tabManager.getActiveContext();
if (activeNoteContext && options.activate) {
await activeNoteContext.setNote(`${parentNotePath}/${note.noteId}`);
if (options.focus === "title") {
appContext.triggerEvent("focusAndSelectTitle", { isNewNote: true });
} else if (options.focus === "content") {
appContext.triggerEvent("focusOnDetail", { ntxId: activeNoteContext.ntxId });
}
}
const noteEntity = await froca.getNote(note.noteId);
const branchEntity = froca.getBranch(branch.branchId);
return {
note: noteEntity,
branch: branchEntity
};
}
async function chooseNoteType() {
return new Promise<ChooseNoteTypeResponse>((res) => {
// TODO: Remove ignore after callback for chooseNoteType is defined in app_context.ts
//@ts-ignore
appContext.triggerCommand("chooseNoteType", { callback: res });
});
}
async function createNoteWithTypePrompt(parentNotePath: string, options: CreateNoteOpts = {}) {
const { success, noteType, templateNoteId, notePath } = await chooseNoteType();
if (!success) {
return;
}
options.type = noteType;
options.templateNoteId = templateNoteId;
return await createNote(notePath || parentNotePath, options);
}
/* If the first element is heading, parse it out and use it as a new heading. */
function parseSelectedHtml(selectedHtml: string) {
const dom = $.parseHTML(selectedHtml);
// TODO: tagName and outerHTML appear to be missing.
//@ts-ignore
if (dom.length > 0 && dom[0].tagName && dom[0].tagName.match(/h[1-6]/i)) {
const title = $(dom[0]).text();
// remove the title from content (only first occurrence)
// TODO: tagName and outerHTML appear to be missing.
//@ts-ignore
const content = selectedHtml.replace(dom[0].outerHTML, "");
return [title, content];
} else {
return [null, selectedHtml];
}
}
async function duplicateSubtree(noteId: string, parentNotePath: string) {
const parentNoteId = treeService.getNoteIdFromUrl(parentNotePath);
const { note } = await server.post<DuplicateResponse>(`notes/${noteId}/duplicate/${parentNoteId}`);
await ws.waitForMaxKnownEntityChangeId();
appContext.tabManager.getActiveContext()?.setNote(`${parentNotePath}/${note.noteId}`);
const origNote = await froca.getNote(noteId);
toastService.showMessage(t("note_create.duplicated", { title: origNote?.title }));
}
export default {
createNote,
createNoteWithTypePrompt,
duplicateSubtree,
chooseNoteType
};