chore(react/type_widget): add back keyboard shortcut for editable code

This commit is contained in:
Elian Doran
2025-09-20 10:08:46 +03:00
parent c86123e3a9
commit 7a3ee7971c
5 changed files with 19 additions and 42 deletions

View File

@@ -16,8 +16,6 @@ import "./NoteDetail.css";
import File from "./type_widgets/File"; import File from "./type_widgets/File";
import Image from "./type_widgets/Image"; import Image from "./type_widgets/Image";
import { ReadOnlyCode, EditableCode } from "./type_widgets/code/Code"; import { ReadOnlyCode, EditableCode } from "./type_widgets/code/Code";
import SpacedUpdate from "../services/spaced_update";
import server from "../services/server";
/** /**
* A `NoteType` altered by the note detail widget, taking into consideration whether the note is editable or not and adding special note types such as an empty one, * A `NoteType` altered by the note detail widget, taking into consideration whether the note is editable or not and adding special note types such as an empty one,
@@ -30,14 +28,15 @@ type ExtendedNoteType = Exclude<NoteType, "launcher" | "text" | "code"> | "empty
*/ */
export default function NoteDetail() { export default function NoteDetail() {
const { note, type, noteContext } = useNoteInfo(); const { note, type, noteContext } = useNoteInfo();
const { ntxId, viewScope } = noteContext ?? {}; const { ntxId, viewScope, parent } = noteContext ?? {};
const [ correspondingWidget, setCorrespondingWidget ] = useState<VNode>(); const [ correspondingWidget, setCorrespondingWidget ] = useState<VNode>();
const isFullHeight = checkFullHeight(noteContext, type); const isFullHeight = checkFullHeight(noteContext, type);
const props: TypeWidgetProps = { const props: TypeWidgetProps = {
note: note!, note: note!,
viewScope, viewScope,
ntxId ntxId,
parentComponent: parent
}; };
useEffect(() => setCorrespondingWidget(getCorrespondingWidget(type, props)), [ note, viewScope, type ]); useEffect(() => setCorrespondingWidget(getCorrespondingWidget(type, props)), [ note, viewScope, type ]);

View File

@@ -1,4 +1,4 @@
import { useCallback, useEffect, useRef, useState } from "preact/hooks"; import { useEffect, useRef, useState } from "preact/hooks";
import { default as VanillaCodeMirror } from "@triliumnext/codemirror"; import { default as VanillaCodeMirror } from "@triliumnext/codemirror";
import { TypeWidgetProps } from "../type_widget"; import { TypeWidgetProps } from "../type_widget";
import "./code.css"; import "./code.css";
@@ -8,6 +8,8 @@ import { useEditorSpacedUpdate, useNoteBlob, useTriliumOptionBool } from "../../
import { t } from "../../../services/i18n"; import { t } from "../../../services/i18n";
import appContext from "../../../components/app_context"; import appContext from "../../../components/app_context";
import TouchBar, { TouchBarButton } from "../../react/TouchBar"; import TouchBar, { TouchBarButton } from "../../react/TouchBar";
import keyboard_actions from "../../../services/keyboard_actions";
import { refToJQuerySelector } from "../../react/react_utils";
export function ReadOnlyCode({ note, viewScope, ntxId }: TypeWidgetProps) { export function ReadOnlyCode({ note, viewScope, ntxId }: TypeWidgetProps) {
const [ content, setContent ] = useState(""); const [ content, setContent ] = useState("");
@@ -32,11 +34,12 @@ export function ReadOnlyCode({ note, viewScope, ntxId }: TypeWidgetProps) {
) )
} }
export function EditableCode({ note, ntxId, debounceUpdate }: TypeWidgetProps & { export function EditableCode({ note, ntxId, debounceUpdate, parentComponent }: TypeWidgetProps & {
// if true, the update will be debounced to prevent excessive updates. Especially useful if the editor is linked to a live preview. // if true, the update will be debounced to prevent excessive updates. Especially useful if the editor is linked to a live preview.
debounceUpdate?: boolean; debounceUpdate?: boolean;
}) { }) {
const editorRef = useRef<VanillaCodeMirror>(null); const editorRef = useRef<VanillaCodeMirror>(null);
const containerRef = useRef<HTMLPreElement>(null);
const [ vimKeymapEnabled ] = useTriliumOptionBool("vimKeymapEnabled"); const [ vimKeymapEnabled ] = useTriliumOptionBool("vimKeymapEnabled");
const spacedUpdate = useEditorSpacedUpdate({ const spacedUpdate = useEditorSpacedUpdate({
note, note,
@@ -50,10 +53,15 @@ export function EditableCode({ note, ntxId, debounceUpdate }: TypeWidgetProps &
} }
}); });
useEffect(() => {
if (!parentComponent) return;
keyboard_actions.setupActionsForElement("code-detail", refToJQuerySelector(containerRef), parentComponent);
}, []);
return ( return (
<div className="note-detail-code note-detail-printable"> <div className="note-detail-code note-detail-printable">
<CodeMirror <CodeMirror
editorRef={editorRef} editorRef={editorRef} containerRef={containerRef}
className="note-detail-code-editor" className="note-detail-code-editor"
ntxId={ntxId} ntxId={ntxId}
placeholder={t("editable_code.placeholder")} placeholder={t("editable_code.placeholder")}

View File

@@ -10,10 +10,11 @@ interface CodeMirrorProps extends Omit<EditorConfig, "parent"> {
className?: string; className?: string;
ntxId: string | null | undefined; ntxId: string | null | undefined;
editorRef?: RefObject<VanillaCodeMirror>; editorRef?: RefObject<VanillaCodeMirror>;
containerRef?: RefObject<HTMLPreElement>;
} }
export default function CodeMirror({ className, content, mime, ntxId, editorRef: externalEditorRef, ...extraOpts }: CodeMirrorProps) { export default function CodeMirror({ className, content, mime, ntxId, editorRef: externalEditorRef, containerRef: externalContainerRef, ...extraOpts }: CodeMirrorProps) {
const parentRef = useRef<HTMLPreElement>(null); const parentRef = useSyncedRef(externalContainerRef);
const codeEditorRef = useRef<VanillaCodeMirror>(); const codeEditorRef = useRef<VanillaCodeMirror>();
const [ codeLineWrapEnabled ] = useTriliumOptionBool("codeLineWrapEnabled"); const [ codeLineWrapEnabled ] = useTriliumOptionBool("codeLineWrapEnabled");
const initialized = $.Deferred(); const initialized = $.Deferred();

View File

@@ -1,9 +1,10 @@
import FNote from "../../entities/fnote"; import FNote from "../../entities/fnote";
import { ViewScope } from "../../services/link"; import { ViewScope } from "../../services/link";
import SpacedUpdate from "../../services/spaced_update"; import { TypedComponent } from "../../components/component";
export interface TypeWidgetProps { export interface TypeWidgetProps {
note: FNote; note: FNote;
viewScope: ViewScope | undefined; viewScope: ViewScope | undefined;
ntxId: string | null | undefined; ntxId: string | null | undefined;
parentComponent: TypedComponent<any> | undefined;
} }

View File

@@ -1,32 +0,0 @@
import type { CommandListenerData, EventData } from "../../components/app_context.js";
import type FNote from "../../entities/fnote.js";
import { t } from "../../services/i18n.js";
import keyboardActionService from "../../services/keyboard_actions.js";
import options from "../../services/options.js";
import AbstractCodeTypeWidget from "./abstract_code_type_widget.js";
import appContext from "../../components/app_context.js";
import type { TouchBarItem } from "../../components/touch_bar.js";
import { hasTouchBar } from "../../services/utils.js";
import type { EditorConfig } from "@triliumnext/codemirror";
const TPL = /*html*/`
`;
export default class EditableCodeTypeWidget extends AbstractCodeTypeWidget {
static getType() {
return "editableCode";
}
doRender() {
this.$widget = $(TPL);
this.contentSized();
this.$editor = this.$widget.find(".note-detail-code-editor");
keyboardActionService.setupActionsForElement("code-detail", this.$widget, this);
super.doRender();
}
}