From 30c2371b9af19e90fe0b7c62e4da77ae8c073731 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Fri, 21 Oct 2022 12:17:49 +0200 Subject: [PATCH] Attach Nextcloud files to mail #569 --- plugins/nextcloud/index.php | 37 ++++++++++++++++++++--- plugins/nextcloud/js/composer.js | 51 +++++++++++++++++++++++++++++++ plugins/nextcloud/js/message.js | 1 + plugins/nextcloud/js/webdav.js | 52 +++++++++++++++++++++----------- plugins/nextcloud/langs/en.ini | 1 + 5 files changed, 119 insertions(+), 23 deletions(-) create mode 100644 plugins/nextcloud/js/composer.js diff --git a/plugins/nextcloud/index.php b/plugins/nextcloud/index.php index f96d98cd1..4d44c51a1 100644 --- a/plugins/nextcloud/index.php +++ b/plugins/nextcloud/index.php @@ -4,7 +4,7 @@ class NextcloudPlugin extends \RainLoop\Plugins\AbstractPlugin { const NAME = 'Nextcloud', - VERSION = '2.4', + VERSION = '2.6', RELEASE = '2022-10-19', CATEGORY = 'Integrations', DESCRIPTION = 'Integrate with Nextcloud v20+', @@ -18,10 +18,15 @@ class NextcloudPlugin extends \RainLoop\Plugins\AbstractPlugin $this->addHook('main.fabrica', 'MainFabrica'); $this->addHook('filter.app-data', 'FilterAppData'); - $this->addJs('js/message.js'); $this->addJs('js/webdav.js'); + + $this->addJs('js/message.js'); $this->addHook('json.attachments', 'DoAttachmentsActions'); $this->addJsonHook('NextcloudSaveMsg', 'NextcloudSaveMsg'); + $this->addJsonHook('NextcloudAttachFile', 'NextcloudAttachFile'); + + $this->addJs('js/composer.js'); + $this->addTemplate('templates/PopupsNextcloudFiles.html'); } } @@ -58,6 +63,30 @@ class NextcloudPlugin extends \RainLoop\Plugins\AbstractPlugin } */ + public function NextcloudAttachFile() : array + { + $aResult = [ + 'success' => false, + 'tempName' => '' + ]; + $sFile = $this->jsonParam('file', ''); + $oFiles = \OCP\Files::getStorage('files'); + if ($oFiles && $oFiles->is_file($sFile) && $fp = $oFiles->fopen($sFile, 'rb')) { + $oActions = \RainLoop\Api::Actions(); + $oAccount = $oActions->getAccountFromToken(); + if ($oAccount) { + $sSavedName = 'nextcloud-file-' . \sha1($sFile . \microtime()); + if (!$oActions->FilesProvider()->PutFile($oAccount, $sSavedName, $fp)) { + $aResult['error'] = 'failed'; + } else { + $aResult['tempName'] = $sSavedName; + $aResult['success'] = true; + } + } + } + return $this->jsonResponse(__FUNCTION__, $aResult); + } + public function NextcloudSaveMsg() : array { $sSaveFolder = \ltrim($this->jsonParam('folder', ''), '/'); @@ -106,7 +135,7 @@ class NextcloudPlugin extends \RainLoop\Plugins\AbstractPlugin $oFiles = \OCP\Files::getStorage('files'); if ($oFiles && \method_exists($oFiles, 'file_put_contents')) { $sSaveFolder = \ltrim($this->jsonParam('NcFolder', ''), '/'); - $sSaveFolder = $sSaveFolder ?: $this->Config()->Get('plugin', 'save_folder', '') ?: 'Attachments'; + $sSaveFolder = $sSaveFolder ?: 'Attachments'; $oFiles->is_dir($sSaveFolder) || $oFiles->mkdir($sSaveFolder); $data->result = true; foreach ($data->items as $aItem) { @@ -192,8 +221,6 @@ class NextcloudPlugin extends \RainLoop\Plugins\AbstractPlugin protected function configMapping() : array { return array( - \RainLoop\Plugins\Property::NewInstance('save_folder')->SetLabel('Save Folder') - ->SetDefaultValue('Attachments'), \RainLoop\Plugins\Property::NewInstance('suggestions')->SetLabel('Suggestions') ->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL) ->SetDefaultValue(true) diff --git a/plugins/nextcloud/js/composer.js b/plugins/nextcloud/js/composer.js new file mode 100644 index 000000000..b7f758c98 --- /dev/null +++ b/plugins/nextcloud/js/composer.js @@ -0,0 +1,51 @@ +(rl => { +// if (rl.settings.get('Nextcloud')) + + addEventListener('rl-view-model.create', e => { + if ('PopupsCompose' === e.detail.viewModelTemplateID) { + let view = e.detail; + view.nextcloudAttach = () => { + rl.ncFiles.selectFiles().then(files => { + files.forEach(file => { + let id = Jua?.randomId() || file.etag, + attachment = view.addAttachmentHelper( + id.etag, + file.name.replace(/^.*\/([^/]+)$/, '$1'), + file.size + ); + attachment + .waiting(false) + .uploading(true) + .complete(false); + + rl.pluginRemoteRequest( + (iError, data) => { + attachment + .uploading(false) + .complete(true); + if (iError) { + attachment.error(data?.Result?.error || 'failed'); + } else { + attachment.tempName(data.Result.tempName); + } + }, + 'NextcloudAttachFile', + { + 'file': file.name + } + ); + + }); + }); + }; + } + }); + + let template = document.getElementById('PopupsCompose'); + const uploadBtn = template.content.querySelector('#composeUploadButton'); + if (uploadBtn) { + uploadBtn.after(Element.fromHTML('◦◯◦')); + } + +})(window.rl); diff --git a/plugins/nextcloud/js/message.js b/plugins/nextcloud/js/message.js index 858a71a88..bc7353897 100644 --- a/plugins/nextcloud/js/message.js +++ b/plugins/nextcloud/js/message.js @@ -1,4 +1,5 @@ (rl => { +// if (rl.settings.get('Nextcloud')) addEventListener('rl-view-model.create', e => { if ('MailMessageView' === e.detail.viewModelTemplateID) { diff --git a/plugins/nextcloud/js/webdav.js b/plugins/nextcloud/js/webdav.js index 70fa81fe3..eba7b7410 100644 --- a/plugins/nextcloud/js/webdav.js +++ b/plugins/nextcloud/js/webdav.js @@ -109,28 +109,26 @@ { if (items.length) { items.forEach(item => { - if (item.isFile) { - if (view.files()) { - // TODO show files - } - } else { + if (!item.isFile) { let li = document.createElement('li'), details = document.createElement('details'), summary = document.createElement('summary'), - ul = document.createElement('ul'), - btn = document.createElement('button'); - btn.item_name = item.name; + ul = document.createElement('ul'); details.addEventListener('toggle', () => { - if (!ul.children.length) { - fetchFiles(propertyRequestBody, item.name).then(items => buildTree(view, ul, items, item.name)); - } + ul.children.length + || fetchFiles(propertyRequestBody, item.name).then(items => buildTree(view, ul, items, item.name)); }); - summary.textContent = '📁 ' + item.name.replace(/^.*\/([^/]+)$/, '$1'); - btn.name = 'select'; - btn.textContent = 'select'; - btn.className = 'button-vue'; - btn.style.marginLeft = '1em'; - summary.append(btn); + summary.textContent = item.name.replace(/^.*\/([^/]+)$/, '$1'); + summary.dataset.icon = '📁'; + if (!view.files()) { + let btn = document.createElement('button'); + btn.item_name = item.name; + btn.name = 'select'; + btn.textContent = 'select'; + btn.className = 'button-vue'; + btn.style.marginLeft = '1em'; + summary.append(btn); + } details.append(summary); details.append(ul); // a.append('- ' + item.name.replace(/^\/+/, '')); @@ -138,6 +136,24 @@ parent.append(li); } }); + if (view.files()) { + items.forEach(item => { + if (item.isFile) { + // TODO show files + let li = document.createElement('li'), + btn = document.createElement('button'); + btn.item = item; + btn.name = 'select'; + btn.textContent = 'select'; + btn.className = 'button-vue'; + btn.style.marginLeft = '1em'; + li.textContent = item.name.replace(/^.*\/([^/]+)$/, '$1'); + li.dataset.icon = '🗎'; + li.append(btn); + parent.append(li); + } + }); + } } if (!view.files()) { let li = document.createElement('li'), @@ -168,7 +184,7 @@ let el = event.target; if (el.matches('button')) { if ('select' == el.name) { - this.select = el.item_name; + this.select = this.files() ? [el.item] : el.item_name; this.close(); } else if ('create' == el.name) { let name = el.input.value.replace(/[|\\?*<":>+[]\/&\s]/g, ''); diff --git a/plugins/nextcloud/langs/en.ini b/plugins/nextcloud/langs/en.ini index 9e79388da..4a5c783fd 100644 --- a/plugins/nextcloud/langs/en.ini +++ b/plugins/nextcloud/langs/en.ini @@ -3,3 +3,4 @@ SAVE_ATTACHMENTS = "Save in Nextcloud" SAVE_EML = "Save as .eml in Nextcloud" SELECT_FOLDER = "Select folder" SELECT_FILES = "Select file(s)" +ATTACH_FILES = "Attach Nextcloud files"