From a3d96a0b67b11792d9a2f2bcbdb9b7d129acc517 Mon Sep 17 00:00:00 2001 From: Elizabeth Danzberger Date: Mon, 9 Dec 2024 11:39:54 -0500 Subject: [PATCH] feat: assistant button This is needed as we are implementing a new feature in Nextcloud which integrates the Nextcloud AI Assistant. It will only be available if the required wopi attribute is passed in CheckFileInfo, which currently is only provided by Nextcloud. Signed-off-by: Elizabeth Danzberger Change-Id: Idfbc00f46b400413053b6068b327014b5ddd7a35 --- browser/src/control/Control.JSDialogBuilder.js | 1 + browser/src/control/Control.Menubar.js | 12 ++++++++++++ browser/src/control/Control.NotebookbarCalc.js | 8 ++++++++ browser/src/control/Control.NotebookbarDraw.js | 8 ++++++++ browser/src/control/Control.NotebookbarImpress.js | 8 ++++++++ browser/src/control/Control.NotebookbarWriter.js | 8 ++++++++ browser/src/docdispatcher.ts | 3 +++ browser/src/map/handler/Map.WOPI.js | 2 ++ wsd/DocumentBroker.cpp | 1 + wsd/wopi/WopiStorage.cpp | 1 + wsd/wopi/WopiStorage.hpp | 3 +++ 11 files changed, 55 insertions(+) diff --git a/browser/src/control/Control.JSDialogBuilder.js b/browser/src/control/Control.JSDialogBuilder.js index acfde2b23d51b..bee64a7731358 100644 --- a/browser/src/control/Control.JSDialogBuilder.js +++ b/browser/src/control/Control.JSDialogBuilder.js @@ -2053,6 +2053,7 @@ L.Control.JSDialogBuilder = L.Control.extend({ 'scalignmentpropertypanel': 'aligntop', 'hyperlinkdialog': 'inserthyperlink', 'remotelink': 'inserthyperlink', + 'remoteaicontent': 'sdrespageobjs', 'openhyperlinkoncursor': 'inserthyperlink', 'pageformatdialog': 'pagedialog', 'backgroundcolor': 'fillcolor', diff --git a/browser/src/control/Control.Menubar.js b/browser/src/control/Control.Menubar.js index c9936d79a7806..0238e401b1398 100644 --- a/browser/src/control/Control.Menubar.js +++ b/browser/src/control/Control.Menubar.js @@ -190,6 +190,7 @@ L.Control.Menubar = L.Control.extend({ {type: 'separator'}, {name: _UNO('.uno:HyperlinkDialog'), id: 'inserthyperlink', type: 'action'}, {name: _('Smart Picker'), id: 'remotelink', type: 'action'}, + {name: _('AI Assistant'), id: 'remoteaicontent', type: 'action'}, {type: 'separator'}, {uno: '.uno:InsertQrCode'}, {uno: '.uno:InsertSymbol'}, @@ -484,6 +485,7 @@ L.Control.Menubar = L.Control.extend({ {type: 'separator'}, {name: _UNO('.uno:HyperlinkDialog'), id: 'inserthyperlink', type: 'action'}, {name: _('Smart Picker'), id: 'remotelink', type: 'action'}, + {name: _('AI Assistant'), id: 'remoteaicontent', type: 'action'}, {type: 'separator'}, {uno: '.uno:InsertSymbol'}, {type: 'separator'}, @@ -631,6 +633,7 @@ L.Control.Menubar = L.Control.extend({ {type: 'separator'}, {name: _UNO('.uno:HyperlinkDialog'), id: 'inserthyperlink', type: 'action'}, {name: _('Smart Picker'), id: 'remotelink', type: 'action'}, + {name: _('AI Assistant'), id: 'remoteaicontent', type: 'action'}, {type: 'separator'}, {uno: '.uno:InsertSymbol'}, {type: 'separator'}, @@ -785,6 +788,7 @@ L.Control.Menubar = L.Control.extend({ {type: 'separator'}, {name: _UNO('.uno:HyperlinkDialog'), uno: '.uno:HyperlinkDialog'}, {name: _('Smart Picker'), id: 'remotelink', type: 'action'}, + {name: _('AI Assistant'), id: 'remoteaicontent', type: 'action'}, {uno: '.uno:InsertSymbol'}, {type: 'separator'}, {name: _UNO('.uno:InsertField', 'text'), type: 'menu', menu: [ @@ -1929,6 +1933,13 @@ L.Control.Menubar = L.Control.extend({ else $(aItem).hide(); } + + if (id === 'remoteaicontent') { + if (self._map['wopi'].EnableRemoteAIContent) + $(aItem).show(); + else + $(aItem).hide(); + } }); }, @@ -1991,6 +2002,7 @@ L.Control.Menubar = L.Control.extend({ || id.startsWith('zotero') || id === 'deletepage' || id === 'remotelink' + || id === 'remoteaicontent' || id === 'toggledarktheme' || id === 'invertbackground' || id === 'home-search' diff --git a/browser/src/control/Control.NotebookbarCalc.js b/browser/src/control/Control.NotebookbarCalc.js index a479eb2c50be8..538bb8cadefc5 100644 --- a/browser/src/control/Control.NotebookbarCalc.js +++ b/browser/src/control/Control.NotebookbarCalc.js @@ -1386,6 +1386,14 @@ L.Control.NotebookbarCalc = L.Control.NotebookbarWriter.extend({ 'command': 'remotelink', 'accessibility': { focusBack: true, combination: 'LR', de: null } } : {}, + (this._map['wopi'].EnableRemoteAIContent) ? { + 'id': 'insert-insert-remote-ai-content', + 'class': 'unoremoteaicontent', + 'type': 'bigcustomtoolitem', + 'text': _('Assistant'), + 'command': 'remoteaicontent', + 'accessibility': { focusBack: true, combination: 'RL', de: null } + } : {}, { 'type': 'container', 'children': [ diff --git a/browser/src/control/Control.NotebookbarDraw.js b/browser/src/control/Control.NotebookbarDraw.js index 28ef750d2ac58..4076d46780bf9 100644 --- a/browser/src/control/Control.NotebookbarDraw.js +++ b/browser/src/control/Control.NotebookbarDraw.js @@ -1278,6 +1278,14 @@ L.Control.NotebookbarDraw = L.Control.NotebookbarImpress.extend({ 'command': 'remotelink', 'accessibility': { focusBack: true, combination: 'RL', de: null } } : {}, + (this._map['wopi'].EnableRemoteAIContent) ? { + 'id': 'insert-insert-remote-ai-content', + 'class': 'unoremoteaicontent', + 'type': 'bigcustomtoolitem', + 'text': _('Assistant'), + 'command': 'remoteaicontent', + 'accessibility': { focusBack: true, combination: 'RL', de: null } + } : {}, { 'type': 'container', 'children': [ diff --git a/browser/src/control/Control.NotebookbarImpress.js b/browser/src/control/Control.NotebookbarImpress.js index 4244e1e6aca3b..9bd3820992c5d 100644 --- a/browser/src/control/Control.NotebookbarImpress.js +++ b/browser/src/control/Control.NotebookbarImpress.js @@ -1290,6 +1290,14 @@ L.Control.NotebookbarImpress = L.Control.NotebookbarWriter.extend({ 'command': 'hyperlinkdialog', 'accessibility': { focusBack: true, combination: 'IL', de: null } }, + (this._map['wopi'].EnableRemoteAIContent) ? { + 'id': 'insert-insert-remote-ai-content', + 'class': 'unoremoteaicontent', + 'type': 'bigcustomtoolitem', + 'text': _('Assistant'), + 'command': 'remoteaicontent', + 'accessibility': { focusBack: true, combination: 'RL', de: null } + } : {}, { 'id': 'insert-insert-annotation', 'type': 'bigtoolitem', diff --git a/browser/src/control/Control.NotebookbarWriter.js b/browser/src/control/Control.NotebookbarWriter.js index beec76b8c87fd..64626384843e6 100644 --- a/browser/src/control/Control.NotebookbarWriter.js +++ b/browser/src/control/Control.NotebookbarWriter.js @@ -1136,6 +1136,14 @@ L.Control.NotebookbarWriter = L.Control.Notebookbar.extend({ 'command': 'hyperlinkdialog', 'accessibility': { focusBack: false, combination: 'ZL', de: '8' } }, + (this._map['wopi'].EnableRemoteAIContent) ? { + 'id': 'insert-insert-remote-ai-content', + 'class': 'unoremoteaicontent', + 'type': 'bigcustomtoolitem', + 'text': _('Assistant'), + 'command': 'remoteaicontent', + 'accessibility': { focusBack: true, combination: 'RL', de: null } + } : {}, { 'id': 'insert-insert-annotation', 'type': 'bigtoolitem', diff --git a/browser/src/docdispatcher.ts b/browser/src/docdispatcher.ts index f45c5f6f22dc0..dd8e6e606acca 100644 --- a/browser/src/docdispatcher.ts +++ b/browser/src/docdispatcher.ts @@ -91,6 +91,9 @@ class Dispatcher { this.actionsMap['remotelink'] = function () { app.map.fire('postMessage', { msgId: 'UI_PickLink' }); }; + this.actionsMap['remoteaicontent'] = function () { + app.map.fire('postMessage', { msgId: 'UI_InsertAIContent' }); + }; // TODO: deduplicate this.actionsMap['hyperlinkdialog'] = function () { app.map.showHyperlinkDialog(); diff --git a/browser/src/map/handler/Map.WOPI.js b/browser/src/map/handler/Map.WOPI.js index 469f4e7f1d271..d3fe6c865d7e8 100644 --- a/browser/src/map/handler/Map.WOPI.js +++ b/browser/src/map/handler/Map.WOPI.js @@ -27,6 +27,7 @@ L.Map.WOPI = L.Handler.extend({ EnableInsertRemoteFile: false, /* Separate, because requires explicit integration support */ DisableInsertLocalImage: false, EnableInsertRemoteLink: false, + EnableRemoteAIContent: false, EnableShare: false, HideUserList: null, CallPythonScriptSource: null, @@ -125,6 +126,7 @@ L.Map.WOPI = L.Handler.extend({ this.EnableInsertRemoteFile = !!wopiInfo['EnableInsertRemoteFile']; this.DisableInsertLocalImage = !!wopiInfo['DisableInsertLocalImage']; this.EnableRemoteLinkPicker = !!wopiInfo['EnableRemoteLinkPicker']; + this.EnableRemoteAIContent = !!wopiInfo['EnableRemoteAIContent']; this.SupportsRename = !!wopiInfo['SupportsRename']; this.UserCanRename = !!wopiInfo['UserCanRename']; this.EnableShare = !!wopiInfo['EnableShare']; diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp index 61e3aa35eca64..735b6c8a6f38f 100644 --- a/wsd/DocumentBroker.cpp +++ b/wsd/DocumentBroker.cpp @@ -1388,6 +1388,7 @@ DocumentBroker::updateSessionWithWopiInfo(const std::shared_ptr& wopiInfo->set("EnableInsertRemoteFile", wopiFileInfo->getEnableInsertRemoteFile()); wopiInfo->set("DisableInsertLocalImage", wopiFileInfo->getDisableInsertLocalImage()); wopiInfo->set("EnableRemoteLinkPicker", wopiFileInfo->getEnableRemoteLinkPicker()); + wopiInfo->set("EnableRemoteAIContent", wopiFileInfo->getEnableRemoteAIContent()); wopiInfo->set("EnableShare", wopiFileInfo->getEnableShare()); wopiInfo->set("HideUserList", wopiFileInfo->getHideUserList()); wopiInfo->set("SupportsRename", wopiFileInfo->getSupportsRename()); diff --git a/wsd/wopi/WopiStorage.cpp b/wsd/wopi/WopiStorage.cpp index 5ac9b2d133552..d62761833df8b 100644 --- a/wsd/wopi/WopiStorage.cpp +++ b/wsd/wopi/WopiStorage.cpp @@ -255,6 +255,7 @@ WopiStorage::WOPIFileInfo::WOPIFileInfo(const FileInfo& fileInfo, Poco::JSON::Ob JsonUtil::findJSONValue(object, "EnableInsertRemoteFile", _enableInsertRemoteFile); JsonUtil::findJSONValue(object, "DisableInsertLocalImage", _disableInsertLocalImage); JsonUtil::findJSONValue(object, "EnableRemoteLinkPicker", _enableRemoteLinkPicker); + JsonUtil::findJSONValue(object, "EnableRemoteAIContent", _enableRemoteAIContent); JsonUtil::findJSONValue(object, "EnableShare", _enableShare); JsonUtil::findJSONValue(object, "HideUserList", _hideUserList); JsonUtil::findJSONValue(object, "SupportsLocks", _supportsLocks); diff --git a/wsd/wopi/WopiStorage.hpp b/wsd/wopi/WopiStorage.hpp index 467b79d593f54..602fb11359382 100644 --- a/wsd/wopi/WopiStorage.hpp +++ b/wsd/wopi/WopiStorage.hpp @@ -80,6 +80,7 @@ class WopiStorage : public StorageBase bool getEnableInsertRemoteFile() const { return _enableInsertRemoteFile; } bool getDisableInsertLocalImage() const { return _disableInsertLocalImage; } bool getEnableRemoteLinkPicker() const { return _enableRemoteLinkPicker; } + bool getEnableRemoteAIContent() const { return _enableRemoteAIContent; } bool getEnableShare() const { return _enableShare; } bool getSupportsRename() const { return _supportsRename; } bool getSupportsLocks() const { return _supportsLocks; } @@ -161,6 +162,8 @@ class WopiStorage : public StorageBase bool _disableInsertLocalImage = false; /// If set to true, users can access the remote link picker functionality bool _enableRemoteLinkPicker = false; + /// If set to true, users can insert remote AI-generated content + bool _enableRemoteAIContent = false; /// If set to true, users can access the file share functionality bool _enableShare = false; /// If WOPI host supports locking