Repository navigation
fix(viewer): migrate to @nextcloud/viewer for Nextcloud 36 - #375
Merged
Merged
Conversation
AndyScherzinger
force-pushed
the
fix/viewer-library
branch
from
October 10, 2026 15:35
61ddb91 to
099c9c1
Compare
Nextcloud 36 dropped array access on the server container, so \OC::$server[...] fails with "Cannot use object of type OC\Server as array" and the viewer iframe returns a 500. OCP\Server::get() is the public API for this and works on all supported versions. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Nextcloud 36 removes the viewer app. OCA.Viewer.registerHandler() and setRootElement() are gone and the LoadViewer event is never dispatched, so mind maps no longer open at all. - Register the handler with @nextcloud/viewer from an init script loaded on BeforeTemplateRenderedEvent. - Render the editor iframe from a native custom element instead of a Vue 2 component built on the viewer mixin. - Open and close the viewer through getViewer(). The edit file action is only registered on Nextcloud 32, from 33 on the viewer registers the actions for its handlers itself. - Mount the element directly into the public share page instead of pointing the viewer at it. Closes #353 Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
The custom renderBuiltUrl emitted a bare OC.filePath(), which a minified top-level function named OC can shadow. With the viewer library bundled, lazy chunks then fail to load wherever this app's copy of the viewer is the one mounted, e.g. on Nextcloud 32. @nextcloud/vite-config already emits window.OC.filePath() itself. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
The toast was handed the Error object, which made it throw and hid the actual error. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
On Nextcloud 32 and later the public share page is rendered by the Files app and opens single-file shares through the default file action, so the #files-public-content container public.js waited for does not exist on any supported version. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
The handler registration runs on every page, but pulled in the whole editor logic with it: dialogs, axios, jszip, and @nextcloud/files-legacy with its WebDAV client and Node polyfills, about 1 MB. - Register the handler from constants and the element only, and load mindmap.js when a mind map is first shown. - Load the Nextcloud 32 file action from its own chunk, only on 32. What every page loads drops from 1062 kB (301 kB gzip) to 169 kB (61 kB gzip), most of it the @nextcloud/viewer entry itself. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Where no newer copy is on the page, this app's copy is the viewer that gets mounted, so ship the current one. Its breaking changes do not affect this app: open() is called without callbacks, and compare() and canCompare are not used. The 'default' theme now follows the user's theme again, as it did with the viewer app. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
None of the rules in css/style.css apply on a supported version: - the #body-public rules styled the old public share page, which the Files app renders since at least Nextcloud 32 - the .ie rule targeted Internet Explorer - nothing renders a #mmframe element - .icon-mindmap was only the template creator's fallback for servers without setIconSvgInline(), which exists since Nextcloud 29 Drop it together with LoadAdditionalListener, which only added it to the Files app, its link in the editor iframe, and the fallback. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
AndyScherzinger
force-pushed
the
fix/viewer-library
branch
from
October 17, 2026 12:34
c0abc6a to
92f5388
Compare
From @nextcloud/viewer 2.0.0-beta.17 the default theme follows the user's theme, but on a light theme the header title stays light on the white header and is barely readable. The dark theme keeps the header readable on every theme. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
The viewer hides a handler until it emits `loaded`. Emitting it on the iframe's load event left the editor hidden while it started, so it laid out its toolbar and nodes without a size: in Firefox the toolbar stayed empty and the root node sat clipped in the corner, depending on how quickly the iframe loaded. Emit `loaded` as soon as the iframe is inserted, as the Vue component did with doneLoading(). Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
This was referenced Oct 17, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #353
Mind maps no longer open on Nextcloud 36, for two reasons:
templates/viewer.phpused\OC::$server[...], and array access on the server container is gone in 36 (Cannot use object of type OC\Server as array). It now usesOCP\Server::get().LoadVieweris no longer dispatched, andOCA.Viewer.registerHandler()/setRootElement()no longer exist.Changes
@nextcloud/viewer(^2.0.0-beta.18) from an init script loaded onBeforeTemplateRenderedEvent. The viewer also registers the Files "View" / "Open with" actions for it.src/views/MindMap.jsis now a native custom element rendering the editor iframe, replacing the Vue 2 component built on the viewer mixin. It emitsloadedas soon as the iframe is inserted: the viewer hides a handler until then, and the editor lays out its toolbar and nodes once on startup, so it must not start hidden (in Firefox the toolbar otherwise stays empty).OCA.FilesMindMap.close()→getViewer().close().darktheme. With 2.0.0-beta.17+ thedefaulttheme follows the user's theme, but on a light theme the header title stays light on white and is barely readable (Header title is barely readable with the default theme on a light theme nextcloud-libraries/nextcloud-viewer#150).defaultcan come back once that is fixed.mindmap.js, with dialogs, axios and jszip) loads when a mind map is first shown. What every page loads is about 170 kB (62 kB gzip), most of it the@nextcloud/viewerentry itself.@nextcloud/files4 (33+) passes a context object toenabled()/exec(), so this action never matched there, and the viewer's own actions cover it.max-versionraised to 36.renderBuiltUrlinvite.config.tsis dropped. It emitted a bareOC.filePath(), which a minified top-levelfunction OCin the bundle shadows, so lazy chunks failed to load wherever this app's copy of the viewer is mounted (e.g. 32).@nextcloud/vite-configalready emitswindow.OC.filePath().Errorobject, which made the toast itself throw.public.jsandLoadPublicViewerListener: on 32+ public share pages are rendered by the Files app and open single-file shares through the default file action, so the#files-public-contentcontainer they waited for never exists.css/style.cssandLoadAdditionalListener, which only loaded it, plus its link in the editor page and the template creator'sicon-mindmapfallback. None of its rules apply on 32+, andsetIconSvgInline()exists since 29.src/__tests__/MindMap.spec.js, replaced bymindmapElement.spec.js. Besides testing the removed Vue component, it collided withmindmap.spec.json case-insensitive filesystems.Testing
Tested in Chromium and Firefox at the head of this branch:
The last row holds back the editor page's load event, which reproduces the empty toolbar with the previous approach of emitting
loadedon the iframe's load event. On 36 this app's copy of the viewer is elected over the server's 2.0.0-beta.15. On 32 and 34 the old viewer app keeps itsOCA.Viewerglobal while the library's registry (window._nc_viewer_scope) only holds this handler, so both coexist. 33 and 35 were not tested separately. Vitest passes.🤖 AI (if applicable)