summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Veyssier <eneiluj@posteo.net>2021-08-23 22:31:03 +0200
committerJoas Schilling <coding@schilljs.com>2022-05-02 09:26:20 +0200
commitafc005b71c413de170f5b83930bf64fc625bb8f2 (patch)
treec1010160929d2b02072045184af6a6e834250bce
parente80d71e83165c8d39e9b5959c373a26eab740e2e (diff)
register share location action in Maps app
Signed-off-by: Julien Veyssier <eneiluj@posteo.net>
-rw-r--r--lib/AppInfo/Application.php2
-rw-r--r--lib/Maps/MapsPluginLoader.php54
-rw-r--r--src/maps.js111
-rw-r--r--webpack.js1
4 files changed, 168 insertions, 0 deletions
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php
index c52c766b4..67446c369 100644
--- a/lib/AppInfo/Application.php
+++ b/lib/AppInfo/Application.php
@@ -58,6 +58,7 @@ use OCA\Talk\Listener\GroupMembershipListener;
use OCA\Talk\Listener\RestrictStartingCalls as RestrictStartingCallsListener;
use OCA\Talk\Listener\UserDeletedListener;
use OCA\Talk\Listener\UserDisplayNameListener;
+use OCA\Talk\Maps\MapsPluginLoader;
use OCA\Talk\Middleware\CanUseTalkMiddleware;
use OCA\Talk\Middleware\InjectionMiddleware;
use OCA\Talk\Notification\Listener as NotificationListener;
@@ -124,6 +125,7 @@ class Application extends App implements IBootstrap {
$context->registerEventListener(\OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent::class, UnifiedSearchCSSLoader::class);
$context->registerEventListener(UserChangedEvent::class, UserDisplayNameListener::class);
$context->registerEventListener(\OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent::class, DeckPluginLoader::class);
+ $context->registerEventListener(\OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent::class, MapsPluginLoader::class);
$context->registerEventListener(RegisterOperationsEvent::class, RegisterOperationsListener::class);
$context->registerEventListener(AttendeesAddedEvent::class, SystemMessageListener::class);
$context->registerEventListener(AttendeesRemovedEvent::class, SystemMessageListener::class);
diff --git a/lib/Maps/MapsPluginLoader.php b/lib/Maps/MapsPluginLoader.php
new file mode 100644
index 000000000..2689148f8
--- /dev/null
+++ b/lib/Maps/MapsPluginLoader.php
@@ -0,0 +1,54 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2021 Julien Veyssier <julien@nextcloud.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Talk\Maps;
+
+use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\IRequest;
+use OCP\Util;
+
+class MapsPluginLoader implements IEventListener {
+ /** @var IRequest */
+ private $request;
+
+ public function __construct(IRequest $request) {
+ $this->request = $request;
+ }
+
+ public function handle(Event $event): void {
+ if (!($event instanceof BeforeTemplateRenderedEvent)) {
+ return;
+ }
+
+ if (!$event->isLoggedIn()) {
+ return;
+ }
+
+ if (strpos($this->request->getPathInfo(), '/apps/maps') === 0) {
+ Util::addScript('spreed', 'talk-collections');
+ Util::addScript('spreed', 'talk-maps');
+ }
+ }
+}
diff --git a/src/maps.js b/src/maps.js
new file mode 100644
index 000000000..16f902cda
--- /dev/null
+++ b/src/maps.js
@@ -0,0 +1,111 @@
+/*
+ * @copyright Copyright (c) 2021 Julien Veyssier <julien@nextcloud.com>
+ *
+ * @author Julien Veyssier <julien@nextcloud.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import Vue from 'vue'
+import { generateFilePath, generateUrl } from '@nextcloud/router'
+import { getRequestToken } from '@nextcloud/auth'
+import { translate, translatePlural } from '@nextcloud/l10n'
+import { showSuccess, showError } from '@nextcloud/dialogs'
+import { postRichObjectToConversation } from './services/messagesService'
+import RoomSelector from './views/RoomSelector'
+
+(function(OC, OCA, t, n) {
+ async function postLocationToRoom(location, token) {
+ try {
+ const response = await postRichObjectToConversation(token, {
+ objectType: 'geo-location',
+ objectId: location.id,
+ metaData: JSON.stringify(location),
+ })
+ const messageId = response.data.ocs.data.id
+ const targetUrl = generateUrl('/call/{token}#message_{messageId}', { token, messageId })
+ showSuccess(t('spreed', 'Location has been posted to the selected <a href="{link}">conversation</a>', {
+ link: targetUrl,
+ }), {
+ isHTML: true,
+ })
+ } catch (exception) {
+ console.error('Error posting location to conversation', exception, exception.response?.status)
+ if (exception.response?.status === 403) {
+ showError(t('spreed', 'No permission to post messages in this conversation'))
+ } else {
+ showError(t('spreed', 'An error occurred while posting location to conversation'))
+ }
+ }
+ }
+
+ function init() {
+ if (!OCA.Maps?.registerMapsAction) {
+ return
+ }
+
+ OCA.Maps.registerMapsAction({
+ label: t('spreed', 'Share to a conversation'),
+ icon: 'icon-talk',
+ callback: (location) => {
+ const container = document.createElement('div')
+ container.id = 'spreed-post-location-to-room-select'
+ const body = document.getElementById('body-user')
+ body.appendChild(container)
+
+ const ComponentVM = Vue.extend(RoomSelector)
+ const vm = new ComponentVM({
+ el: container,
+ propsData: {
+ dialogTitle: t('spreed', 'Share to conversation'),
+ showPostableOnly: true,
+ },
+ })
+
+ vm.$root.$on('close', () => {
+ vm.$el.remove()
+ vm.$destroy()
+ })
+ vm.$root.$on('select', (token) => {
+ vm.$el.remove()
+ vm.$destroy()
+
+ postLocationToRoom(location, token)
+ })
+ },
+ })
+ }
+
+ // CSP config for webpack dynamic chunk loading
+ // eslint-disable-next-line
+ __webpack_nonce__ = btoa(getRequestToken())
+
+ // Correct the root of the app for chunk loading
+ // OC.linkTo matches the apps folders
+ // OC.generateUrl ensure the index.php (or not)
+ // We do not want the index.php since we're loading files
+ // eslint-disable-next-line
+ __webpack_public_path__ = generateFilePath('spreed', '', 'js/')
+
+ Vue.prototype.t = translate
+ Vue.prototype.n = translatePlural
+ Vue.prototype.OC = OC
+ Vue.prototype.OCA = OCA
+
+ document.addEventListener('DOMContentLoaded', init)
+
+})(window.OC, window.OCA, t, n)
diff --git a/webpack.js b/webpack.js
index cd0189af2..f8f8015e3 100644
--- a/webpack.js
+++ b/webpack.js
@@ -17,6 +17,7 @@ webpackConfig.entry = {
flow: path.join(__dirname, 'src', 'flow.js'),
dashboard: path.join(__dirname, 'src', 'dashboard.js'),
deck: path.join(__dirname, 'src', 'deck.js'),
+ maps: path.join(__dirname, 'src', 'maps.js'),
}
webpackConfig.output.assetModuleFilename = '[name][ext]?v=[contenthash]'