diff options
author | Grigorii K. Shartsev <me@shgk.me> | 2024-05-16 17:59:29 +0200 |
---|---|---|
committer | Maksim Sukharev <antreesy.web@gmail.com> | 2024-06-28 11:03:31 +0200 |
commit | b71a50cf29a27460d6c622a2368be937e972cc0e (patch) | |
tree | f080aa1e1376148cb745a00e3d03e96cedcff192 | |
parent | 39d2d1637a1ebe50fe08cc60473785fd0ef2b3c4 (diff) |
fix(RightSidebar): use new open state to fix focus trap on mobile
Signed-off-by: Grigorii K. Shartsev <me@shgk.me>
-rw-r--r-- | src/components/RightSidebar/RightSidebar.vue | 119 | ||||
-rw-r--r-- | src/components/TopBar/TopBar.vue | 111 |
2 files changed, 120 insertions, 110 deletions
diff --git a/src/components/RightSidebar/RightSidebar.vue b/src/components/RightSidebar/RightSidebar.vue index 435240cd6..8efc1c03a 100644 --- a/src/components/RightSidebar/RightSidebar.vue +++ b/src/components/RightSidebar/RightSidebar.vue @@ -4,13 +4,27 @@ --> <template> - <NcAppSidebar v-show="opened" + <NcAppSidebar v-if="token" + :open="opened" :name="conversation.displayName" :title="conversation.displayName" :active.sync="activeTab" :class="'active-tab-' + activeTab" + :toggle-classes="{ 'chat-button-sidebar-toggle': isInCall }" + :toggle-attrs="isInCall ? inCallToggleAttrs : undefined" + @update:open="handleUpdateOpen" + @update:active="handleUpdateActive" @closed="handleClosed" @close="handleClose"> + <!-- Use a custom icon when sidebar is used for chat messages during the call --> + <template v-if="isInCall" #toggle-icon> + <MessageText :size="20" /> + <NcCounterBubble v-if="unreadMessagesCounter > 0" + class="chat-button__unread-messages-counter" + :type="hasUnreadMentions ? 'highlighted' : 'outlined'"> + {{ unreadMessagesCounter }} + </NcCounterBubble> + </template> <template #description> <LobbyStatus v-if="canFullModerate && hasLobbyEnabled" :token="token" /> </template> @@ -94,13 +108,16 @@ import DotsCircle from 'vue-material-design-icons/DotsCircle.vue' import FolderMultipleImage from 'vue-material-design-icons/FolderMultipleImage.vue' import InformationOutline from 'vue-material-design-icons/InformationOutline.vue' import Message from 'vue-material-design-icons/Message.vue' +import MessageText from 'vue-material-design-icons/MessageText.vue' +import { showMessage } from '@nextcloud/dialogs' import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus' import { t } from '@nextcloud/l10n' import NcAppSidebar from '@nextcloud/vue/dist/Components/NcAppSidebar.js' import NcAppSidebarTab from '@nextcloud/vue/dist/Components/NcAppSidebarTab.js' import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' +import NcCounterBubble from '@nextcloud/vue/dist/Components/NcCounterBubble.js' import BreakoutRoomsTab from './BreakoutRooms/BreakoutRoomsTab.vue' import LobbyStatus from './LobbyStatus.vue' @@ -123,6 +140,7 @@ export default { NcAppSidebar, NcAppSidebarTab, NcButton, + NcCounterBubble, ParticipantsTab, SetGuestUsername, SharedItemsTab, @@ -134,6 +152,7 @@ export default { FolderMultipleImage, InformationOutline, Message, + MessageText, }, props: { @@ -147,6 +166,7 @@ export default { return { activeTab: 'participants', contactsLoading: false, + unreadNotificationHandle: null, } }, @@ -155,7 +175,7 @@ export default { return this.$store.getters.getSidebarStatus }, opened() { - return !!this.token && !this.isInLobby && this.show + return !this.isInLobby && this.show }, token() { return this.$store.getters.getToken() @@ -257,6 +277,21 @@ export default { breakoutRoomsText() { return t('spreed', 'Breakout rooms') }, + + unreadMessagesCounter() { + return this.conversation.unreadMessages + }, + hasUnreadMentions() { + return this.conversation.unreadMention + }, + + inCallToggleAttrs() { + return { + 'data-theme-dark': true, + 'aria-label': t('spreed', 'Open chat'), + title: t('spreed', 'Open chat') + } + }, }, watch: { @@ -287,6 +322,27 @@ export default { }, }, + unreadMessagesCounter(newValue, oldValue) { + if (!this.isInCall || this.opened) { + return + } + + // new messages arrived + if (newValue > 0 && oldValue === 0 && !this.hasUnreadMentions) { + this.notifyUnreadMessages(t('spreed', 'You have new unread messages in the chat.')) + } + }, + + hasUnreadMentions(newValue) { + if (!this.isInCall || this.opened) { + return + } + + if (newValue) { + this.notifyUnreadMessages(t('spreed', 'You have been mentioned in the chat.')) + } + }, + isInCall(newValue) { if (newValue) { // Set 'chat' tab as active, and switch to it if sidebar is open @@ -294,6 +350,9 @@ export default { return } + // discard notification if the call ends + this.notifyUnreadMessages(null) + // If 'chat' tab wasn't active, leave it as is if (this.activeTab !== 'chat') { return @@ -335,11 +394,30 @@ export default { methods: { t, + + openSidebar() { + // In call by default open on chat + if (this.isInCall) { + this.activeTab = 'chat' + } + + this.$store.dispatch('showSidebar') + BrowserStorage.setItem('sidebarOpen', 'true') + }, + handleClose() { this.$store.dispatch('hideSidebar') BrowserStorage.setItem('sidebarOpen', 'false') }, + handleUpdateOpen(open) { + if (open) { + this.openSidebar() + } else { + this.handleClose() + } + }, + handleUpdateActive(active) { this.activeTab = active }, @@ -351,6 +429,21 @@ export default { handleClosed() { emit('files:sidebar:closed', {}) }, + + notifyUnreadMessages(message) { + if (this.unreadNotificationHandle) { + this.unreadNotificationHandle.hideToast() + this.unreadNotificationHandle = null + } + if (message) { + this.unreadNotificationHandle = showMessage(message, { + onClick: () => { + this.activeTab = 'chat' + this.openSidebar() + }, + }) + } + }, }, } </script> @@ -391,4 +484,26 @@ export default { height: 100%; } +.chat-button__unread-messages-counter { + position: absolute; + bottom: 2px; + right: 2px; + pointer-events: none; + + &.counter-bubble__counter--highlighted { + color: var(--color-primary-text); + } +} +</style> + +<style lang="scss"> +/* + * NcAppSidebar toggle it rendered on the page outside the sidebar element, so we need global styles here. + * It is _quite_ safe, as chat-button-sidebar-toggle class is defined here manually, not an internal class. + */ +.chat-button-sidebar-toggle { + position: relative; + // Allow unread counter to overflow rounded button + overflow: visible !important; +} </style> diff --git a/src/components/TopBar/TopBar.vue b/src/components/TopBar/TopBar.vue index fee8bc701..14d25316d 100644 --- a/src/components/TopBar/TopBar.vue +++ b/src/components/TopBar/TopBar.vue @@ -80,38 +80,6 @@ <CallButton shrink-on-mobile :is-screensharing="!!localMediaModel.attributes.localScreen" /> - <!-- sidebar toggle --> - <template v-if="showOpenSidebarButton"> - <!-- in chat: open last tab --> - <NcButton v-if="!isInCall" - :aria-label="t('spreed', 'Open sidebar')" - :title="t('spreed', 'Open sidebar')" - close-after-click="true" - type="tertiary" - @click="openSidebar"> - <template #icon> - <MenuIcon :size="20" /> - </template> - </NcButton> - - <!-- in call: open chat tab --> - <NcButton v-else - :aria-label="t('spreed', 'Open chat')" - :title="t('spreed', 'Open chat')" - class="chat-button" - type="tertiary" - @click="openSidebar('chat')"> - <template #icon> - <MessageText :size="20" /> - <NcCounterBubble v-if="unreadMessagesCounter > 0" - class="chat-button__unread-messages-counter" - :type="hasUnreadMentions ? 'highlighted' : 'outlined'"> - {{ unreadMessagesCounter }} - </NcCounterBubble> - </template> - </NcButton> - </template> - <!-- Breakout rooms editor --> <BreakoutRoomsEditor v-if="showBreakoutRoomsEditor" :token="token" @@ -121,15 +89,11 @@ <script> import AccountMultiple from 'vue-material-design-icons/AccountMultiple.vue' -import MenuIcon from 'vue-material-design-icons/Menu.vue' -import MessageText from 'vue-material-design-icons/MessageText.vue' -import { showMessage } from '@nextcloud/dialogs' import { emit } from '@nextcloud/event-bus' import { t, n } from '@nextcloud/l10n' import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' -import NcCounterBubble from '@nextcloud/vue/dist/Components/NcCounterBubble.js' import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip.js' import richEditor from '@nextcloud/vue/dist/Mixins/richEditor.js' @@ -163,13 +127,10 @@ export default { ConversationIcon, TopBarMediaControls, NcButton, - NcCounterBubble, TopBarMenu, ReactionMenu, // Icons AccountMultiple, - MenuIcon, - MessageText, }, mixins: [richEditor], @@ -199,7 +160,6 @@ export default { data: () => { return { - unreadNotificationHandle: null, showBreakoutRoomsEditor: false, } }, @@ -209,10 +169,6 @@ export default { return this.$store.getters.getMainContainerSelector() }, - showOpenSidebarButton() { - return !this.$store.getters.getSidebarStatus - }, - isOneToOneConversation() { return this.conversation.type === CONVERSATION.TYPE.ONE_TO_ONE || this.conversation.type === CONVERSATION.TYPE.ONE_TO_ONE_FORMER @@ -238,13 +194,6 @@ export default { return getStatusMessage(this.conversation) }, - unreadMessagesCounter() { - return this.conversation.unreadMessages - }, - hasUnreadMentions() { - return this.conversation.unreadMention - }, - renderedDescription() { return this.renderContent(this.conversation.description) }, @@ -302,36 +251,6 @@ export default { }, }, - watch: { - unreadMessagesCounter(newValue, oldValue) { - if (!this.isInCall || !this.showOpenSidebarButton) { - return - } - - // new messages arrived - if (newValue > 0 && oldValue === 0 && !this.hasUnreadMentions) { - this.notifyUnreadMessages(t('spreed', 'You have new unread messages in the chat.')) - } - }, - - hasUnreadMentions(newValue) { - if (!this.isInCall || !this.showOpenSidebarButton) { - return - } - - if (newValue) { - this.notifyUnreadMessages(t('spreed', 'You have been mentioned in the chat.')) - } - }, - - isInCall(newValue) { - if (!newValue) { - // discard notification if the call ends - this.notifyUnreadMessages(null) - } - }, - }, - mounted() { document.body.classList.add('has-topbar') document.addEventListener('fullscreenchange', this.fullScreenChanged, false) @@ -352,20 +271,6 @@ export default { methods: { t, n, - notifyUnreadMessages(message) { - if (this.unreadNotificationHandle) { - this.unreadNotificationHandle.hideToast() - this.unreadNotificationHandle = null - } - if (message) { - this.unreadNotificationHandle = showMessage(message, { - onClick: () => { - this.openSidebar('chat') - }, - }) - } - }, - openSidebar(activeTab) { if (typeof activeTab === 'string') { emit('spreed:select-active-sidebar-tab', activeTab) @@ -395,7 +300,9 @@ export default { z-index: 10; gap: 3px; justify-content: flex-end; - padding: 8px; + padding: calc(2 * var(--default-grid-baseline)); + // Reserve space for the sidebar toggle button + padding-right: calc(2 * var(--default-grid-baseline) + var(--app-sidebar-offset)); background-color: var(--color-main-background); border-bottom: 1px solid var(--color-border); @@ -411,18 +318,6 @@ export default { left: 0; background-color: transparent; } - - .chat-button { - position: relative; - overflow: visible; - &__unread-messages-counter { - position: absolute; - top: 24px; - right: 2px; - pointer-events: none; - color: var(--color-primary-element); - } - } } .conversation-icon { |