chore(react/type_widget): scroll to end & focus

This commit is contained in:
Elian Doran 2025-09-22 13:36:18 +03:00
parent efaa1815ec
commit 46db047fa0
No known key found for this signature in database
3 changed files with 50 additions and 25 deletions

View File

@ -869,6 +869,29 @@ export function getErrorMessage(e: unknown) {
}
}
// TODO: Deduplicate with server
export interface DeferredPromise<T> extends Promise<T> {
resolve: (value: T | PromiseLike<T>) => void;
reject: (reason?: any) => void;
}
// TODO: Deduplicate with server
export function deferred<T>(): DeferredPromise<T> {
return (() => {
let resolve!: (value: T | PromiseLike<T>) => void;
let reject!: (reason?: any) => void;
let promise = new Promise<T>((res, rej) => {
resolve = res;
reject = rej;
}) as DeferredPromise<T>;
promise.resolve = resolve;
promise.reject = reject;
return promise as DeferredPromise<T>;
})();
}
export default {
reloadFrontendApp,
restartDesktopApp,

View File

@ -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<string>();
const watchdogRef = useRef<EditorWatchdog>(null);
const [ language ] = useNoteLabel(note, "language");
const [ textNoteEditorType ] = useTriliumOption("textNoteEditorType");
const isClassicEditor = isMobile() || textNoteEditorType === "ckeditor-classic";
const initialized = useRef(deferred<void>());
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 (
<div class="note-detail-editable-text note-detail-printable">
{note && <CKEditorWithWatchdog
@ -68,6 +90,8 @@ export default function EditableText({ note, parentComponent }: TypeWidgetProps)
if (isClassicEditor) {
setupClassicEditor(editor, parentComponent);
}
initialized.current.resolve();
}}
/>}
</div>
@ -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<HTMLElement> {
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.

View File

@ -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() {