diff --git a/apps/comments/lib/Listener/LoadSidebarScripts.php b/apps/comments/lib/Listener/LoadSidebarScripts.php index a77cd4e0af376..39c81c03ad106 100644 --- a/apps/comments/lib/Listener/LoadSidebarScripts.php +++ b/apps/comments/lib/Listener/LoadSidebarScripts.php @@ -28,6 +28,8 @@ use OCA\Comments\AppInfo\Application; use OCA\Files\Event\LoadSidebar; +use OCP\App\IAppManager; +use OCP\AppFramework\Services\IInitialState; use OCP\Comments\ICommentsManager; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; @@ -36,6 +38,8 @@ class LoadSidebarScripts implements IEventListener { public function __construct( private ICommentsManager $commentsManager, + private IInitialState $initialState, + private IAppManager $appManager, ) { } @@ -46,6 +50,8 @@ public function handle(Event $event): void { $this->commentsManager->load(); + $this->initialState->provideInitialState('activityEnabled', $this->appManager->isEnabledForUser('activity')); + // TODO: make sure to only include the sidebar script when // we properly split it between files list and sidebar Util::addScript(Application::APP_ID, 'comments'); diff --git a/apps/comments/src/comments-activity-tab.ts b/apps/comments/src/comments-activity-tab.ts new file mode 100644 index 0000000000000..30c1e38d8e706 --- /dev/null +++ b/apps/comments/src/comments-activity-tab.ts @@ -0,0 +1,85 @@ +/** + * @copyright Copyright (c) 2023 Ferdinand Thiessen + * + * @author Ferdinand Thiessen + * + * @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 moment from '@nextcloud/moment' +import Vue from 'vue' +import logger from './logger.js' +import { getComments } from './services/GetComments.js' + +let ActivityTabPluginView +let ActivityTabPluginInstance + +/** + * Register the comments plugins for the Activity sidebar + */ +export function registerCommentsPlugins() { + window.OCA.Activity.registerSidebarAction({ + mount: async (el, { context, fileInfo, reload }) => { + if (!ActivityTabPluginView) { + const { default: ActivityCommmentAction } = await import('./views/ActivityCommentAction.vue') + ActivityTabPluginView = Vue.extend(ActivityCommmentAction) + } + ActivityTabPluginInstance = new ActivityTabPluginView({ + parent: context, + propsData: { + reloadCallback: reload, + ressourceId: fileInfo.id, + }, + }) + ActivityTabPluginInstance.$mount(el) + logger.info('Comments plugin mounted in Activity sidebar action', { fileInfo }) + }, + unmount: () => { + // destroy previous instance if available + if (ActivityTabPluginInstance) { + ActivityTabPluginInstance.$destroy() + } + }, + }) + + window.OCA.Activity.registerSidebarEntries(async ({ fileInfo, limit, offset }) => { + const { data: comments } = await getComments({ commentsType: 'files', ressourceId: fileInfo.id }, { limit, offset }) + logger.debug('Loaded comments', { fileInfo, comments }) + const { default: CommentView } = await import('./views/ActivityCommentEntry.vue') + const CommentsViewObject = Vue.extend(CommentView) + + return comments.map((comment) => ({ + timestamp: moment(comment.props.creationDateTime).toDate().getTime(), + mount(element, { context, reload }) { + this._CommentsViewInstance = new CommentsViewObject({ + parent: context, + propsData: { + comment, + ressourceId: fileInfo.id, + reloadCallback: reload, + }, + }) + this._CommentsViewInstance.$mount(element) + }, + unmount() { + this._CommentsViewInstance.$destroy() + }, + })) + }) + + window.OCA.Activity.registerSidebarFilter((activity) => activity.type !== 'comments') + logger.info('Comments plugin registered for Activity sidebar action') +} diff --git a/apps/comments/src/comments-tab.js b/apps/comments/src/comments-tab.js index 121b8d686f4e2..1a367cc18ee8a 100644 --- a/apps/comments/src/comments-tab.js +++ b/apps/comments/src/comments-tab.js @@ -22,40 +22,53 @@ // eslint-disable-next-line n/no-missing-import, import/no-unresolved import MessageReplyText from '@mdi/svg/svg/message-reply-text.svg?raw' +import { getRequestToken } from '@nextcloud/auth' +import { loadState } from '@nextcloud/initial-state' +import { registerCommentsPlugins } from './comments-activity-tab.ts' -// Init Comments tab component -let TabInstance = null -const commentTab = new OCA.Files.Sidebar.Tab({ - id: 'comments', - name: t('comments', 'Comments'), - iconSvg: MessageReplyText, +// @ts-expect-error __webpack_nonce__ is injected by webpack +__webpack_nonce__ = btoa(getRequestToken()) - async mount(el, fileInfo, context) { - if (TabInstance) { +if (loadState('comments', 'activityEnabled', false) && OCA?.Activity?.registerSidebarAction !== undefined) { + // Do not mount own tab but mount into activity + window.addEventListener('DOMContentLoaded', function() { + registerCommentsPlugins() + }) +} else { + // Init Comments tab component + let TabInstance = null + const commentTab = new OCA.Files.Sidebar.Tab({ + id: 'comments', + name: t('comments', 'Comments'), + iconSvg: MessageReplyText, + + async mount(el, fileInfo, context) { + if (TabInstance) { + TabInstance.$destroy() + } + TabInstance = new OCA.Comments.View('files', { + // Better integration with vue parent component + parent: context, + }) + // Only mount after we have all the info we need + await TabInstance.update(fileInfo.id) + TabInstance.$mount(el) + }, + update(fileInfo) { + TabInstance.update(fileInfo.id) + }, + destroy() { TabInstance.$destroy() - } - TabInstance = new OCA.Comments.View('files', { - // Better integration with vue parent component - parent: context, - }) - // Only mount after we have all the info we need - await TabInstance.update(fileInfo.id) - TabInstance.$mount(el) - }, - update(fileInfo) { - TabInstance.update(fileInfo.id) - }, - destroy() { - TabInstance.$destroy() - TabInstance = null - }, - scrollBottomReached() { - TabInstance.onScrollBottomReached() - }, -}) + TabInstance = null + }, + scrollBottomReached() { + TabInstance.onScrollBottomReached() + }, + }) -window.addEventListener('DOMContentLoaded', function() { - if (OCA.Files && OCA.Files.Sidebar) { - OCA.Files.Sidebar.registerTab(commentTab) - } -}) + window.addEventListener('DOMContentLoaded', function() { + if (OCA.Files && OCA.Files.Sidebar) { + OCA.Files.Sidebar.registerTab(commentTab) + } + }) +} diff --git a/apps/comments/src/components/Comment.vue b/apps/comments/src/components/Comment.vue index e8ae9a88e771d..a5b72efb74b83 100644 --- a/apps/comments/src/components/Comment.vue +++ b/apps/comments/src/components/Comment.vue @@ -111,6 +111,7 @@ + + diff --git a/apps/comments/src/views/ActivityCommentEntry.vue b/apps/comments/src/views/ActivityCommentEntry.vue new file mode 100644 index 0000000000000..21c600dcddbde --- /dev/null +++ b/apps/comments/src/views/ActivityCommentEntry.vue @@ -0,0 +1,86 @@ + + + + + + + diff --git a/apps/comments/src/views/Comments.vue b/apps/comments/src/views/Comments.vue index 93e9031df5a88..7a36823299e9a 100644 --- a/apps/comments/src/views/Comments.vue +++ b/apps/comments/src/views/Comments.vue @@ -82,11 +82,8 @@