Skip to content

refactor(files): migrate to Vue 3 - #61291

Merged
skjnldsv merged 13 commits into
masterfrom
chore/files-vue3
Oct 1, 2026
Merged

skjnldsv merged 13 commits into
masterfrom
chore/files-vue3

Conversation

@susnux

@susnux susnux commented Jun 15, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Migrate the app to Vue 3.
The stupid work of migration was done with AI, but thats only changed in: 01801b5

TODO

  • fix issues with breadcrumbs
  • fix issues with reloading content
  • fix uploading
  • fix issues with actions
  • fix visual issue where navigation always has a chevron even without children
  • fix this: Uncaught (in promise) TypeError: can't access property "focus", firstButton.$el is undefined

Checklist

AI (if applicable)

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

@susnux susnux added 2. developing Work in progress feature: files ♻️ refactor Refactor code (not a bug fix, not a feature just refactoring) team: Files Code maintained by 📁 Files team labels Jun 15, 2026
@susnux susnux added this to the Nextcloud 35 milestone Jun 15, 2026
@susnux susnux self-assigned this Jun 15, 2026
@susnux
susnux force-pushed the chore/files-vue3 branch from 60e1f29 to 5faa61b Compare June 15, 2026 13:30
@blizzz blizzz mentioned this pull request Aug 27, 2026
@susnux
susnux force-pushed the chore/files-vue3 branch 2 times, most recently from a48cb03 to 4419d5d Compare September 15, 2026 18:21
@susnux
susnux changed the base branch from master to refactor/files-navigation-quota September 15, 2026 20:19
@susnux
susnux added this pull request to stack #64389 September 15, 2026 20:19
Base automatically changed from refactor/files-navigation-quota to master September 25, 2026 17:47
@susnux
susnux marked this pull request as ready for review September 30, 2026 10:48
@susnux
susnux requested review from a team and skjnldsv as code owners September 30, 2026 10:48
@susnux
susnux requested review from kristian-zendato and sorbaugh and removed request for a team September 30, 2026 10:48
@susnux susnux mentioned this pull request Sep 30, 2026
29 of 32 tasks
@susnux susnux added 3. to review Waiting for reviews and removed 2. developing Work in progress labels Sep 30, 2026
Comment thread apps/files_sharing/src/public/router.ts Outdated
Assisted-by: ClaudeCode:claude-opus-5-5
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Assisted-by: ClaudeCode:claude-opus-5-5
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Assisted-by: ClaudeCode:claude-opus-4-8
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Assisted-by: ClaudeCode:claude-opus-5-5
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
…re child views

Assisted-by: ClaudeCode:claude-opus-5-5
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Assisted-by: ClaudeCode:claude-opus-5-5
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Assisted-by: ClaudeCode:claude-opus-5
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Assisted-by: ClaudeCode:claude-opus-5-5
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
`RouterService` still read `router.currentRoute` directly, but with
vue-router 5 that is a ref, so name, params and query were always empty:
every navigation dropped the `dir` query and the fileid. It now unwraps
the ref and, because vue-router navigates asynchronously, also reports a
requested route until it is applied - otherwise the stores that each
merge their own change into the route overwrite each other.

`spawnDialog()` returns a promise since @nextcloud/vue 9, so the call
sites still passing a callback as third argument never resolved and the
"New folder" and rename dialogs hung.

The type filter looped endlessly because resetting an already empty
selection re-entered `setPresets()`, which resets again.

`Uploader.upload()` ignores the `root` option, so dropping onto a folder
row uploaded into the folder being browsed instead of the drop target.
The uploader destination is now moved to the drop target while the queue
is built.

Finally the router lost the query encoding Nextcloud URLs use: keep
spaces as "%20" instead of vue-router's "+".

On the test side: `NcCheckboxRadioSwitch` now forwards attributes to its
`<input>`, so the selection hooks sit on the checkbox itself; Vue 3
condenses the whitespace between the filename and extension spans; and
the breadcrumb helper addressed ancestors as buttons although only the
current directory is one.

Assisted-by: ClaudeCode:claude-opus-5
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
The files app is built with Vue 3 and vue-router 5, but the public share
entry point still created a vue-router 3 instance and exposed it as
`window.OCP.Files.Router`. The files app installs exactly that router, so
on a public share it ended up with a Vue 2 router in a Vue 3 app: there
was no `$route` and rendering the file list threw.

The entry point and everything only it uses now live in `src/public/` and
are built by the Vue 3 frontend, which makes that directory the boundary
between the migrated and the not yet migrated parts of the app. The
remaining entry points keep being built - and linted - as Vue 2.

`<RouterView>` needs a component to render, so the share route now points
at the file list, which the files app rendered directly before the router
was introduced.

Assisted-by: ClaudeCode:claude-opus-5
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
…cker

`NcUploadPicker` names the menu entry "Upload folder" where the Vue 2
`UploadPicker` said "Upload folders", it renders a progress bar of its
own - and the files app re-renders the file drop view while uploading,
so the list header is what reports the progress. The new uploader also
probes the destination collection before uploading, which the request
interception held back together with the file it means to delay.

Assisted-by: ClaudeCode:claude-opus-5
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
The sidebar API brought back on master still rendered the sidebar with
the Vue 2 constructor API and set the Webpack nonce in its entry point.
Mount it as a Vue 3 app instead. As Vue 3 renders into the mountpoint
rather than replacing it, the mountpoint uses `display: contents` so the
sidebar keeps being laid out as a child of the target element.

The Vue 3 stores return reactive proxies of the nodes, so the provider
spec compares the raw nodes.

Assisted-by: ClaudeCode:claude-opus-5-5
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
…ent file

The delete handler bypassed the router service, so the sidebar closing
navigated from the outdated route and restored the deleted file's id.
Navigate through the router service instead.

Assisted-by: ClaudeCode:claude-opus-5-5
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
@skjnldsv
skjnldsv merged commit fe2bc92 into master Oct 1, 2026
160 of 162 checks passed
@skjnldsv
skjnldsv deleted the chore/files-vue3 branch October 1, 2026 05:39
@pringelmann

Copy link
Copy Markdown
Contributor

Found a few more bugs...will open separate issues

vitormattos added a commit to LibreSign/libresign that referenced this pull request Oct 1, 2026
Nextcloud master migrated the Files app to Vue 3 and NcUploadPicker
(nextcloud/server#61291), whose hidden input has no
data-cy-upload-picker-input attribute. Open New > Upload files and feed
the file chooser instead, which works with both upload pickers.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3. to review Waiting for reviews AI assisted feature: files force-e2e-tests ♻️ refactor Refactor code (not a bug fix, not a feature just refactoring) team: Files Code maintained by 📁 Files team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants