Skip to content

feat(notes): expose file versions in the note sidebar - #1972

Open
karlitschek wants to merge 1 commit into
mainfrom
feat/noid/expose-versions
Open

feat(notes): expose file versions in the note sidebar#1972
karlitschek wants to merge 1 commit into
mainfrom
feat/noid/expose-versions

Conversation

@karlitschek

Copy link
Copy Markdown
Member

Notes have been versioned all along — they are ordinary files, so files_versions keeps history for them without the app doing anything. There was just no way to see it from Notes.

Most of the wiring already existed:

  • PageController dispatches OCA\Files\Event\LoadSidebar, and files_versions registers a listener on that event which adds its sidebar-tab script. The Versions tab has therefore been registered on every Notes page already, simply never rendered.
  • NotePlain and NoteRich both already subscribe to files_versions:restore:requested and :restored, showing a loading state and refreshing the note afterwards. The restore path was built and unreachable.
  • NoteShareSidebar already knew how to mount a registered Files sidebar tab as a custom element with the node/folder/view props it expects.

The only thing missing was that the sidebar hard-filtered the tab registry down to id === 'sharing'. It now renders every tab from an allow-list, so Sharing and Versions sit side by side.

Details:

  • Tab selection moved to a pure function in sidebarTabs.js. It is an allow-list rather than "everything registered", because LoadSidebar brings in whatever every installed app registers and a note sidebar should not grow new tabs when an unrelated app is installed. A tab's own enabled() predicate still has the final say — the versions tab hides itself on public shares and for non-files — but it needs a node to judge, so while the node is still loading tabs are kept and filtered again once it arrives, and a predicate that throws drops that tab instead of taking the sidebar down.
  • Tabs initialise independently, so one failing to define its custom element no longer hides the others; only a total failure is reported.
  • New event notes:sidebar:open carries a tab id. notes:share:open is kept as a thin wrapper so anything already emitting it keeps working.
  • "Versions" action added to the note's action menu, next to "Share". That menu lives in the note list row, so it is present in every editor mode rather than only the non-default one.
  • Sidebar copy no longer says "sharing" now that it hosts two tabs. The data-cy-notes-share-sidebar hook is deliberately unchanged, since playwright/e2e/basic.spec.ts asserts on it.

🤖 AI (if applicable)

  • The content of this PR was partly or fully generated using AI

Notes have been versioned all along — they are ordinary files, so
files_versions keeps history for them without the app doing anything. There
was just no way to see it from Notes.

Most of the wiring already existed:

* PageController dispatches OCA\Files\Event\LoadSidebar, and files_versions
  registers a listener on that event which adds its sidebar-tab script. The
  Versions tab has therefore been registered on every Notes page already,
  simply never rendered.
* NotePlain and NoteRich both already subscribe to
  files_versions:restore:requested and :restored, showing a loading state and
  refreshing the note afterwards. The restore path was built and unreachable.
* NoteShareSidebar already knew how to mount a registered Files sidebar tab as
  a custom element with the node/folder/view props it expects.

The only thing missing was that the sidebar hard-filtered the tab registry
down to `id === 'sharing'`. It now renders every tab from an allow-list, so
Sharing and Versions sit side by side.

Details:

* Tab selection moved to a pure function in sidebarTabs.js. It is an
  allow-list rather than "everything registered", because LoadSidebar brings
  in whatever every installed app registers and a note sidebar should not
  grow new tabs when an unrelated app is installed. A tab's own enabled()
  predicate still has the final say — the versions tab hides itself on public
  shares and for non-files — but it needs a node to judge, so while the node
  is still loading tabs are kept and filtered again once it arrives, and a
  predicate that throws drops that tab instead of taking the sidebar down.
* Tabs initialise independently, so one failing to define its custom element
  no longer hides the others; only a total failure is reported.
* New event notes:sidebar:open carries a tab id. notes:share:open is kept as
  a thin wrapper so anything already emitting it keeps working.
* "Versions" action added to the note's action menu, next to "Share". That
  menu lives in the note list row, so it is present in every editor mode
  rather than only the non-default one.
* Sidebar copy no longer says "sharing" now that it hosts two tabs. The
  data-cy-notes-share-sidebar hook is deliberately unchanged, since
  playwright/e2e/basic.spec.ts asserts on it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@karlitschek
karlitschek requested review from enjeck and silverkszlo and a lite review from Copilot and removed request for enjeck and silverkszlo August 6, 2026 17:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Expose file version history for Notes by rendering the Files “Versions” sidebar tab alongside Sharing, and add a Versions shortcut in the note actions menu.

Changes:

  • Add a tab allow-list and selection helper to render only Sharing + Versions tabs in Notes.
  • Update NoteShareSidebar to render multiple sidebar tabs, initialize them independently, and support opening the sidebar with a specific tab.
  • Add a “Versions” action in note row actions that opens the sidebar directly on the Versions tab.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
src/sidebarTabs.js Introduces allow-list + selection logic for which Files sidebar tabs Notes will render.
src/components/NoteShareSidebar.vue Renders multiple tabs, adds a new open event with tab id, and refactors initialization/context loading.
src/components/NoteItem.vue Adds a “Versions” action that opens the sidebar to the versions tab.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +170 to 179
async initializeTab(tab) {
if (window.customElements.get(tab.tagName) || this.initializedTabs.has(tab.tagName)) {
this.loadingTab = false
this.tabError = ''
return
return true
}

if (this.initializingTabs.has(tab.tagName)) {
// another open is already awaiting this one
this.loadingTab = true
return
return true
}
Comment on lines +247 to 251
async onSidebarOpen({ noteId, tab = 'sharing' }) {
this.contextRequestToken += 1
this.noteId = Number(noteId)
this.activeTab = 'sharing'
this.activeTab = tab
this.isOpen = true
Comment thread src/sidebarTabs.js
Comment on lines +41 to +45
try {
return tab.enabled({ node, folder, view })
} catch {
return false
}

@enjeck enjeck left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pls add screenshots showing what the UI looks like. Maybe significant enough tp require designer input

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants