mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-04 13:39:01 +01:00 
			
		
		
		
	chore(react/ribbon): add focus to attribute editor
This commit is contained in:
		
							parent
							
								
									efd713dc61
								
							
						
					
					
						commit
						db687197de
					
				@ -18,14 +18,6 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget implem
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async save() {
 | 
			
		||||
        if (this.lastUpdatedNoteId !== this.noteId) {
 | 
			
		||||
            // https://github.com/zadam/trilium/issues/3090
 | 
			
		||||
            console.warn("Ignoring blur event because a different note is loaded.");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dataChanged() {
 | 
			
		||||
        this.lastUpdatedNoteId = this.noteId;
 | 
			
		||||
    }
 | 
			
		||||
@ -49,20 +41,6 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget implem
 | 
			
		||||
    focus() {
 | 
			
		||||
        this.$editor.trigger("focus");
 | 
			
		||||
 | 
			
		||||
        this.textEditor.model.change((writer) => {
 | 
			
		||||
            const documentRoot = this.textEditor.editing.model.document.getRoot();
 | 
			
		||||
            if (!documentRoot) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const positionAt = writer.createPositionAt(documentRoot, "end");
 | 
			
		||||
            writer.setSelection(positionAt);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) {
 | 
			
		||||
        if (loadResults.getAttributeRows(this.componentId).find((attr) => attributeService.isAffecting(attr, this.note))) {
 | 
			
		||||
            this.refresh();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,13 @@
 | 
			
		||||
import { CKTextEditor, type AttributeEditor, type EditorConfig, type ModelPosition } from "@triliumnext/ckeditor5";
 | 
			
		||||
import { useEffect, useRef } from "preact/compat";
 | 
			
		||||
import { useEffect, useImperativeHandle, useRef } from "preact/compat";
 | 
			
		||||
import { MutableRef } from "preact/hooks";
 | 
			
		||||
 | 
			
		||||
export interface CKEditorApi {
 | 
			
		||||
    focus: () => void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface CKEditorOpts {
 | 
			
		||||
    apiRef: MutableRef<CKEditorApi | undefined>;
 | 
			
		||||
    currentValue?: string;
 | 
			
		||||
    className: string;
 | 
			
		||||
    tabIndex?: number;
 | 
			
		||||
@ -15,9 +21,22 @@ interface CKEditorOpts {
 | 
			
		||||
    onBlur?: () => void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default function CKEditor({ currentValue, editor, config, disableNewlines, disableSpellcheck, onChange, onClick, ...restProps }: CKEditorOpts) {
 | 
			
		||||
export default function CKEditor({ apiRef, currentValue, editor, config, disableNewlines, disableSpellcheck, onChange, onClick, ...restProps }: CKEditorOpts) {
 | 
			
		||||
    const editorContainerRef = useRef<HTMLDivElement>(null);    
 | 
			
		||||
    const textEditorRef = useRef<CKTextEditor>(null);
 | 
			
		||||
    useImperativeHandle(apiRef, () => {
 | 
			
		||||
        return {
 | 
			
		||||
            focus() {
 | 
			
		||||
                editorContainerRef.current?.focus();
 | 
			
		||||
                textEditorRef.current?.model.change((writer) => {
 | 
			
		||||
                    const documentRoot = textEditorRef.current?.editing.model.document.getRoot();
 | 
			
		||||
                    if (documentRoot) {
 | 
			
		||||
                        writer.setSelection(writer.createPositionAt(documentRoot, "end"));
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    }, [ editorContainerRef ]);
 | 
			
		||||
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
        if (!editorContainerRef.current) return;
 | 
			
		||||
 | 
			
		||||
@ -148,7 +148,7 @@ const TAB_CONFIGURATION = numberObjectsInPlace<TabConfiguration>([
 | 
			
		||||
]);
 | 
			
		||||
 | 
			
		||||
export default function Ribbon() {
 | 
			
		||||
    const { note, ntxId, hoistedNoteId, notePath, noteContext } = useNoteContext();
 | 
			
		||||
    const { note, ntxId, hoistedNoteId, notePath, noteContext, componentId } = useNoteContext();
 | 
			
		||||
    const titleContext: TitleContext = { note };
 | 
			
		||||
    const [ activeTabIndex, setActiveTabIndex ] = useState<number | undefined>();
 | 
			
		||||
    const filteredTabs = useMemo(() => TAB_CONFIGURATION.filter(tab => typeof tab.show === "boolean" ? tab.show : tab.show?.(titleContext)), [ titleContext, note ]);
 | 
			
		||||
@ -190,7 +190,8 @@ export default function Ribbon() {
 | 
			
		||||
                            ntxId,
 | 
			
		||||
                            hoistedNoteId,
 | 
			
		||||
                            notePath,
 | 
			
		||||
                            noteContext
 | 
			
		||||
                            noteContext,
 | 
			
		||||
                            componentId
 | 
			
		||||
                        });
 | 
			
		||||
                    })}
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
@ -3,8 +3,8 @@ import { AttributeEditor as CKEditorAttributeEditor, MentionFeed, ModelElement,
 | 
			
		||||
import { t } from "../../../services/i18n";
 | 
			
		||||
import server from "../../../services/server";
 | 
			
		||||
import note_autocomplete, { Suggestion } from "../../../services/note_autocomplete";
 | 
			
		||||
import CKEditor from "../../react/CKEditor";
 | 
			
		||||
import { useLegacyWidget, useTooltip } from "../../react/hooks";
 | 
			
		||||
import CKEditor, { CKEditorApi } from "../../react/CKEditor";
 | 
			
		||||
import { useLegacyWidget, useTooltip, useTriliumEventBeta } from "../../react/hooks";
 | 
			
		||||
import FAttribute from "../../../entities/fattribute";
 | 
			
		||||
import attribute_renderer from "../../../services/attribute_renderer";
 | 
			
		||||
import FNote from "../../../entities/fnote";
 | 
			
		||||
@ -19,6 +19,7 @@ import froca from "../../../services/froca";
 | 
			
		||||
import contextMenu from "../../../menus/context_menu";
 | 
			
		||||
import type { CommandData, FilteredCommandNames } from "../../../components/app_context";
 | 
			
		||||
import { AttributeType } from "@triliumnext/commons";
 | 
			
		||||
import attributes from "../../../services/attributes";
 | 
			
		||||
 | 
			
		||||
type AttributeCommandNames = FilteredCommandNames<CommandData>;
 | 
			
		||||
 | 
			
		||||
@ -86,6 +87,7 @@ export default function AttributeEditor({ note, componentId }: { note: FNote, co
 | 
			
		||||
    const lastSavedContent = useRef<string>();
 | 
			
		||||
    const currentValueRef = useRef(initialValue);
 | 
			
		||||
    const wrapperRef = useRef<HTMLDivElement>(null);
 | 
			
		||||
    const editorRef = useRef<CKEditorApi>();
 | 
			
		||||
 | 
			
		||||
    const { showTooltip, hideTooltip } = useTooltip(wrapperRef, {
 | 
			
		||||
        trigger: "focus",
 | 
			
		||||
@ -207,9 +209,23 @@ export default function AttributeEditor({ note, componentId }: { note: FNote, co
 | 
			
		||||
        }, 100);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
    // Refresh with note
 | 
			
		||||
    function refresh() {
 | 
			
		||||
        renderOwnedAttributes(note.getOwnedAttributes(), true);
 | 
			
		||||
    }, [ note ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    useEffect(() => refresh(), [ note ]);
 | 
			
		||||
    useTriliumEventBeta("entitiesReloaded", ({ loadResults }) => {
 | 
			
		||||
        if (loadResults.getAttributeRows(componentId).find((attr) => attributes.isAffecting(attr, note))) {
 | 
			
		||||
            console.log("Trigger due to entities reloaded");
 | 
			
		||||
            refresh();
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // Focus on show.
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
        setTimeout(() => editorRef.current?.focus(), 0);
 | 
			
		||||
    }, []);
 | 
			
		||||
    
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
@ -224,6 +240,7 @@ export default function AttributeEditor({ note, componentId }: { note: FNote, co
 | 
			
		||||
                }}
 | 
			
		||||
            >
 | 
			
		||||
                <CKEditor
 | 
			
		||||
                    apiRef={editorRef}
 | 
			
		||||
                    className="attribute-list-editor"
 | 
			
		||||
                    tabIndex={200}
 | 
			
		||||
                    editor={CKEditorAttributeEditor}
 | 
			
		||||
 | 
			
		||||
@ -8,4 +8,5 @@ export interface TabContext {
 | 
			
		||||
    hoistedNoteId?: string;
 | 
			
		||||
    notePath?: string | null;
 | 
			
		||||
    noteContext?: NoteContext;
 | 
			
		||||
    componentId: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user