From a40ab84195ee90bfcc9dbe089c59291c151fc56f Mon Sep 17 00:00:00 2001 From: Andras Timar Date: Fri, 13 Feb 2026 18:10:52 +0100 Subject: [PATCH] fix: register handler directly with ViewerService when available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When an app (e.g. richdocuments) calls registerHandler() from the @nextcloud/viewer package, the handler is stored in the global window._oca_viewer_handlers Map. These handlers are only bridged into the ViewerService (and thus into OCA.Viewer.mimetypes) by a DOMContentLoaded listener in Viewer.vue. Since all Nextcloud scripts are loaded with the defer attribute, there is a race window between the file list rendering and DOMContentLoaded firing. If the files app finishes rendering before the bridge runs, viewerAction's enabled() check reads OCA.Viewer.mimetypes before document mimetypes have been added — the viewer action is disabled and the download action takes over, causing documents to be downloaded instead of opened in Collabora/the viewer. Fix this by also registering the handler directly with the ViewerService when it is already initialized. Because viewer-init runs before other apps' init scripts (both are deferred, viewer registers its LoadViewer listener first), OCA.Viewer is guaranteed to exist when richdocuments' init-viewer script calls registerHandler(). Duplicate registration is harmless — ViewerService.registerHandler() already rejects handlers whose id is already known. Signed-off-by: Andras Timar --- src/api_package/global.d.ts | 6 ++++++ src/api_package/index.ts | 14 ++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/api_package/global.d.ts b/src/api_package/global.d.ts index ccd66138f..119493447 100644 --- a/src/api_package/global.d.ts +++ b/src/api_package/global.d.ts @@ -12,5 +12,11 @@ declare global { */ // eslint-disable-next-line camelcase _oca_viewer_handlers: Map + + OCA?: { + Viewer?: { + registerHandler?: (handler: IHandler) => void + } + } } } diff --git a/src/api_package/index.ts b/src/api_package/index.ts index bdb215809..58c7f9159 100644 --- a/src/api_package/index.ts +++ b/src/api_package/index.ts @@ -44,8 +44,9 @@ export interface IHandler { /** * Register a new handler for the viewer. - * This needs to be called before the viewer is initialized to ensure the handler is available. - * So this should be called from an initialization script (`OCP\Util::addInitScript`). + * Should be called from an initialization script (`OCP\Util::addInitScript`). + * If the ViewerService is already initialized the handler is registered + * immediately, otherwise it will be picked up on DOMContentLoaded. * * @param handler - The handler to register * @throws Error if the handler is invalid @@ -60,6 +61,15 @@ export function registerHandler(handler: IHandler): void { } window._oca_viewer_handlers.set(handler.id, handler) + + // If the ViewerService is already initialized, register the handler + // directly so its mimetypes are available immediately for file actions. + // Without this, mimetypes are only bridged on DOMContentLoaded which + // can race with the file list rendering — causing downloads instead of + // opening files in the viewer. + if (window.OCA?.Viewer?.registerHandler) { + window.OCA.Viewer.registerHandler(handler) + } } /**