Skip to content

Feat/noid/note info - #1974

Open
karlitschek wants to merge 2 commits into
mainfrom
feat/noid/note-info
Open

Feat/noid/note info#1974
karlitschek wants to merge 2 commits into
mainfrom
feat/noid/note-info

Conversation

@karlitschek

Copy link
Copy Markdown
Member

🤖 AI (if applicable)

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

Frank Karlitschek and others added 2 commits August 6, 2026 19:18
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>
The sidebar hosts Sharing and Versions but says nothing about the note
itself. This adds a first tab with category, word and character counts, a
reading estimate, size, created and modified times, the file path, and a
read-only marker when the note cannot be written.

Most of it is free: the sidebar already fetches the note's DAV node for the
Files tabs, so size and creation time come from data it was loading anyway,
and everything else is on the note in the store.

The counts are not free, and that shapes the design. The note list payload
excludes `content`, so a note that has never been opened has none client-side.
Rather than fetching every body up front, the tab pulls the one note it needs
and only once its tab is actually selected — opening the sidebar to share a
note does not drag its body down with it. Until then the row shows a
placeholder.

Counting words means ignoring the markup, otherwise '#' and '**' inflate the
number. noteStats.js strips the obvious things — fenced code, image syntax,
link targets while keeping labels, heading, quote and list markers, setext
underlines, emphasis — and leaves the rest alone. A full parse would be much
more code for a number nobody checks to the decimal. Characters are counted on
the note as stored, since that is what was typed, and by code point rather
than UTF-16 unit so astral characters count once.

The tab is Notes' own rather than a Files sidebar tab, so it renders outside
the registry loop with order 0 to sit ahead of Sharing. The "nothing to show
here" empty state now also checks for a note, so it cannot appear just because
the Files tabs failed to register.

Stacked on the sidebar generalisation: without a multi-tab sidebar there is
nowhere to put this.

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 18:32

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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

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.

2 participants