refactor(note-create): remove unnecessary deep hierarchy

This commit is contained in:
Jakob Schlanstedt 2025-10-28 18:47:09 +01:00 committed by Jakob Schlanstedt
parent f15b778bf4
commit 4134f000df
13 changed files with 39 additions and 47 deletions

View file

@ -1,5 +1,5 @@
import appContext, { type EventData } from "./app_context.js"; import appContext, { type EventData } from "./app_context.js";
import noteCreateService, { CreateNoteIntoUrlOpts, CreateNoteAfterUrlOpts } from "../services/note_create.js"; import noteCreateService, { CreateNoteWithUrlOpts } from "../services/note_create.js";
import treeService from "../services/tree.js"; import treeService from "../services/tree.js";
import hoistedNoteService from "../services/hoisted_note.js"; import hoistedNoteService from "../services/hoisted_note.js";
import Component from "./component.js"; import Component from "./component.js";
@ -55,7 +55,7 @@ export default class MainTreeExecutors extends Component {
isProtected: activeNoteContext.note.isProtected, isProtected: activeNoteContext.note.isProtected,
saveSelection: false, saveSelection: false,
promptForType: false, promptForType: false,
} as CreateNoteIntoUrlOpts } as CreateNoteWithUrlOpts
); );
} }
@ -84,7 +84,7 @@ export default class MainTreeExecutors extends Component {
targetBranchId: node.data.branchId, targetBranchId: node.data.branchId,
isProtected: isProtected, isProtected: isProtected,
saveSelection: false saveSelection: false
} as CreateNoteAfterUrlOpts } as CreateNoteWithUrlOpts
); );
} }
} }

View file

@ -9,7 +9,7 @@ import froca from "../services/froca.js";
import utils from "../services/utils.js"; import utils from "../services/utils.js";
import LlmChatPanel from "../widgets/llm_chat_panel.js"; import LlmChatPanel from "../widgets/llm_chat_panel.js";
import toastService from "../services/toast.js"; import toastService from "../services/toast.js";
import noteCreateService, { CreateNoteIntoUrlOpts } from "../services/note_create.js"; import noteCreateService, { CreateNoteWithUrlOpts } from "../services/note_create.js";
export default class RootCommandExecutor extends Component { export default class RootCommandExecutor extends Component {
editReadOnlyNoteCommand() { editReadOnlyNoteCommand() {
@ -242,7 +242,7 @@ export default class RootCommandExecutor extends Component {
messages: [], messages: [],
title: "New AI Chat" title: "New AI Chat"
}), }),
} as CreateNoteIntoUrlOpts } as CreateNoteWithUrlOpts
); );
if (!result.note) { if (!result.note) {

View file

@ -1,7 +1,7 @@
import treeService from "../services/tree.js"; import treeService from "../services/tree.js";
import froca from "../services/froca.js"; import froca from "../services/froca.js";
import clipboard from "../services/clipboard.js"; import clipboard from "../services/clipboard.js";
import noteCreateService, { CreateNoteAfterUrlOpts, CreateNoteIntoUrlOpts } from "../services/note_create.js"; import noteCreateService, { CreateNoteWithUrlOpts } from "../services/note_create.js";
import contextMenu, { type MenuCommandItem, type MenuItem } from "./context_menu.js"; import contextMenu, { type MenuCommandItem, type MenuItem } from "./context_menu.js";
import appContext, { type ContextMenuCommandData, type FilteredCommandNames } from "../components/app_context.js"; import appContext, { type ContextMenuCommandData, type FilteredCommandNames } from "../components/app_context.js";
import noteTypesService from "../services/note_types.js"; import noteTypesService from "../services/note_types.js";
@ -283,7 +283,7 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
isProtected: isProtected, isProtected: isProtected,
templateNoteId: templateNoteId, templateNoteId: templateNoteId,
promptForType: false, promptForType: false,
} as CreateNoteAfterUrlOpts } as CreateNoteWithUrlOpts
); );
} else if (command === "insertChildNote") { } else if (command === "insertChildNote") {
const parentNotePath = treeService.getNotePath(this.node); const parentNotePath = treeService.getNotePath(this.node);
@ -296,7 +296,7 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
isProtected: this.node.data.isProtected, isProtected: this.node.data.isProtected,
templateNoteId: templateNoteId, templateNoteId: templateNoteId,
promptForType: false, promptForType: false,
} as CreateNoteIntoUrlOpts } as CreateNoteWithUrlOpts
); );
} else if (command === "openNoteInSplit") { } else if (command === "openNoteInSplit") {
const subContexts = appContext.tabManager.getActiveContext()?.getSubContexts(); const subContexts = appContext.tabManager.getActiveContext()?.getSubContexts();

View file

@ -1,6 +1,6 @@
import server from "./server.js"; import server from "./server.js";
import appContext from "../components/app_context.js"; import appContext from "../components/app_context.js";
import noteCreateService, { CreateNoteIntoUrlOpts, CreateNoteIntoInboxOpts } from "./note_create.js"; import noteCreateService, { CreateNoteIntoInboxOpts, CreateNoteWithUrlOpts } from "./note_create.js";
import froca from "./froca.js"; import froca from "./froca.js";
import { t } from "./i18n.js"; import { t } from "./i18n.js";
import commandRegistry from "./command_registry.js"; import commandRegistry from "./command_registry.js";
@ -528,7 +528,7 @@ function initNoteAutocomplete($el: JQuery<HTMLElement>, options?: Options) {
title: suggestion.noteTitle, title: suggestion.noteTitle,
activate: true, activate: true,
promptForType: true, promptForType: true,
} as CreateNoteIntoUrlOpts, } as CreateNoteWithUrlOpts,
); );
if (!note) return; if (!note) return;
@ -549,7 +549,7 @@ function initNoteAutocomplete($el: JQuery<HTMLElement>, options?: Options) {
title: suggestion.noteTitle, title: suggestion.noteTitle,
activate: false, activate: false,
promptForType: true, promptForType: true,
} as CreateNoteIntoUrlOpts } as CreateNoteWithUrlOpts
); );
if (!note) return; if (!note) return;

View file

@ -17,9 +17,8 @@ import dateNoteService from "../services/date_notes.js";
* accepted by `note_create`. * accepted by `note_create`.
* *
* ## Overview * ## Overview
* Each variant (e.g. `CreateNoteIntoUrlOpts`, `CreateNoteBeforeUrlOpts`, etc.) * Each variant extends `CreateNoteOpts` and enforces specific constraints to
* extends `CreateNoteOpts` and enforces specific constraints to ensure only * ensure only valid note creation options are allowed at compile time.
* valid note creation options are allowed at compile time.
* *
* ## Type Safety * ## Type Safety
* The `PromptingRule` ensures that `promptForType` and `type` stay mutually * The `PromptingRule` ensures that `promptForType` and `type` stay mutually
@ -36,10 +35,7 @@ import dateNoteService from "../services/date_notes.js";
* *
* Hierarchy (general specific): * Hierarchy (general specific):
* - CreateNoteOpts * - CreateNoteOpts
* - CreateNoteAtUrlOpts * - CreateNoteWithUrlOpts
* - CreateNoteIntoUrlOpts
* - CreateNoteBeforeUrlOpts
* - CreateNoteAfterUrlOpts
* - CreateNoteIntoInboxOpts * - CreateNoteIntoInboxOpts
*/ */
@ -81,7 +77,7 @@ export type CreateNoteOpts = {
* Serves as a base for "into", "before", and "after" variants, * Serves as a base for "into", "before", and "after" variants,
* sharing common URL-related fields. * sharing common URL-related fields.
*/ */
type CreateNoteWithUrlOpts = CreateNoteOpts & { export type CreateNoteWithUrlOpts = CreateNoteOpts & {
// `Url` may refer to either parentNotePath or parentNoteId. // `Url` may refer to either parentNotePath or parentNoteId.
// The vocabulary is inspired by existing function getNoteIdFromUrl. // The vocabulary is inspired by existing function getNoteIdFromUrl.
parentNoteUrl: string; parentNoteUrl: string;
@ -90,10 +86,6 @@ type CreateNoteWithUrlOpts = CreateNoteOpts & {
targetBranchId: string; targetBranchId: string;
} }
export type CreateNoteIntoUrlOpts = CreateNoteWithUrlOpts;
export type CreateNoteBeforeUrlOpts = CreateNoteWithUrlOpts;
export type CreateNoteAfterUrlOpts = CreateNoteWithUrlOpts;
type NeverDefineParentNoteUrlRule = { type NeverDefineParentNoteUrlRule = {
parentNoteUrl?: never; parentNoteUrl?: never;
}; };
@ -155,12 +147,12 @@ async function promptForType(
} as CreateNoteOpts; } as CreateNoteOpts;
if (notePath) { if (notePath) {
resolvedOptions = resolvedOptions as CreateNoteIntoUrlOpts; resolvedOptions = resolvedOptions as CreateNoteWithUrlOpts;
resolvedOptions = { resolvedOptions = {
...resolvedOptions, ...resolvedOptions,
target: "into", target: "into",
parentNoteUrl: notePath, parentNoteUrl: notePath,
} as CreateNoteIntoUrlOpts; } as CreateNoteWithUrlOpts;
} }
return resolvedOptions; return resolvedOptions;
@ -274,7 +266,7 @@ async function createNoteIntoInbox(
{ {
...options, ...options,
parentNoteUrl: inboxNote.noteId, parentNoteUrl: inboxNote.noteId,
} as CreateNoteIntoUrlOpts } as CreateNoteWithUrlOpts
); );
return result; return result;

View file

@ -6,7 +6,7 @@ import branches from "../../../services/branches";
import { executeBulkActions } from "../../../services/bulk_action"; import { executeBulkActions } from "../../../services/bulk_action";
import froca from "../../../services/froca"; import froca from "../../../services/froca";
import { t } from "../../../services/i18n"; import { t } from "../../../services/i18n";
import note_create, { CreateNoteIntoUrlOpts } from "../../../services/note_create.js"; import note_create, { CreateNoteWithUrlOpts } from "../../../services/note_create.js";
import server from "../../../services/server"; import server from "../../../services/server";
import { ColumnMap } from "./data"; import { ColumnMap } from "./data";
@ -33,7 +33,7 @@ export default class BoardApi {
parentNoteUrl: parentNotePath, parentNoteUrl: parentNotePath,
activate: false, activate: false,
title, title,
} as CreateNoteIntoUrlOpts); } as CreateNoteWithUrlOpts);
if (newNote && newBranch) { if (newNote && newBranch) {
await this.changeColumn(newNote.noteId, column); await this.changeColumn(newNote.noteId, column);
@ -140,7 +140,7 @@ export default class BoardApi {
activate: false, activate: false,
targetBranchId: relativeToBranchId, targetBranchId: relativeToBranchId,
title: t("board_view.new-item"), title: t("board_view.new-item"),
} as CreateNoteIntoUrlOpts } as CreateNoteWithUrlOpts
); );
if (!note || !branch) { if (!note || !branch) {

View file

@ -8,7 +8,7 @@ import froca from "../../../services/froca.js";
import branches from "../../../services/branches.js"; import branches from "../../../services/branches.js";
import Component from "../../../components/component.js"; import Component from "../../../components/component.js";
import { RefObject } from "preact"; import { RefObject } from "preact";
import { CreateNoteAfterUrlOpts, CreateNoteBeforeUrlOpts } from "../../../services/note_create.js"; import { CreateNoteWithUrlOpts } from "../../../services/note_create.js";
export function useContextMenu(parentNote: FNote, parentComponent: Component | null | undefined, tabulator: RefObject<Tabulator>): Partial<EventCallBackMethods> { export function useContextMenu(parentNote: FNote, parentComponent: Component | null | undefined, tabulator: RefObject<Tabulator>): Partial<EventCallBackMethods> {
const events: Partial<EventCallBackMethods> = {}; const events: Partial<EventCallBackMethods> = {};
@ -185,7 +185,7 @@ export function showRowContextMenu(parentComponent: Component, e: MouseEvent, ro
customOpts: { customOpts: {
target: "before", target: "before",
targetBranchId: rowData.branchId, targetBranchId: rowData.branchId,
} as CreateNoteBeforeUrlOpts } as CreateNoteWithUrlOpts
}) })
}, },
{ {
@ -199,7 +199,7 @@ export function showRowContextMenu(parentComponent: Component, e: MouseEvent, ro
customOpts: { customOpts: {
target: "after", target: "after",
targetBranchId: branchId, targetBranchId: branchId,
} as CreateNoteAfterUrlOpts } as CreateNoteWithUrlOpts
}); });
} }
}, },
@ -212,7 +212,7 @@ export function showRowContextMenu(parentComponent: Component, e: MouseEvent, ro
customOpts: { customOpts: {
target: "after", target: "after",
targetBranchId: rowData.branchId, targetBranchId: rowData.branchId,
} as CreateNoteAfterUrlOpts } as CreateNoteWithUrlOpts
}) })
}, },
{ kind: "separator" }, { kind: "separator" },

View file

@ -1,6 +1,6 @@
import { EventCallBackMethods, RowComponent, Tabulator } from "tabulator-tables"; import { EventCallBackMethods, RowComponent, Tabulator } from "tabulator-tables";
import { CommandListenerData } from "../../../components/app_context"; import { CommandListenerData } from "../../../components/app_context";
import note_create, { CreateNoteOpts, CreateNoteIntoUrlOpts as CreateNoteIntoUrlOpts } from "../../../services/note_create"; import note_create, { CreateNoteOpts, CreateNoteWithUrlOpts } from "../../../services/note_create";
import { useLegacyImperativeHandlers } from "../../react/hooks"; import { useLegacyImperativeHandlers } from "../../react/hooks";
import { RefObject } from "preact"; import { RefObject } from "preact";
import { setAttribute, setLabel } from "../../../services/attributes"; import { setAttribute, setLabel } from "../../../services/attributes";
@ -23,7 +23,7 @@ export default function useRowTableEditing(api: RefObject<Tabulator>, attributeD
{ {
parentNoteUrl: notePath, parentNoteUrl: notePath,
...opts ...opts
} as CreateNoteIntoUrlOpts } as CreateNoteWithUrlOpts
).then(({ branch }) => { ).then(({ branch }) => {
if (branch) { if (branch) {
setTimeout(() => { setTimeout(() => {

View file

@ -3,7 +3,7 @@ import appContext from "../../components/app_context";
import contextMenu from "../../menus/context_menu"; import contextMenu from "../../menus/context_menu";
import branches from "../../services/branches"; import branches from "../../services/branches";
import { t } from "../../services/i18n"; import { t } from "../../services/i18n";
import note_create, { CreateNoteIntoUrlOpts } from "../../services/note_create"; import note_create, { CreateNoteWithUrlOpts } from "../../services/note_create";
import tree from "../../services/tree"; import tree from "../../services/tree";
import ActionButton from "../react/ActionButton"; import ActionButton from "../react/ActionButton";
import { ParentComponent } from "../react/react_utils"; import { ParentComponent } from "../react/react_utils";
@ -33,7 +33,7 @@ export default function MobileDetailMenu() {
{ {
target: "into", target: "into",
parentNoteUrl: appContext.tabManager.getActiveContextNotePath() ?? undefined parentNoteUrl: appContext.tabManager.getActiveContextNotePath() ?? undefined
} as CreateNoteIntoUrlOpts } as CreateNoteWithUrlOpts
); );
} else if (command === "delete") { } else if (command === "delete") {
const notePath = appContext.tabManager.getActiveContextNotePath(); const notePath = appContext.tabManager.getActiveContextNotePath();

View file

@ -5,7 +5,7 @@ import SpacedUpdate from "../services/spaced_update.js";
import server from "../services/server.js"; import server from "../services/server.js";
import appContext, { type CommandListenerData, type EventData } from "../components/app_context.js"; import appContext, { type CommandListenerData, type EventData } from "../components/app_context.js";
import keyboardActionsService from "../services/keyboard_actions.js"; import keyboardActionsService from "../services/keyboard_actions.js";
import noteCreateService, { CreateNoteIntoUrlOpts } from "../services/note_create.js"; import noteCreateService, { CreateNoteWithUrlOpts } from "../services/note_create.js";
import attributeService from "../services/attributes.js"; import attributeService from "../services/attributes.js";
import EmptyTypeWidget from "./type_widgets/empty.js"; import EmptyTypeWidget from "./type_widgets/empty.js";
@ -436,7 +436,7 @@ export default class NoteDetailWidget extends NoteContextAwareWidget {
isProtected: note.isProtected, isProtected: note.isProtected,
saveSelection: true, saveSelection: true,
textEditor: await this.noteContext.getTextEditor() textEditor: await this.noteContext.getTextEditor()
} as CreateNoteIntoUrlOpts } as CreateNoteWithUrlOpts
); );
} }
} }

View file

@ -7,7 +7,7 @@ import branchService from "../services/branches.js";
import ws from "../services/ws.js"; import ws from "../services/ws.js";
import NoteContextAwareWidget from "./note_context_aware_widget.js"; import NoteContextAwareWidget from "./note_context_aware_widget.js";
import server from "../services/server.js"; import server from "../services/server.js";
import noteCreateService, { CreateNoteIntoUrlOpts } from "../services/note_create.js"; import noteCreateService, { CreateNoteWithUrlOpts } from "../services/note_create.js";
import toastService from "../services/toast.js"; import toastService from "../services/toast.js";
import appContext, { type CommandListenerData, type EventData } from "../components/app_context.js"; import appContext, { type CommandListenerData, type EventData } from "../components/app_context.js";
import keyboardActionsService from "../services/keyboard_actions.js"; import keyboardActionsService from "../services/keyboard_actions.js";
@ -237,7 +237,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
target: "into", target: "into",
parentNoteUrl: parentNotePath, parentNoteUrl: parentNotePath,
isProtected: node.data.isProtected isProtected: node.data.isProtected
} as CreateNoteIntoUrlOpts, } as CreateNoteWithUrlOpts,
); );
} else if (target.classList.contains("enter-workspace-button")) { } else if (target.classList.contains("enter-workspace-button")) {
const node = $.ui.fancytree.getNode(e as unknown as Event); const node = $.ui.fancytree.getNode(e as unknown as Event);
@ -1854,7 +1854,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
target: "into", target: "into",
parentNoteUrl: notePath, parentNoteUrl: notePath,
isProtected: node.data.isProtected isProtected: node.data.isProtected
} as CreateNoteIntoUrlOpts } as CreateNoteWithUrlOpts
) )
} }
}), }),

View file

@ -19,7 +19,7 @@ import contextMenu from "../../../menus/context_menu";
import type { CommandData, FilteredCommandNames } from "../../../components/app_context"; import type { CommandData, FilteredCommandNames } from "../../../components/app_context";
import { AttributeType } from "@triliumnext/commons"; import { AttributeType } from "@triliumnext/commons";
import attributes from "../../../services/attributes"; import attributes from "../../../services/attributes";
import note_create, { CreateNoteAfterUrlOpts, CreateNoteIntoUrlOpts, CreateNoteIntoInboxOpts } from "../../../services/note_create"; import note_create, { CreateNoteWithUrlOpts, CreateNoteIntoInboxOpts } from "../../../services/note_create";
import { CreateNoteAction } from "@triliumnext/commons"; import { CreateNoteAction } from "@triliumnext/commons";
type AttributeCommandNames = FilteredCommandNames<CommandData>; type AttributeCommandNames = FilteredCommandNames<CommandData>;
@ -285,7 +285,7 @@ export default function AttributeEditor({ api, note, componentId, notePath, ntxI
title, title,
activate: false, activate: false,
promptForType: true, promptForType: true,
} as CreateNoteIntoUrlOpts, } as CreateNoteWithUrlOpts,
) )
return resp?.note?.getBestNotePathString() ?? ""; return resp?.note?.getBestNotePathString() ?? "";
} }

View file

@ -1,7 +1,7 @@
import utils, { hasTouchBar } from "../../services/utils.js"; import utils, { hasTouchBar } from "../../services/utils.js";
import keyboardActionService from "../../services/keyboard_actions.js"; import keyboardActionService from "../../services/keyboard_actions.js";
import froca from "../../services/froca.js"; import froca from "../../services/froca.js";
import noteCreateService, { CreateNoteIntoUrlOpts, CreateNoteIntoInboxOpts } from "../../services/note_create.js"; import noteCreateService, { CreateNoteWithUrlOpts, CreateNoteIntoInboxOpts } from "../../services/note_create.js";
import AbstractTextTypeWidget from "./abstract_text_type_widget.js"; import AbstractTextTypeWidget from "./abstract_text_type_widget.js";
import link from "../../services/link.js"; import link from "../../services/link.js";
import appContext, { type CommandListenerData, type EventData } from "../../components/app_context.js"; import appContext, { type CommandListenerData, type EventData } from "../../components/app_context.js";
@ -523,7 +523,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
title, title,
activate: true, activate: true,
promptForType: true, promptForType: true,
} as CreateNoteIntoUrlOpts } as CreateNoteWithUrlOpts
) )
return note?.getBestNotePathString() ?? ""; return note?.getBestNotePathString() ?? "";
@ -552,7 +552,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
title, title,
activate: false, activate: false,
promptForType: true, promptForType: true,
} as CreateNoteIntoUrlOpts } as CreateNoteWithUrlOpts
); );
return note?.getBestNotePathString() ?? ""; return note?.getBestNotePathString() ?? "";