From 40bea6f54b4c82115875a0deddc0f78d68babeca Mon Sep 17 00:00:00 2001 From: Mike Kaganski Date: Tue, 19 Nov 2024 13:11:52 +0500 Subject: [PATCH 1/2] Implement support for insertion of multimedia from Nextcloud assets This change adds ability to insert multimedia files from Nextcloud to Impress documents. It advertises EnableInsertRemoteFile capability, so that Office activates the feature (depends on Office including commit 60d9a9c20bf69b3f1d8591b2d8400c4a453970ab - older builds won't show the respective button). Signed-off-by: Mike Kaganski Signed-off-by: Elizabeth Danzberger --- docs/frontend-integration.md | 4 ++++ lib/Controller/WopiController.php | 1 + src/view/FilesAppIntegration.js | 26 ++++++++++++++++++-------- src/view/Office.vue | 8 ++++++++ 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/docs/frontend-integration.md b/docs/frontend-integration.md index 1c92f32b7a..7c031663c8 100644 --- a/docs/frontend-integration.md +++ b/docs/frontend-integration.md @@ -100,6 +100,10 @@ The following handlers are currently supported: - insertGraphic: will be called when an image from the Nextcloud storage should be inserted - Arguments - insertFileFromPath(path): Callback to trigger the actual inserting of the graphic from an absolute file path +- insertFile: will be called when a file (e.g., multimedia) from the Nextcloud storage should be inserted (generalized insertGraphic) + - Arguments + - mimeTypeFilter: array of MIME types (strings) to filter in the UI + - insertFileFromPath(path): Callback to trigger the actual inserting of the file from an absolute file path In addition, the following handlers can be used to overwrite the handling of file actions that are rendered in the Nextcloud header bar: - actionDetails diff --git a/lib/Controller/WopiController.php b/lib/Controller/WopiController.php index d93f16c91d..be8e328cb4 100644 --- a/lib/Controller/WopiController.php +++ b/lib/Controller/WopiController.php @@ -153,6 +153,7 @@ public function checkFileInfo($fileId, $access_token) { 'SupportsRename' => !$isVersion && !$wopi->isRemoteToken(), 'UserCanRename' => !$isPublic && !$isVersion && !$wopi->isRemoteToken(), 'EnableInsertRemoteImage' => !$isPublic, + 'EnableInsertRemoteFile' => !$isPublic, 'EnableShare' => $file->isShareable() && !$isVersion && !$isPublic, 'HideUserList' => '', 'EnableOwnerTermination' => $wopi->getCanwrite() && !$isPublic, diff --git a/src/view/FilesAppIntegration.js b/src/view/FilesAppIntegration.js index b1d8631e33..1a7f016fb6 100644 --- a/src/view/FilesAppIntegration.js +++ b/src/view/FilesAppIntegration.js @@ -149,30 +149,30 @@ export default { } }, - insertGraphic(insertFile) { - if (isPublic) { - console.error('[FilesAppIntegration] insertGraphic is not supported') + insertFile_impl(mimeTypeFilter, insertFileProc, insertHandler) { + if (isPublicShare()) { + console.error('[FilesAppIntegration] insertFile is not supported') } const insertFileFromPath = async (path) => { const filename = path.substring(path.lastIndexOf('/') + 1) const { data } = await axios.post(generateUrl('apps/richdocuments/assets'), { path }) - insertFile(filename, data.url) + insertFileProc(filename, data.url) } - if (this.handlers.insertGraphic && this.handlers.insertGraphic(this, { insertFileFromPath })) { + if (insertHandler && insertHandler(this, mimeTypeFilter, { insertFileFromPath })) { return } - getFilePickerBuilder(t('richdocuments', 'Insert image from {name}', { name: OC.theme.name })) - .setMimeTypeFilter(['image/png', 'image/gif', 'image/jpeg', 'image/svg']) + getFilePickerBuilder(t('richdocuments', 'Insert file from {name}', { name: OC.theme.name })) + .setMimeTypeFilter(mimeTypeFilter) .setFilter((node) => { const downloadShareAttribute = JSON.parse(node.attributes['share-attributes']).find((shareAttribute) => shareAttribute.key === 'download') const downloadPermissions = downloadShareAttribute !== undefined ? (downloadShareAttribute.enabled || downloadShareAttribute.value) : true return (node.permissions & OC.PERMISSION_READ) && downloadPermissions }) .addButton({ - label: t('richdocuments', 'Insert image'), + label: t('richdocuments', 'Insert file'), callback: (files) => { if (files && files.length) { insertFileFromPath(files[0].path) @@ -183,6 +183,16 @@ export default { .pick() }, + insertGraphic(insertFileProc) { + this.insertFile_impl(['image/png', 'image/gif', 'image/jpeg', 'image/svg'], + insertFileProc, + (filesAppIntegration, mimeTypeFilter, { insertFileFromPath }) => { return this.handlers.insertGraphic && this.handlers.insertGraphic(filesAppIntegration, { insertFileFromPath }) }) + }, + + insertFile(mimeTypeFilter, insertFileProc) { + this.insertFile_impl(mimeTypeFilter, insertFileProc, this.handlers.insertFile) + }, + getFileList() { if (this.fileList) { return this.fileList diff --git a/src/view/Office.vue b/src/view/Office.vue index a202bfe769..449463ac1e 100644 --- a/src/view/Office.vue +++ b/src/view/Office.vue @@ -428,6 +428,14 @@ export default { }) }) break + case 'UI_InsertFile': + FilesAppIntegration.insertFile(args.mimeTypeFilter, (filename, url) => { + this.postMessage.sendWOPIPostMessage(FRAME_DOCUMENT, args.callback, { + filename, + url, + }) + }) + break case 'UI_Mention': this.uiMention(parsed.args) break From 2dbf4e3500a9b2af73e771e237624e66415c5ef4 Mon Sep 17 00:00:00 2001 From: Elizabeth Danzberger Date: Fri, 29 Nov 2024 15:30:44 -0500 Subject: [PATCH 2/2] chore: resolve lint errors Signed-off-by: Elizabeth Danzberger --- src/components/Modal/ZoteroHint.vue | 2 +- src/view/FilesAppIntegration.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Modal/ZoteroHint.vue b/src/components/Modal/ZoteroHint.vue index dec1f09a50..344e077e75 100644 --- a/src/components/Modal/ZoteroHint.vue +++ b/src/components/Modal/ZoteroHint.vue @@ -4,7 +4,7 @@ -->