mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
Merge branch 'stable'
# Conflicts: # src/services/notes.js
This commit is contained in:
commit
4c7c3105e8
@ -76,8 +76,7 @@ async function initContextMenu(event, contextMenu) {
|
|||||||
// in such case we'll position it above click coordinates so it will fit into client
|
// in such case we'll position it above click coordinates so it will fit into client
|
||||||
const clickPosition = event.pageY;
|
const clickPosition = event.pageY;
|
||||||
const clientHeight = document.documentElement.clientHeight;
|
const clientHeight = document.documentElement.clientHeight;
|
||||||
const contextMenuHeight = $contextMenuContainer.height();
|
const contextMenuHeight = $contextMenuContainer.outerHeight() + 30;
|
||||||
|
|
||||||
let top;
|
let top;
|
||||||
|
|
||||||
if (clickPosition + contextMenuHeight > clientHeight) {
|
if (clickPosition + contextMenuHeight > clientHeight) {
|
||||||
|
@ -201,17 +201,13 @@ async function loadNoteDetail(origNotePath, options = {}) {
|
|||||||
const newTab = !!options.newTab;
|
const newTab = !!options.newTab;
|
||||||
const activate = !!options.activate;
|
const activate = !!options.activate;
|
||||||
|
|
||||||
const notePath = await treeService.resolveNotePath(origNotePath);
|
let notePath = await treeService.resolveNotePath(origNotePath);
|
||||||
|
|
||||||
if (!notePath) {
|
if (!notePath) {
|
||||||
console.error(`Cannot resolve note path ${origNotePath}`);
|
console.error(`Cannot resolve note path ${origNotePath}`);
|
||||||
|
|
||||||
// fallback to display something
|
// fallback to display something
|
||||||
if (tabContexts.length === 0) {
|
notePath = 'root';
|
||||||
await openEmptyTab();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
|
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
|
||||||
|
@ -47,6 +47,7 @@ class NoteDetailText {
|
|||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.$component = ctx.$tabContent.find('.note-detail-text');
|
this.$component = ctx.$tabContent.find('.note-detail-text');
|
||||||
this.$editorEl = this.$component.find('.note-detail-text-editor');
|
this.$editorEl = this.$component.find('.note-detail-text-editor');
|
||||||
|
this.textEditorPromise = null;
|
||||||
this.textEditor = null;
|
this.textEditor = null;
|
||||||
|
|
||||||
this.$component.on("dblclick", "img", e => {
|
this.$component.on("dblclick", "img", e => {
|
||||||
@ -67,44 +68,12 @@ class NoteDetailText {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async render() {
|
async render() {
|
||||||
if (!this.textEditor) {
|
if (!this.textEditorPromise) {
|
||||||
await libraryLoader.requireLibrary(libraryLoader.CKEDITOR);
|
this.textEditorPromise = this.initEditor();
|
||||||
|
|
||||||
const codeBlockLanguages =
|
|
||||||
(await mimeTypesService.getMimeTypes())
|
|
||||||
.filter(mt => mt.enabled)
|
|
||||||
.map(mt => {
|
|
||||||
return {
|
|
||||||
language: mt.mime.toLowerCase().replace(/[\W_]+/g,"-"),
|
|
||||||
label: mt.title
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// CKEditor since version 12 needs the element to be visible before initialization. At the same time
|
|
||||||
// we want to avoid flicker - i.e. show editor only once everything is ready. That's why we have separate
|
|
||||||
// display of $component in both branches.
|
|
||||||
this.$component.show();
|
|
||||||
|
|
||||||
// textEditor might have been initialized during previous await so checking again
|
|
||||||
// looks like double initialization can freeze CKEditor pretty badly
|
|
||||||
if (!this.textEditor) {
|
|
||||||
this.textEditor = await BalloonEditor.create(this.$editorEl[0], {
|
|
||||||
placeholder: "Type the content of your note here ...",
|
|
||||||
mention: mentionSetup,
|
|
||||||
codeBlock: {
|
|
||||||
languages: codeBlockLanguages
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (glob.isDev && ENABLE_INSPECTOR) {
|
|
||||||
await import('../../libraries/ckeditor/inspector.js');
|
|
||||||
CKEditorInspector.attach(this.textEditor);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.onNoteChange(() => this.ctx.noteChanged());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.textEditorPromise;
|
||||||
|
|
||||||
// lazy loading above can take time and tab might have been already switched to another note
|
// lazy loading above can take time and tab might have been already switched to another note
|
||||||
if (this.ctx.note && this.ctx.note.type === 'text') {
|
if (this.ctx.note && this.ctx.note.type === 'text') {
|
||||||
this.textEditor.isReadOnly = await this.isReadOnly();
|
this.textEditor.isReadOnly = await this.isReadOnly();
|
||||||
@ -115,6 +84,42 @@ class NoteDetailText {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async initEditor() {
|
||||||
|
await libraryLoader.requireLibrary(libraryLoader.CKEDITOR);
|
||||||
|
|
||||||
|
const codeBlockLanguages =
|
||||||
|
(await mimeTypesService.getMimeTypes())
|
||||||
|
.filter(mt => mt.enabled)
|
||||||
|
.map(mt => {
|
||||||
|
return {
|
||||||
|
language: mt.mime.toLowerCase().replace(/[\W_]+/g,"-"),
|
||||||
|
label: mt.title
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// CKEditor since version 12 needs the element to be visible before initialization. At the same time
|
||||||
|
// we want to avoid flicker - i.e. show editor only once everything is ready. That's why we have separate
|
||||||
|
// display of $component in both branches.
|
||||||
|
this.$component.show();
|
||||||
|
|
||||||
|
const textEditorInstance = await BalloonEditor.create(this.$editorEl[0], {
|
||||||
|
placeholder: "Type the content of your note here ...",
|
||||||
|
mention: mentionSetup,
|
||||||
|
codeBlock: {
|
||||||
|
languages: codeBlockLanguages
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (glob.isDev && ENABLE_INSPECTOR) {
|
||||||
|
await import('../../libraries/ckeditor/inspector.js');
|
||||||
|
CKEditorInspector.attach(textEditorInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.textEditor = textEditorInstance;
|
||||||
|
|
||||||
|
this.onNoteChange(() => this.ctx.noteChanged());
|
||||||
|
}
|
||||||
|
|
||||||
getContent() {
|
getContent() {
|
||||||
const content = this.textEditor.getData();
|
const content = this.textEditor.getData();
|
||||||
|
|
||||||
|
@ -350,8 +350,6 @@ class TabContext {
|
|||||||
|
|
||||||
this.$savedIndicator.fadeIn();
|
this.$savedIndicator.fadeIn();
|
||||||
|
|
||||||
this.$scriptArea.empty();
|
|
||||||
|
|
||||||
// run async
|
// run async
|
||||||
bundleService.executeRelationBundles(this.note, 'runOnNoteChange', this);
|
bundleService.executeRelationBundles(this.note, 'runOnNoteChange', this);
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ body {
|
|||||||
|
|
||||||
#context-menu-container {
|
#context-menu-container {
|
||||||
max-height: 100vh;
|
max-height: 100vh;
|
||||||
overflow: auto; /* make it scrollable when exceeding total height of the window */
|
/* !!! Cannot set overflow: auto, submenus will break !!! */
|
||||||
}
|
}
|
||||||
|
|
||||||
#context-menu-container, #context-menu-container .dropdown-menu {
|
#context-menu-container, #context-menu-container .dropdown-menu {
|
||||||
|
@ -594,6 +594,8 @@ async function eraseDeletedNotes() {
|
|||||||
SET name = 'deleted',
|
SET name = 'deleted',
|
||||||
value = ''
|
value = ''
|
||||||
WHERE noteId IN (???)`, noteIdsToErase);
|
WHERE noteId IN (???)`, noteIdsToErase);
|
||||||
|
|
||||||
|
log.info(`Erased notes: ${JSON.stringify(noteIdsToErase)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function duplicateNote(noteId, parentNoteId) {
|
async function duplicateNote(noteId, parentNoteId) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user