diff --git a/apps/client/src/services/utils.ts b/apps/client/src/services/utils.ts index 3c83d3e86..61f013829 100644 --- a/apps/client/src/services/utils.ts +++ b/apps/client/src/services/utils.ts @@ -869,6 +869,29 @@ export function getErrorMessage(e: unknown) { } } +// TODO: Deduplicate with server +export interface DeferredPromise extends Promise { + resolve: (value: T | PromiseLike) => void; + reject: (reason?: any) => void; +} + +// TODO: Deduplicate with server +export function deferred(): DeferredPromise { + return (() => { + let resolve!: (value: T | PromiseLike) => void; + let reject!: (reason?: any) => void; + + let promise = new Promise((res, rej) => { + resolve = res; + reject = rej; + }) as DeferredPromise; + + promise.resolve = resolve; + promise.reject = reject; + return promise as DeferredPromise; + })(); +} + export default { reloadFrontendApp, restartDesktopApp, diff --git a/apps/client/src/widgets/type_widgets/text/EditableText.tsx b/apps/client/src/widgets/type_widgets/text/EditableText.tsx index 425f62ae3..f423dcd3b 100644 --- a/apps/client/src/widgets/type_widgets/text/EditableText.tsx +++ b/apps/client/src/widgets/type_widgets/text/EditableText.tsx @@ -1,8 +1,8 @@ import { useRef, useState } from "preact/hooks"; import dialog from "../../../services/dialog"; import toast from "../../../services/toast"; -import utils, { isMobile } from "../../../services/utils"; -import { useEditorSpacedUpdate, useNoteLabel, useTriliumOption } from "../../react/hooks"; +import utils, { deferred, isMobile } from "../../../services/utils"; +import { useEditorSpacedUpdate, useNoteLabel, useTriliumEvent, useTriliumOption } from "../../react/hooks"; import { TypeWidgetProps } from "../type_widget"; import CKEditorWithWatchdog from "./CKEditorWithWatchdog"; import "./EditableText.css"; @@ -15,12 +15,13 @@ import Component from "../../../components/component"; * - Ballon block mode, in which there is a floating toolbar for the selected text, but another floating button for the entire block (i.e. paragraph). * - Decoupled mode, in which the editing toolbar is actually added on the client side (in {@link ClassicEditorToolbar}), see https://ckeditor.com/docs/ckeditor5/latest/examples/framework/bottom-toolbar-editor.html for an example on how the decoupled editor works. */ -export default function EditableText({ note, parentComponent }: TypeWidgetProps) { +export default function EditableText({ note, parentComponent, ntxId }: TypeWidgetProps) { const [ content, setContent ] = useState(); const watchdogRef = useRef(null); const [ language ] = useNoteLabel(note, "language"); const [ textNoteEditorType ] = useTriliumOption("textNoteEditorType"); const isClassicEditor = isMobile() || textNoteEditorType === "ckeditor-classic"; + const initialized = useRef(deferred()); const spacedUpdate = useEditorSpacedUpdate({ note, getData() { @@ -43,6 +44,27 @@ export default function EditableText({ note, parentComponent }: TypeWidgetProps) } }) + useTriliumEvent("scrollToEnd", () => { + const editor = watchdogRef.current?.editor; + if (!editor) return; + + editor.model.change((writer) => { + const rootItem = editor.model.document.getRoot(); + if (rootItem) { + writer.setSelection(writer.createPositionAt(rootItem, "end")); + } + }); + editor.editing.view.focus(); + }); + + useTriliumEvent("focusOnDetail", async ({ ntxId: eventNtxId }) => { + if (eventNtxId !== ntxId) return; + await initialized.current; + const editor = watchdogRef.current?.editor; + if (!editor) return; + editor.editing.view.focus(); + }); + return (
{note && }
@@ -106,7 +130,6 @@ function onNotificationWarning(data, evt) { function setupClassicEditor(editor: CKTextEditor, parentComponent: Component | undefined) { if (!parentComponent) return; const $classicToolbarWidget = findClassicToolbar(parentComponent); - console.log("Found ", $classicToolbarWidget); $classicToolbarWidget.empty(); if ($classicToolbarWidget.length) { @@ -140,7 +163,6 @@ function findClassicToolbar(parentComponent: Component): JQuery { if (!utils.isMobile()) { const $parentSplit = $widget.parents(".note-split.type-text"); - console.log("Got split ", $parentSplit) if ($parentSplit.length) { // The editor is in a normal tab. diff --git a/apps/client/src/widgets/type_widgets_old/editable_text.ts b/apps/client/src/widgets/type_widgets_old/editable_text.ts index 42ae5eef7..11e50300c 100644 --- a/apps/client/src/widgets/type_widgets_old/editable_text.ts +++ b/apps/client/src/widgets/type_widgets_old/editable_text.ts @@ -51,26 +51,6 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget { await this.createEditor(); } - focus() { - const editor = this.watchdog.editor; - if (editor) { - editor.editing.view.focus(); - } else { - this.$editor.trigger("focus"); - } - } - - scrollToEnd() { - this.watchdog?.editor?.model.change((writer) => { - const rootItem = this.watchdog?.editor?.model.document.getRoot(); - if (rootItem) { - writer.setSelection(writer.createPositionAt(rootItem, "end")); - } - }); - - this.watchdog?.editor?.editing.view.focus(); - } - show() { } getEditor() {