From e01d835709a6b600c1d2b078c01120bf343fbac1 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 18 Apr 2026 19:04:22 +0300 Subject: [PATCH] feat(revisions): add a shortcut to save named revisions --- apps/client/src/components/app_context.ts | 1 + apps/client/src/components/entrypoints.ts | 18 +++++++++++++ .../src/translations/en/translation.json | 4 +++ apps/client/src/widgets/dialogs/revisions.tsx | 16 ++++++++++++ .../client/src/widgets/ribbon/NoteActions.tsx | 1 + .../Notes/Note Revisions.html | 26 ++++++++++++------- .../src/assets/translations/en/server.json | 4 ++- apps/server/src/services/keyboard_actions.ts | 8 ++++++ docs/User Guide/!!!meta.json | 7 +++++ .../Notes/Note Revisions.md | 8 ++++++ .../src/lib/keyboard_actions_interface.ts | 3 ++- 11 files changed, 85 insertions(+), 11 deletions(-) diff --git a/apps/client/src/components/app_context.ts b/apps/client/src/components/app_context.ts index 27fc2e1396..ba213a4edf 100644 --- a/apps/client/src/components/app_context.ts +++ b/apps/client/src/components/app_context.ts @@ -281,6 +281,7 @@ export type CommandMappings = { backInNoteHistory: CommandData; forwardInNoteHistory: CommandData; forceSaveRevision: CommandData; + saveNamedRevision: CommandData; scrollToActiveNote: CommandData; quickSearch: CommandData; collapseTree: CommandData; diff --git a/apps/client/src/components/entrypoints.ts b/apps/client/src/components/entrypoints.ts index 8fc4e1b3d5..781790e156 100644 --- a/apps/client/src/components/entrypoints.ts +++ b/apps/client/src/components/entrypoints.ts @@ -1,6 +1,7 @@ import { CreateChildrenResponse, SqlExecuteResponse } from "@triliumnext/commons"; import bundleService from "../services/bundle.js"; +import dialog from "../services/dialog.js"; import dateNoteService from "../services/date_notes.js"; import froca from "../services/froca.js"; import { t } from "../services/i18n.js"; @@ -216,4 +217,21 @@ export default class Entrypoints extends Component { toastService.showMessage(t("entrypoints.note-revision-created")); } + + async saveNamedRevisionCommand() { + const noteId = appContext.tabManager.getActiveContextNoteId(); + if (!noteId) return; + + const name = await dialog.prompt({ + title: t("entrypoints.save-named-revision-title"), + message: t("entrypoints.save-named-revision-message"), + defaultValue: "" + }); + + // null means the user cancelled + if (name === null) return; + + await server.post(`notes/${noteId}/revision`, { description: name || undefined }); + toastService.showMessage(t("entrypoints.note-revision-created")); + } } diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 0367588547..7d4856a5b9 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -302,6 +302,7 @@ "snapshot_interval": "Note Revision Snapshot Interval: {{seconds}}s.", "maximum_revisions": "Note Revision Snapshot Limit: {{number}}.", "save_revision_now": "Save a revision now", + "save_named_revision": "Save named revision...", "snapshot_header": "Note revision snapshot", "snapshot_interval_value": "Interval: {{seconds}}s", "snapshot_limit_value": "Limit: {{number}}", @@ -746,6 +747,7 @@ "print_note": "Print note", "view_revisions": "Note revisions...", "save_revision": "Save revision", + "save_named_revision": "Save named revision...", "advanced": "Advanced", "convert_into_attachment_failed": "Converting note '{{title}}' failed.", "convert_into_attachment_successful": "Note '{{title}}' has been converted to attachment.", @@ -1925,6 +1927,8 @@ }, "entrypoints": { "note-revision-created": "Note revision has been created.", + "save-named-revision-title": "Save named revision", + "save-named-revision-message": "Enter a name for this revision (leave empty for no name):", "note-executed": "Note executed.", "sql-error": "Error occurred while executing SQL query: {{message}}" }, diff --git a/apps/client/src/widgets/dialogs/revisions.tsx b/apps/client/src/widgets/dialogs/revisions.tsx index e9f67d88f5..d36d509cc8 100644 --- a/apps/client/src/widgets/dialogs/revisions.tsx +++ b/apps/client/src/widgets/dialogs/revisions.tsx @@ -199,6 +199,22 @@ function RevisionsMenu({ note, onRevisionSaved, onAllDeleted, hasRevisions }: { > {t("revisions.save_revision_now")} + { + const name = await dialog.prompt({ + title: t("entrypoints.save-named-revision-title"), + message: t("entrypoints.save-named-revision-message"), + defaultValue: "" + }); + if (name === null) return; + await server.post(`notes/${note.noteId}/revision`, { description: name || undefined }); + toast.showMessage(t("revisions.revision_saved")); + onRevisionSaved(); + }} + > + {t("revisions.save_named_revision")} + {t("revisions.snapshot_header")} diff --git a/apps/client/src/widgets/ribbon/NoteActions.tsx b/apps/client/src/widgets/ribbon/NoteActions.tsx index 6490542d78..f9442f7185 100644 --- a/apps/client/src/widgets/ribbon/NoteActions.tsx +++ b/apps/client/src/widgets/ribbon/NoteActions.tsx @@ -153,6 +153,7 @@ export function NoteContextMenu({ note, noteContext, itemsAtStart, itemsNearNote + diff --git a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.html b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.html index 7a3a2c743e..fcbe2334a9 100644 --- a/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.html +++ b/apps/server/src/assets/doc_notes/en/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.html @@ -62,16 +62,24 @@

Named revisions

Named revisions are a new feature of Trilium v0.103.0 which allows adding a short description of what the changes in the snapshot contain.

+

In the list of note revisions:

    -
  • -

    The name of the revision is displayed underneath the time of the revision - in the sidebar, as well as at the top of the dialog where it is displayed - in full.

    -
  • -
  • -

    Clicking on the edit button near the name of the revision allows it to - be changed.

    -
  • +
  • The name of the revision is displayed underneath the time of the revision + in the sidebar, as well as at the top of the dialog where it is displayed + in full.
  • +
  • Clicking on the edit button near the name of the revision allows it to + be changed.
  • +
+

To create a named revision, either:

+
    +
  • Go to the Note buttons, + select Save named revision…, enter the name of revision and confirm.
  • +
  • Use the corresponding keyboard shortcut or + the Jump to... command + with the same name.
  • +
  • Save a revision normally, and adjust the name afterwards from the note + revision list.

When revisions are saved

Revisions are saved:

diff --git a/apps/server/src/assets/translations/en/server.json b/apps/server/src/assets/translations/en/server.json index 23c8347aee..5ba0c138e9 100644 --- a/apps/server/src/assets/translations/en/server.json +++ b/apps/server/src/assets/translations/en/server.json @@ -100,6 +100,7 @@ "reset-zoom-level": "Reset zoom level", "copy-without-formatting": "Copy selected text without formatting", "force-save-revision": "Force creating / saving new note revision of the active note", + "save-named-revision": "Save a named revision of the active note", "toggle-book-properties": "Toggle Collection Properties", "toggle-classic-editor-toolbar": "Toggle the Formatting tab for the editor with fixed toolbar", "export-as-pdf": "Export the current note as a PDF", @@ -200,7 +201,8 @@ "zoom-in": "Zoom In", "reset-zoom-level": "Reset Zoom Level", "copy-without-formatting": "Copy Without Formatting", - "force-save-revision": "Force Save Revision" + "force-save-revision": "Force Save Revision", + "save-named-revision": "Save Named Revision" }, "login": { "title": "Login", diff --git a/apps/server/src/services/keyboard_actions.ts b/apps/server/src/services/keyboard_actions.ts index 326672eeb2..558d85ea5e 100644 --- a/apps/server/src/services/keyboard_actions.ts +++ b/apps/server/src/services/keyboard_actions.ts @@ -828,6 +828,14 @@ function getDefaultKeyboardActions() { defaultShortcuts: [], description: t("keyboard_actions.force-save-revision"), scope: "window" + }, + { + actionName: "saveNamedRevision", + friendlyName: t("keyboard_action_names.save-named-revision"), + iconClass: "bx bx-purchase-tag", + defaultShortcuts: [], + description: t("keyboard_actions.save-named-revision"), + scope: "window" } ]; diff --git a/docs/User Guide/!!!meta.json b/docs/User Guide/!!!meta.json index aeda15c94d..27057f940a 100644 --- a/docs/User Guide/!!!meta.json +++ b/docs/User Guide/!!!meta.json @@ -4574,6 +4574,13 @@ "value": "A9Oc6YKKc65v", "isInheritable": false, "position": 90 + }, + { + "type": "relation", + "name": "internalLink", + "value": "F1r9QtzQLZqm", + "isInheritable": false, + "position": 100 } ], "format": "markdown", diff --git a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.md b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.md index 1d44e22ffd..1a75dee966 100644 --- a/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.md +++ b/docs/User Guide/User Guide/Basic Concepts and Features/Notes/Note Revisions.md @@ -32,9 +32,17 @@ Trilium supports seamless versioning of notes by storing snapshots ("revisions") Named revisions are a new feature of Trilium v0.103.0 which allows adding a short description of what the changes in the snapshot contain. +In the list of note revisions: + * The name of the revision is displayed underneath the time of the revision in the sidebar, as well as at the top of the dialog where it is displayed in full. * Clicking on the edit button near the name of the revision allows it to be changed. +To create a named revision, either: + +* Go to the Note buttons, select _Save named revision…_, enter the name of revision and confirm. +* Use the corresponding [keyboard shortcut](../Keyboard%20Shortcuts.md) or the Jump to... command with the same name. +* Save a revision normally, and adjust the name afterwards from the note revision list. + ## When revisions are saved Revisions are saved: diff --git a/packages/commons/src/lib/keyboard_actions_interface.ts b/packages/commons/src/lib/keyboard_actions_interface.ts index ce2defcd63..159785d4a8 100644 --- a/packages/commons/src/lib/keyboard_actions_interface.ts +++ b/packages/commons/src/lib/keyboard_actions_interface.ts @@ -94,7 +94,8 @@ const enum KeyboardActionNamesEnum { zoomIn, zoomReset, copyWithoutFormatting, - forceSaveRevision + forceSaveRevision, + saveNamedRevision } export type KeyboardActionNames = keyof typeof KeyboardActionNamesEnum;