From 60d9a9c20bf69b3f1d8591b2d8400c4a453970ab Mon Sep 17 00:00:00 2001 From: Mike Kaganski Date: Tue, 19 Nov 2024 11:38:44 +0500 Subject: [PATCH] Implement remote multimedia insertion support Similar to the existing "Insert Image", this turns multimedia insertion button into a menu, which is optionally expanded to include the remote item. It depends on explicit integration support (controlled by present "EnableInsertRemoteFile" file info response field equal to true), and requests the integration to show a "pick an asset" UI with given MIME types (by sending 'UI_InsertFile' request), and to call back with the Action_InsertMultimedia (also defined in another argument UI_InsertFile argument), that takes the selected URL. Signed-off-by: Mike Kaganski Change-Id: Ide6eefa6a55213f4ec0d1e47e35b5e4bf4a109be --- browser/src/control/Control.Menubar.js | 25 +++++++++++++++++++ .../src/control/Control.NotebookbarImpress.js | 4 +-- browser/src/control/Toolbar.js | 4 +-- .../src/control/jsdialog/Definitions.Menu.ts | 5 ++++ browser/src/docdispatcher.ts | 25 +++++++++++++++++++ browser/src/map/handler/Map.FileInserter.js | 12 ++++----- browser/src/map/handler/Map.WOPI.js | 22 +++++++++++++--- kit/ChildSession.cpp | 7 +++--- wsd/DocumentBroker.cpp | 1 + wsd/wopi/WopiStorage.cpp | 1 + wsd/wopi/WopiStorage.hpp | 3 +++ 11 files changed, 92 insertions(+), 17 deletions(-) diff --git a/browser/src/control/Control.Menubar.js b/browser/src/control/Control.Menubar.js index ac732c89029c..8a0ffe94ea8b 100644 --- a/browser/src/control/Control.Menubar.js +++ b/browser/src/control/Control.Menubar.js @@ -1992,6 +1992,28 @@ L.Control.Menubar = L.Control.extend({ this._map.fire('postMessage', {msgId: 'UI_InsertGraphic'}); } else if (id === 'insertmultimedia') { L.DomUtil.get('insertmultimedia').click(); + } else if (id === 'remotemultimedia') { + this._map.fire('postMessage', { + msgId: 'UI_InsertFile', args: { + callback: 'Action_InsertMultimedia', mimeTypeFilter: [ + 'video/MP2T', + 'video/mp4', + 'video/mpeg', + 'video/ogg', + 'video/quicktime', + 'video/webm', + 'video/x-matroska', + 'video/x-ms-wmv', + 'video/x-msvideo', + 'audio/aac', + 'audio/flac', + 'audio/mp4', + 'audio/mpeg', + 'audio/ogg', + 'audio/x-wav', + ] + } + }); } else if (id === 'selectbackground') { app.dispatcher.dispatch('selectbackground'); } else if (id === 'zoomin' && this._map.getZoom() < this._map.getMaxZoom()) { @@ -2243,6 +2265,9 @@ L.Control.Menubar = L.Control.extend({ if (menuItem.id === 'insertmultimedia' && this._map['wopi'].DisableInsertLocalImage) return false; + if (menuItem.id === 'remotemultimedia' && !this._map['wopi'].EnableInsertRemoteFile) + return false; + if (menuItem.id && menuItem.id.startsWith('fullscreen-presentation') && this._map['wopi'].HideExportOption) return false; diff --git a/browser/src/control/Control.NotebookbarImpress.js b/browser/src/control/Control.NotebookbarImpress.js index 12063c699ec5..ae45132c60c5 100644 --- a/browser/src/control/Control.NotebookbarImpress.js +++ b/browser/src/control/Control.NotebookbarImpress.js @@ -1214,8 +1214,8 @@ L.Control.NotebookbarImpress = L.Control.NotebookbarWriter.extend({ 'accessibility': { focusBack: true, combination: 'IG', de: null } }, { - 'id': 'insert-insert-multimedia', - 'type': 'bigcustomtoolitem', + 'id': 'insert-insert-multimedia:InsertMultimediaMenu', + 'type': 'menubutton', 'text': _UNO('.uno:InsertAVMedia'), 'command': 'insertmultimedia', 'accessibility': { focusBack: true, combination: 'MM', de: null }, // IM was already taken, so 'MM' for MultiMedia diff --git a/browser/src/control/Toolbar.js b/browser/src/control/Toolbar.js index 22fb98f7fe3d..3e43db46752f 100644 --- a/browser/src/control/Toolbar.js +++ b/browser/src/control/Toolbar.js @@ -439,8 +439,8 @@ L.Map.include({ this.fire('insertmultimedia', {file: file}); }, - insertURL: function (url) { - this.fire('inserturl', {url: url}); + insertURL: function (url, urltype) { + this.fire('inserturl', {url: url, urltype: urltype}); }, selectBackground: function (file) { diff --git a/browser/src/control/jsdialog/Definitions.Menu.ts b/browser/src/control/jsdialog/Definitions.Menu.ts index 67ce7412a170..f1b6d84d3d60 100644 --- a/browser/src/control/jsdialog/Definitions.Menu.ts +++ b/browser/src/control/jsdialog/Definitions.Menu.ts @@ -260,6 +260,11 @@ menuDefinitions.set('InsertImageMenu', [ // remote entry added in Map.WOPI ] as Array); +menuDefinitions.set('InsertMultimediaMenu', [ + { action: 'insertmultimedia', text: _('Insert Local Multimedia') }, + // remote entry added in Map.WOPI +] as Array); + menuDefinitions.set('CharSpacingMenu', [ { id: 'space1', text: _('Very Tight'), uno: 'Spacing?Spacing:short=-60' }, { id: 'space1', text: _('Tight'), uno: 'Spacing?Spacing:short=-30' }, diff --git a/browser/src/docdispatcher.ts b/browser/src/docdispatcher.ts index 51aff643478c..08356910c89b 100644 --- a/browser/src/docdispatcher.ts +++ b/browser/src/docdispatcher.ts @@ -119,6 +119,31 @@ class Dispatcher { this.actionsMap['insertmultimedia'] = function () { L.DomUtil.get('insertmultimedia').click(); }; + this.actionsMap['remotemultimedia'] = function () { + app.map.fire('postMessage', { + msgId: 'UI_InsertFile', + args: { + callback: 'Action_InsertMultimedia', + mimeTypeFilter: [ + 'video/MP2T', + 'video/mp4', + 'video/mpeg', + 'video/ogg', + 'video/quicktime', + 'video/webm', + 'video/x-matroska', + 'video/x-ms-wmv', + 'video/x-msvideo', + 'audio/aac', + 'audio/flac', + 'audio/mp4', + 'audio/mpeg', + 'audio/ogg', + 'audio/x-wav', + ], + }, + }); + }; this.actionsMap['charmapcontrol'] = function () { app.map.sendUnoCommand('.uno:InsertSymbol'); diff --git a/browser/src/map/handler/Map.FileInserter.js b/browser/src/map/handler/Map.FileInserter.js index f16eec39919b..de63f1e6b49a 100644 --- a/browser/src/map/handler/Map.FileInserter.js +++ b/browser/src/map/handler/Map.FileInserter.js @@ -65,10 +65,10 @@ L.Map.FileInserter = L.Handler.extend({ _onInsertURL: function (e) { if (!this._childId) { app.socket.sendMessage('getchildid'); - this._toInsertURL[Date.now()] = e.url; + this._toInsertURL[Date.now()] = e; } else { - this._sendURL(Date.now(), e.url); + this._sendURL(Date.now(), e); } }, @@ -202,17 +202,17 @@ L.Map.FileInserter = L.Handler.extend({ } }, - _sendURL: function (name, url) { + _sendURL: function (name, e) { var sectionName = L.CSections.ContentControl.name; var section; if (app.sectionContainer.doesSectionExist(sectionName)) { section = app.sectionContainer.getSectionWithName(sectionName); } - if (section && section.sectionProperties.picturePicker) { - app.socket.sendMessage('contentcontrolevent type=pictureurl' + ' name=' + encodeURIComponent(url)); + if (e.urltype == "graphicurl" && section && section.sectionProperties.picturePicker) { + app.socket.sendMessage('contentcontrolevent name=' + encodeURIComponent(e.url) + ' type=pictureurl'); } else { - app.socket.sendMessage('insertfile name=' + encodeURIComponent(url) + ' type=graphicurl'); + app.socket.sendMessage('insertfile name=' + encodeURIComponent(e.url) + ' type=' + e.urltype); } } }); diff --git a/browser/src/map/handler/Map.WOPI.js b/browser/src/map/handler/Map.WOPI.js index 4cd6ac1730b5..b83c959f504f 100644 --- a/browser/src/map/handler/Map.WOPI.js +++ b/browser/src/map/handler/Map.WOPI.js @@ -24,6 +24,7 @@ L.Map.WOPI = L.Handler.extend({ DownloadAsPostMessage: false, UserCanNotWriteRelative: true, EnableInsertRemoteImage: false, + EnableInsertRemoteFile: false, /* Separate, because requires explicit integration support */ DisableInsertLocalImage: false, EnableInsertRemoteLink: false, EnableShare: false, @@ -121,6 +122,7 @@ L.Map.WOPI = L.Handler.extend({ overridenFileInfo.DownloadAsPostMessage : !!wopiInfo['DownloadAsPostMessage']; this.UserCanNotWriteRelative = !!wopiInfo['UserCanNotWriteRelative']; this.EnableInsertRemoteImage = !!wopiInfo['EnableInsertRemoteImage']; + this.EnableInsertRemoteFile = !!wopiInfo['EnableInsertRemoteFile']; this.DisableInsertLocalImage = !!wopiInfo['DisableInsertLocalImage']; this.EnableRemoteLinkPicker = !!wopiInfo['EnableRemoteLinkPicker']; this.SupportsRename = !!wopiInfo['SupportsRename']; @@ -160,14 +162,21 @@ L.Map.WOPI = L.Handler.extend({ return; } - var menuEntries = JSDialog.MenuDefinitions.get('InsertImageMenu'); + var menuEntriesImage = JSDialog.MenuDefinitions.get('InsertImageMenu'); + var menuEntriesMultimedia = JSDialog.MenuDefinitions.get('InsertMultimediaMenu'); if (this.DisableInsertLocalImage) { - menuEntries = []; + menuEntriesImage = []; + menuEntriesMultimedia = []; } if (this.EnableInsertRemoteImage) { - menuEntries.push({action: 'remotegraphic', text: _UNO('.uno:InsertGraphic', '', true)}); + menuEntriesImage.push({action: 'remotegraphic', text: _UNO('.uno:InsertGraphic', '', true)}); + } + + if (this.EnableInsertRemoteFile) { + /* Separate, because needs explicit integration support */ + menuEntriesMultimedia.push({action: 'remotemultimedia', text: _UNO('.uno:InsertAVMedia', '', true)}); } this._insertImageMenuSetupDone = true; @@ -538,7 +547,12 @@ L.Map.WOPI = L.Handler.extend({ } else if (msg.MessageId == 'Action_InsertGraphic') { if (msg.Values) { - this._map.insertURL(msg.Values.url); + this._map.insertURL(msg.Values.url, "graphicurl"); + } + } + else if (msg.MessageId == 'Action_InsertMultimedia') { + if (msg.Values) { + this._map.insertURL(msg.Values.url, "multimediaurl"); } } else if (msg.MessageId == 'Action_InsertLink') { diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp index 5e5b0cea84bf..6fa94f469b31 100644 --- a/kit/ChildSession.cpp +++ b/kit/ChildSession.cpp @@ -1670,7 +1670,8 @@ bool ChildSession::insertFile(const StringVector& tokens) if (type == "graphic" || type == "graphicurl" || type == "selectbackground" || - type == "multimedia") + type == "multimedia" || + type == "multimediaurl" ) { std::string url; @@ -1687,7 +1688,7 @@ bool ChildSession::insertFile(const StringVector& tokens) } url = "file://" + jailDoc + "insertfile/" + name; } - else if (type == "graphicurl") + else if (type == "graphicurl" || type == "multimediaurl") { URI::decode(name, url); if (!Util::toLower(url).starts_with("http")) @@ -1714,7 +1715,7 @@ bool ChildSession::insertFile(const StringVector& tokens) std::string command; std::string arguments; - if (type == "multimedia") { + if (type == "multimedia" || type == "multimediaurl") { command = ".uno:InsertAVMedia"; arguments = "{" "\"URL\":{" diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp index 960808bf75ca..be10e0b8afd2 100644 --- a/wsd/DocumentBroker.cpp +++ b/wsd/DocumentBroker.cpp @@ -1379,6 +1379,7 @@ DocumentBroker::updateSessionWithWopiInfo(const std::shared_ptr& wopiInfo->set("DownloadAsPostMessage", wopiFileInfo->getDownloadAsPostMessage()); wopiInfo->set("UserCanNotWriteRelative", wopiFileInfo->getUserCanNotWriteRelative()); wopiInfo->set("EnableInsertRemoteImage", wopiFileInfo->getEnableInsertRemoteImage()); + wopiInfo->set("EnableInsertRemoteFile", wopiFileInfo->getEnableInsertRemoteFile()); wopiInfo->set("DisableInsertLocalImage", wopiFileInfo->getDisableInsertLocalImage()); wopiInfo->set("EnableRemoteLinkPicker", wopiFileInfo->getEnableRemoteLinkPicker()); wopiInfo->set("EnableShare", wopiFileInfo->getEnableShare()); diff --git a/wsd/wopi/WopiStorage.cpp b/wsd/wopi/WopiStorage.cpp index b7edb437b2d7..61195383c60f 100644 --- a/wsd/wopi/WopiStorage.cpp +++ b/wsd/wopi/WopiStorage.cpp @@ -250,6 +250,7 @@ WopiStorage::WOPIFileInfo::WOPIFileInfo(const FileInfo& fileInfo, Poco::JSON::Ob JsonUtil::findJSONValue(object, "DownloadAsPostMessage", _downloadAsPostMessage); JsonUtil::findJSONValue(object, "UserCanNotWriteRelative", _userCanNotWriteRelative); JsonUtil::findJSONValue(object, "EnableInsertRemoteImage", _enableInsertRemoteImage); + JsonUtil::findJSONValue(object, "EnableInsertRemoteFile", _enableInsertRemoteFile); JsonUtil::findJSONValue(object, "DisableInsertLocalImage", _disableInsertLocalImage); JsonUtil::findJSONValue(object, "EnableRemoteLinkPicker", _enableRemoteLinkPicker); JsonUtil::findJSONValue(object, "EnableShare", _enableShare); diff --git a/wsd/wopi/WopiStorage.hpp b/wsd/wopi/WopiStorage.hpp index 4d1f416ad4db..1e646b567794 100644 --- a/wsd/wopi/WopiStorage.hpp +++ b/wsd/wopi/WopiStorage.hpp @@ -76,6 +76,7 @@ class WopiStorage : public StorageBase bool getDownloadAsPostMessage() const { return _downloadAsPostMessage; } bool getUserCanNotWriteRelative() const { return _userCanNotWriteRelative; } bool getEnableInsertRemoteImage() const { return _enableInsertRemoteImage; } + bool getEnableInsertRemoteFile() const { return _enableInsertRemoteFile; } bool getDisableInsertLocalImage() const { return _disableInsertLocalImage; } bool getEnableRemoteLinkPicker() const { return _enableRemoteLinkPicker; } bool getEnableShare() const { return _enableShare; } @@ -151,6 +152,8 @@ class WopiStorage : public StorageBase bool _userCanNotWriteRelative = true; /// If set to true, users can access the insert remote image functionality bool _enableInsertRemoteImage = false; + /// If set to true, users can access the insert remote multimedia functionality + bool _enableInsertRemoteFile = false; /// If set to true, users can't insert an image from the local machine bool _disableInsertLocalImage = false; /// If set to true, users can access the remote link picker functionality