From a2f5f70e84500253204960e3988e091b24f2740a Mon Sep 17 00:00:00 2001 From: Richard Steinmetz Date: Thu, 17 Aug 2023 15:31:27 +0200 Subject: [PATCH] perf(dashboard): implement widget item api v2 Signed-off-by: Richard Steinmetz --- lib/Dashboard/TalkWidget.php | 62 ++++++++- src/dashboard.js | 56 -------- src/views/Dashboard.vue | 248 ----------------------------------- webpack.config.js | 1 - 4 files changed, 58 insertions(+), 309 deletions(-) delete mode 100644 src/dashboard.js delete mode 100644 src/views/Dashboard.vue diff --git a/lib/Dashboard/TalkWidget.php b/lib/Dashboard/TalkWidget.php index ccf366e1ffc..fb01eb6a51e 100644 --- a/lib/Dashboard/TalkWidget.php +++ b/lib/Dashboard/TalkWidget.php @@ -5,6 +5,7 @@ * @copyright Copyright (c) 2020 Julius Härtl * * @author Julius Härtl + * @author Richard Steinmetz * * @license GNU AGPL version 3 or any later version * @@ -40,8 +41,10 @@ use OCP\Dashboard\IConditionalWidget; use OCP\Dashboard\IIconWidget; use OCP\Dashboard\IOptionWidget; +use OCP\Dashboard\IReloadableWidget; use OCP\Dashboard\Model\WidgetButton; use OCP\Dashboard\Model\WidgetItem; +use OCP\Dashboard\Model\WidgetItems; use OCP\Dashboard\Model\WidgetOptions; use OCP\IL10N; use OCP\IURLGenerator; @@ -49,7 +52,7 @@ use OCP\IUserSession; use OCP\Util; -class TalkWidget implements IAPIWidget, IIconWidget, IButtonWidget, IOptionWidget, IConditionalWidget { +class TalkWidget implements IAPIWidget, IIconWidget, IButtonWidget, IOptionWidget, IConditionalWidget, IReloadableWidget { public function __construct( protected IUserSession $userSession, @@ -112,7 +115,7 @@ public function getWidgetButtons(string $userId): array { $buttons[] = new WidgetButton( WidgetButton::TYPE_MORE, $this->url->linkToRouteAbsolute('spreed.Page.index'), - $this->l10n->t('More unread mentions') + $this->l10n->t('More conversations') ); return $buttons; } @@ -135,8 +138,6 @@ public function getUrl(): ?string { * @inheritDoc */ public function load(): void { - Util::addStyle('spreed', 'icons'); - Util::addScript('spreed', 'talk-dashboard'); } public function getItems(string $userId, ?string $since = null, int $limit = 7): array { @@ -170,6 +171,52 @@ public function getItems(string $userId, ?string $since = null, int $limit = 7): return $result; } + /** + * @inheritDoc + */ + public function getItemsV2(string $userId, ?string $since = null, int $limit = 7): WidgetItems { + $allRooms = $this->manager->getRoomsForUser($userId, [], true); + + $rooms = []; + $mentions = []; + foreach ($allRooms as $room) { + if ($room->getObjectType() !== BreakoutRoom::PARENT_OBJECT_TYPE) { + $rooms[] = $room; + } + + $participant = $this->participantService->getParticipant($room, $userId); + $attendee = $participant->getAttendee(); + if ($room->getCallFlag() !== Participant::FLAG_DISCONNECTED + || $attendee->getLastMentionMessage() > $attendee->getLastReadMessage() + || ( + ($room->getType() === Room::TYPE_ONE_TO_ONE || $room->getType() === Room::TYPE_ONE_TO_ONE_FORMER) + && $room->getLastMessage() + && $room->getLastMessage()->getId() > $attendee->getLastReadMessage() + )) { + $mentions[] = $room; + } + } + + $roomsToReturn = $rooms; + if (!empty($mentions)) { + $roomsToReturn = $mentions; + } + + uasort($roomsToReturn, [$this, 'sortRooms']); + $roomsToReturn = array_slice($roomsToReturn, 0, $limit); + + $result = []; + foreach ($roomsToReturn as $room) { + $result[] = $this->prepareRoom($room, $userId); + } + + return new WidgetItems( + $result, + empty($result) ? $this->l10n->t('Say hi to your friends and colleagues!') : '', + empty($mentions) ? $this->l10n->t('No unread mentions') : '', + ); + } + protected function prepareRoom(Room $room, string $userId): WidgetItem { $participant = $this->participantService->getParticipant($room, $userId); $subtitle = ''; @@ -219,4 +266,11 @@ protected function sortRooms(Room $roomA, Room $roomB): int { return $roomA->getLastActivity() >= $roomB->getLastActivity() ? -1 : 1; } + + /** + * @inheritDoc + */ + public function getReloadInterval(): int { + return 30; + } } diff --git a/src/dashboard.js b/src/dashboard.js deleted file mode 100644 index 4407997bf30..00000000000 --- a/src/dashboard.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * @copyright Copyright (c) 2020 Julius Härtl - * - * @author Julius Härtl - * - * @license AGPL-3.0-or-later - * - * 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 . - * - */ - -import Vue from 'vue' - -import { getRequestToken } from '@nextcloud/auth' -import { translate, translatePlural } from '@nextcloud/l10n' -import { generateFilePath } from '@nextcloud/router' - -import Dashboard from './views/Dashboard.vue' - -// 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', function() { - - OCA.Dashboard.register('spreed', (el) => { - const View = Vue.extend(Dashboard) - new View({ - propsData: {}, - }).$mount(el) - }) - -}) diff --git a/src/views/Dashboard.vue b/src/views/Dashboard.vue deleted file mode 100644 index 7076d80e0e2..00000000000 --- a/src/views/Dashboard.vue +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - - diff --git a/webpack.config.js b/webpack.config.js index 970115584e2..bb54350af89 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -29,7 +29,6 @@ module.exports = mergeWithRules({ 'public-share-auth-sidebar': path.join(__dirname, 'src', 'mainPublicShareAuthSidebar.js'), 'public-share-sidebar': path.join(__dirname, 'src', 'mainPublicShareSidebar.js'), 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'), },