Feat/external apps integrations - #262
Merged
Merged
Conversation
Lets a browser-local localStorage preference (key "preferredOfficeAppName") win over the backend/admin-configured hasPriority default when deciding which app opens an office file from the file listing - but only among the actions actually available for that resource, so it's a no-op when the preferred app doesn't support a given file type. Written by the office-app-feedback web-extension's "make this the default for this browser" option. Deliberately reads localStorage inline rather than through a proper store - this is meant to be temporary (a couple of months) while piloting alternative office apps, and removed once no longer needed. Does not affect the legacy external-app bookmark redirect (web-app-external/src/Redirect.vue), which keeps using the backend default as before. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
rawe0
approved these changes
Jul 28, 2026
rawe0
left a comment
There was a problem hiding this comment.
If everything works then I'm okay with merging this, but maybe we should look over the logic for searching for users a bit.
diocas
force-pushed
the
feat/external_apps_integrations
branch
from
July 29, 2026 14:23
37604f8 to
8befade
Compare
When the app-open response carries a forced_viewmode_reason, a warning banner already told the user why they're stuck in a forced view mode. This adds a "Switch to <app>" action to that banner: it reads the name of the app currently holding the lock, matches it against the external apps actually configured (appProviderService.appNames), and - if there's a match other than the app already open - lets the user jump straight into that app for concurrent editing instead of staying read-only.
….vue Introduces the app-agnostic scaffolding for the office postMessage integration: OfficePostMessageContext/OfficePostMessageRegistration/ OfficePostMessageFactory (types.ts), the registry that picks the right per-app handler by app name and delegates message handling/resource-change notifications to it (registry.ts), and postMessageToIframe, the one place that builds and posts WOPI-shaped messages back to the app iframe. App.vue wires this in: registers/unregisters the handler on mount/unmount, forwards window "message" events from the resolved app origin into the registry, warns before unload if the active handler reports pending mentions, and reacts to isAppLoaded (MS365's "connection issues" alert, Collabora's first-open modal) - none of these behaviors do anything until the per-app handlers and shared functions land in the following commits. Remove Collabora Experimental Banner. Moves isOfficeAlertClosed/showOfficeAlert out of App.vue into their own composable, mirroring useCollaboraModal.ts's shape (an is*Closed computed plus a show* function). Takes App.vue's generic showAlert DOM-builder as a dependency rather than duplicating it, since that builder is also used by the unrelated file-locked warning (showWarningAlert) and stays in App.vue. Dedupe resource watch, otherwise it re-fires on indicator mutation.
Collabora Online's WOPI postMessage protocol - App_LoadingStatus (replies Host_PostmessageReady), Doc_ModifiedStatus/UI_Close (flush mentions), UI_SaveAs/Action_Save_Resp (save-as + navigate to the renamed file), UI_InsertGraphic/UI_InsertFile/UI_PickLink (file/link picker round-trips), and UI_Mention (autocomplete + queueing selected mentions). Delegates to useOfficeFileOperations.ts and useMentionNotifications.ts for the actual behavior, landing in a following commit.
Microsoft 365 for the web's WOPI postMessage protocol: App_LoadingStatus (replies Host_PostmessageReady - MS365 disables some of its own UI, e.g. Share, until it gets this back; exposes isLoaded), UI_Edit (switches to write mode), UI_Sharing (opens the share dialog via useShareDialog.ts). UI_Close/UI_FileVersions/File_Rename/Edit_Notification stay documented stubs pending backend confirmation of their exact behavior/payloads.
EuroOffice's (OnlyOffice-engine) WOPI postMessage protocol, confirmed against api.onlyoffice.com's WOPI postmessage docs: App_LoadingStatus (replies Host_PostmessageReady, exposes isLoaded), UI_Sharing (opens the share dialog via useShareDialog.ts, landing in a following commit). UI_Close/UI_FileVersions/File_Rename/Edit_Notification stay documented stubs - the docs don't specify their Values payloads. Blur_Focus/Grab_Focus are intentionally not handled - they're host -> iframe only per the docs, nothing to receive.
Behavior shared by more than one app's postMessage handler, implemented
once and reused rather than duplicated per app:
- useOfficeFileOperations.ts: saveAs, insertGraphic/insertFile (open the
embed-mode file picker, read the download URL straight off the picked
resource) and insertLink (privateLink), used by Collabora today.
- useMentionNotifications.ts: resolves @mention autocomplete candidates,
queues a pick without granting access yet, and once the comment is
actually finished (not merely picked from the list), grants access to
anyone who doesn't already have it and flushes the queue via
POST {serverUrl}/app/mentions. Used by Collabora today.
- useShareDialog.ts: opens the share dialog, used by EuroOffice and MS365.
- useCollaboraModal.ts: tracks whether the first-open "office" modal has
been dismissed (localStorage-backed), used by App.vue for Collabora.
include username in mention labels, fall back to service/secondary accounts
- Office apps (e.g. Collabora) re-match the typed query against the label
they were given for each candidate - a label with only the display name
doesn't contain what was typed if someone searches by login/username, so
the entry silently fails to show up as a match. Labels are now
"Name Surname (username)" when onPremisesSamAccountName is available.
- CERN: the default user search only covers primary (personal) accounts.
When it comes up empty, resolveMentionCandidates now also searches service
and secondary accounts (userType eq 'Service'/'Secondary') - same account
types InviteCollaboratorForm.vue's per-role-type filters already use, as
two separate calls since the graph API's $filter doesn't support "or" -
only on the empty-result path, to avoid the extra round-trips on the
common case.
…shared functions Unit tests for everything added across the preceding commits: registry registration/dispatch/teardown, each app's postMessage dispatch table, useMentionNotifications' full mention-then-share-then-notify flow, useOfficeFileOperations, useShareDialog, useCollaboraModal, and App.vue's handler registration, origin filtering, and beforeunload mentions warning.
diocas
force-pushed
the
feat/external_apps_integrations
branch
from
July 29, 2026 14:44
8befade to
e1f4f89
Compare
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.
External apps integrations like mentions and file picker.