diff options
author | Joas Schilling <213943+nickvergessen@users.noreply.github.com> | 2022-11-07 14:56:04 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-07 14:56:04 +0300 |
commit | 86a150f90aee066a8666012831e0f6e8f70e62b9 (patch) | |
tree | b5b981b049170bbb1d03edac06b22bbeed556501 | |
parent | fbd410fedb04542cd347459f245a848333541a3b (diff) | |
parent | 15594405be5f66f38f817f4b17e48e4a25074a4a (diff) |
Merge pull request #8209 from nextcloud/feature/6889/one-action-menu-only-in-calls
Reduce two menus to one
-rw-r--r-- | src/components/CallView/shared/LocalMediaControls.vue | 112 | ||||
-rw-r--r-- | src/components/TopBar/TopBar.vue | 210 | ||||
-rw-r--r-- | src/components/TopBar/TopBarMenu.vue | 396 |
3 files changed, 417 insertions, 301 deletions
diff --git a/src/components/CallView/shared/LocalMediaControls.vue b/src/components/CallView/shared/LocalMediaControls.vue index 437de45e6..ac68a95dd 100644 --- a/src/components/CallView/shared/LocalMediaControls.vue +++ b/src/components/CallView/shared/LocalMediaControls.vue @@ -167,61 +167,11 @@ @click.stop="toggleHandRaised"> <template #icon> <!-- The following icon is much bigger than all the others - so we reduce its size --> + so we reduce its size --> <HandBackLeft :size="18" fill-color="#ffffff" /> </template> </NcButton> - <NcActions v-if="showActions" - v-tooltip="t('spreed', 'More actions')" - :container="container" - :aria-label="t('spreed', 'More actions')"> - <template #icon> - <DotsHorizontal :size="20" - fill-color="#ffffff" /> - </template> - - <NcActionButton :close-after-click="true" - @click="toggleHandRaised"> - <!-- The following icon is much bigger than all the others - so we reduce its size --> - <template #icon> - <HandBackLeft :size="18" /> - </template> - {{ raiseHandButtonLabel }} - </NcActionButton> - <NcActionButton v-if="isVirtualBackgroundAvailable" - :close-after-click="true" - @click="toggleVirtualBackground"> - <template #icon> - <BlurOff v-if="isVirtualBackgroundEnabled" - :size="20" /> - <Blur v-else - :size="20" /> - </template> - {{ toggleVirtualBackgroundButtonLabel }} - </NcActionButton> - <!-- Call layout switcher --> - <NcActionButton v-if="isInCall" - :close-after-click="true" - @click="changeView"> - <template #icon> - <GridView v-if="!isGrid" - :size="20" /> - <PromotedView v-else - :size="20" /> - </template> - {{ changeViewText }} - </NcActionButton> - <NcActionSeparator /> - <NcActionButton :close-after-click="true" - @click="showSettings"> - <template #icon> - <Cog :size="20" /> - </template> - {{ t('spreed', 'Devices settings') }} - </NcActionButton> - </NcActions> </div> </div> </template> @@ -231,31 +181,26 @@ import escapeHtml from 'escape-html' import { emit } from '@nextcloud/event-bus' import { showMessage } from '@nextcloud/dialogs' import CancelPresentation from '../../missingMaterialDesignIcons/CancelPresentation.vue' -import Cog from 'vue-material-design-icons/Cog.vue' -import DotsHorizontal from 'vue-material-design-icons/DotsHorizontal.vue' -import GridView from '../../missingMaterialDesignIcons/GridView.vue' import HandBackLeft from 'vue-material-design-icons/HandBackLeft.vue' import Microphone from 'vue-material-design-icons/Microphone.vue' import MicrophoneOff from 'vue-material-design-icons/MicrophoneOff.vue' import Monitor from 'vue-material-design-icons/Monitor.vue' import PresentToAll from '../../missingMaterialDesignIcons/PresentToAll.vue' -import PromotedView from '../../missingMaterialDesignIcons/PromotedView.vue' import VideoIcon from 'vue-material-design-icons/Video.vue' import VideoOff from 'vue-material-design-icons/VideoOff.vue' -import Blur from 'vue-material-design-icons/Blur.vue' -import BlurOff from 'vue-material-design-icons/BlurOff.vue' import NcPopover from '@nextcloud/vue/dist/Components/NcPopover.js' -import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip.js' import { PARTICIPANT } from '../../../constants.js' import SpeakingWhileMutedWarner from '../../../utils/webrtc/SpeakingWhileMutedWarner.js' import NetworkStrength2Alert from 'vue-material-design-icons/NetworkStrength2Alert.vue' -import NcActions from '@nextcloud/vue/dist/Components/NcActions.js' -import NcActionSeparator from '@nextcloud/vue/dist/Components/NcActionSeparator.js' -import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js' import { callAnalyzer } from '../../../utils/webrtc/index.js' import { CONNECTION_QUALITY } from '../../../utils/webrtc/analyzers/PeerConnectionAnalyzer.js' import isInCall from '../../../mixins/isInCall.js' +import Blur from 'vue-material-design-icons/Blur.vue' +import BlurOff from 'vue-material-design-icons/BlurOff.vue' +import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' +import NcActions from '@nextcloud/vue/dist/Components/NcActions.js' +import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js' export default { @@ -267,22 +212,17 @@ export default { components: { NetworkStrength2Alert, NcPopover, - NcActions, - NcActionSeparator, - NcActionButton, - NcButton, CancelPresentation, - Cog, - DotsHorizontal, - GridView, HandBackLeft, Microphone, MicrophoneOff, PresentToAll, - PromotedView, VideoIcon, VideoOff, Monitor, + NcButton, + NcActions, + NcActionButton, Blur, BlurOff, }, @@ -337,19 +277,6 @@ export default { }, computed: { - raiseHandButtonLabel() { - if (!this.model.attributes.raisedHand.state) { - if (this.disableKeyboardShortcuts) { - return t('spreed', 'Raise hand') - } - return t('spreed', 'Raise hand (R)') - } - if (this.disableKeyboardShortcuts) { - return t('spreed', 'Lower hand') - } - return t('spreed', 'Lower hand (R)') - }, - isVirtualBackgroundAvailable() { return this.model.attributes.virtualBackgroundAvailable }, @@ -667,18 +594,6 @@ export default { return tooltip }, - changeViewText() { - if (this.isGrid) { - return t('spreed', 'Speaker view') - } else { - return t('spreed', 'Grid view') - } - }, - - isGrid() { - return this.$store.getters.isGrid - }, - disableKeyboardShortcuts() { return OCP.Accessibility.disableKeyboardShortcuts() }, @@ -732,10 +647,6 @@ export default { this.$refs.volumeIndicator.style.height = height + 'px' }, - showSettings() { - emit('show-settings') - }, - /** * This method executes on spacebar keydown and keyup */ @@ -910,11 +821,6 @@ export default { dismissQualityWarningTooltip() { this.$store.dispatch('dismissQualityWarningTooltip') }, - - changeView() { - this.$store.dispatch('setCallViewMode', { isGrid: !this.isGrid }) - this.$store.dispatch('selectedVideoPeerId', null) - }, }, } </script> diff --git a/src/components/TopBar/TopBar.vue b/src/components/TopBar/TopBar.vue index 4e417af7b..2e8429ad8 100644 --- a/src/components/TopBar/TopBar.vue +++ b/src/components/TopBar/TopBar.vue @@ -61,71 +61,17 @@ :show-actions="!isSidebar" :screen-sharing-button-hidden="isSidebar" :local-call-participant-model="localCallParticipantModel" /> + + <!-- TopBar menu --> + <TopBarMenu :token="token" + :show-actions="!isSidebar" + :is-sidebar="isSidebar" + :model="localMediaModel" /> + <div class="top-bar__buttons"> <CallButton class="top-bar__button" /> - <!-- Vertical line --> - <div v-if="!isSidebar && isInCall" - class="top-bar__separator" /> - <!-- sidebar toggle --> - <NcActions v-if="!isSidebar" - v-shortkey.once="disableKeyboardShortcuts ? null : ['f']" - class="top-bar__button" - :aria-label="t('spreed', 'Conversation actions')" - :container="container" - @shortkey.native="toggleFullscreen"> - <template #icon> - <span :class="{'top-bar__button__force-white': isInCall}"> - <Cog :size="20" /> - </span> - </template> - <NcActionButton :icon="iconFullscreen" - :aria-label="t('spreed', 'Toggle fullscreen')" - :close-after-click="true" - @click="toggleFullscreen"> - {{ labelFullscreen }} - </NcActionButton> - <NcActionSeparator v-if="showModerationOptions" /> - <NcActionLink v-if="isFileConversation" - :href="linkToFile"> - <template #icon> - <File :size="20" /> - </template> - {{ t('spreed', 'Go to file') }} - </NcActionLink> - <template v-if="showModerationOptions"> - <NcActionButton :close-after-click="true" - icon="icon-rename" - @click="handleRenameConversation"> - {{ t('spreed', 'Rename conversation') }} - </NcActionButton> - </template> - <NcActionButton v-if="!isOneToOneConversation" - icon="icon-clippy" - :close-after-click="true" - @click="handleCopyLink"> - {{ t('spreed', 'Copy link') }} - </NcActionButton> - <template v-if="showModerationOptions && canFullModerate && isInCall"> - <NcActionSeparator /> - <NcActionButton :close-after-click="true" - @click="forceMuteOthers"> - <template #icon> - <MicrophoneOff :size="20" /> - </template> - {{ t('spreed', 'Mute others') }} - </NcActionButton> - </template> - <NcActionSeparator v-if="showModerationOptions" /> - <NcActionButton :close-after-click="true" - @click="openConversationSettings"> - <template #icon> - <Cog :size="20" /> - </template> - {{ t('spreed', 'Conversation settings') }} - </NcActionButton> - </NcActions> <NcActions v-if="showOpenSidebarButton" class="top-bar__button" close-after-click="true" @@ -156,29 +102,25 @@ </template> <script> -import { showError, showSuccess, showMessage } from '@nextcloud/dialogs' +import { showMessage } from '@nextcloud/dialogs' import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js' import NcActions from '@nextcloud/vue/dist/Components/NcActions.js' import NcCounterBubble from '@nextcloud/vue/dist/Components/NcCounterBubble.js' import CallButton from './CallButton.vue' import BrowserStorage from '../../services/BrowserStorage.js' -import NcActionLink from '@nextcloud/vue/dist/Components/NcActionLink.js' -import NcActionSeparator from '@nextcloud/vue/dist/Components/NcActionSeparator.js' -import File from 'vue-material-design-icons/File.vue' import MenuPeople from '../missingMaterialDesignIcons/MenuPeople.vue' import MessageText from 'vue-material-design-icons/MessageText.vue' -import MicrophoneOff from 'vue-material-design-icons/MicrophoneOff.vue' -import { CONVERSATION, PARTICIPANT } from '../../constants.js' +import { CONVERSATION } from '../../constants.js' import { generateUrl } from '@nextcloud/router' -import { callParticipantCollection, localCallParticipantModel, localMediaModel } from '../../utils/webrtc/index.js' +import { localCallParticipantModel, localMediaModel } from '../../utils/webrtc/index.js' import { emit } from '@nextcloud/event-bus' import ConversationIcon from '../ConversationIcon.vue' import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip.js' import richEditor from '@nextcloud/vue/dist/Mixins/richEditor.js' import userStatus from '../../mixins/userStatus.js' import LocalMediaControls from '../CallView/shared/LocalMediaControls.vue' -import Cog from 'vue-material-design-icons/Cog.vue' import getParticipants from '../../mixins/getParticipants.js' +import TopBarMenu from './TopBarMenu.vue' export default { name: 'TopBar', @@ -190,17 +132,13 @@ export default { components: { NcActionButton, NcActions, - NcActionLink, NcCounterBubble, CallButton, - NcActionSeparator, - File, MenuPeople, MessageText, - MicrophoneOff, ConversationIcon, LocalMediaControls, - Cog, + TopBarMenu, }, mixins: [ @@ -238,60 +176,14 @@ export default { return this.$store.getters.getMainContainerSelector() }, - isFullscreen() { - return this.$store.getters.isFullscreen() - }, - - iconFullscreen() { - if (this.isInCall) { - return 'forced-white icon-fullscreen' - } - return 'icon-fullscreen' - }, - - labelFullscreen() { - if (this.isFullscreen) { - return t('spreed', 'Exit fullscreen (F)') - } - return t('spreed', 'Fullscreen (F)') - }, - showOpenSidebarButton() { return !this.$store.getters.getSidebarStatus }, - isFileConversation() { - return this.conversation.objectType === 'file' && this.conversation.objectId - }, - isOneToOneConversation() { return this.conversation.type === CONVERSATION.TYPE.ONE_TO_ONE }, - linkToFile() { - if (this.isFileConversation) { - return window.location.protocol + '//' + window.location.host + generateUrl('/f/' + this.conversation.objectId) - } else { - return '' - } - }, - - participantType() { - return this.conversation.participantType - }, - - canFullModerate() { - return this.participantType === PARTICIPANT.TYPE.OWNER || this.participantType === PARTICIPANT.TYPE.MODERATOR - }, - - canModerate() { - return this.canFullModerate || this.participantType === PARTICIPANT.TYPE.GUEST_MODERATOR - }, - - showModerationOptions() { - return !this.isOneToOneConversation && this.canModerate - }, - token() { return this.$store.getters.getToken() }, @@ -323,11 +215,6 @@ export default { } }, - conversationHasSettings() { - return this.conversation.type === CONVERSATION.TYPE.GROUP - || this.conversation.type === CONVERSATION.TYPE.PUBLIC - }, - renderedDescription() { return this.renderContent(this.conversation.description) }, @@ -361,10 +248,6 @@ export default { return !peer.sessionIds.length } else return false }, - - disableKeyboardShortcuts() { - return OCP.Accessibility.disableKeyboardShortcuts() - }, }, watch: { @@ -439,67 +322,6 @@ export default { BrowserStorage.setItem('sidebarOpen', 'true') }, - fullScreenChanged() { - this.$store.dispatch( - 'setIsFullscreen', - document.webkitIsFullScreen || document.mozFullScreen || document.msFullscreenElement - ) - }, - - toggleFullscreen() { - if (this.isFullscreen) { - this.disableFullscreen() - this.$store.dispatch('setIsFullscreen', false) - } else { - this.enableFullscreen() - this.$store.dispatch('setIsFullscreen', true) - } - }, - - enableFullscreen() { - const fullscreenElem = document.getElementById('content-vue') - - if (fullscreenElem.requestFullscreen) { - fullscreenElem.requestFullscreen() - } else if (fullscreenElem.webkitRequestFullscreen) { - fullscreenElem.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT) - } else if (fullscreenElem.mozRequestFullScreen) { - fullscreenElem.mozRequestFullScreen() - } else if (fullscreenElem.msRequestFullscreen) { - fullscreenElem.msRequestFullscreen() - } - }, - - disableFullscreen() { - if (document.exitFullscreen) { - document.exitFullscreen() - } else if (document.webkitExitFullscreen) { - document.webkitExitFullscreen() - } else if (document.mozCancelFullScreen) { - document.mozCancelFullScreen() - } else if (document.msExitFullscreen) { - document.msExitFullscreen() - } - }, - - async handleCopyLink() { - try { - await navigator.clipboard.writeText(this.linkToConversation) - showSuccess(t('spreed', 'Conversation link copied to clipboard')) - } catch (error) { - showError(t('spreed', 'The link could not be copied')) - } - }, - handleRenameConversation() { - this.$store.dispatch('isRenamingConversation', true) - this.$store.dispatch('showSidebar') - }, - forceMuteOthers() { - callParticipantCollection.callParticipantModels.forEach(callParticipantModel => { - callParticipantModel.forceMute() - }) - }, - openConversationSettings() { emit('show-conversation-settings', { token: this.token }) }, @@ -561,14 +383,6 @@ export default { right: 4px; pointer-events: none; } - - &__separator { - top: 4px; - border-left: 1px solid white; - height: 36px; - margin: auto 6px; - opacity: 0.5; - } } .conversation-icon { diff --git a/src/components/TopBar/TopBarMenu.vue b/src/components/TopBar/TopBarMenu.vue new file mode 100644 index 000000000..a43b212b8 --- /dev/null +++ b/src/components/TopBar/TopBarMenu.vue @@ -0,0 +1,396 @@ +<!-- + - @copyright Copyright (c) 2022 Marco Ambrosini <marcoambrosini@icloud.com> + - + - @author Marco Ambrosini <marcoambrosini@icloud.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/>. +--> + +<template> + <NcActions v-if="!isSidebar" + v-shortkey.once="disableKeyboardShortcuts ? null : ['f']" + v-tooltip="t('spreed', 'Conversation actions')" + class="top-bar__button" + :aria-label="t('spreed', 'Conversation actions')" + :container="container" + @shortkey.native="toggleFullscreen"> + <!-- White icon if in call --> + <template v-if="isInCall" #icon> + <DotsHorizontal :size="20" + fill-color="#ffffff" /> + </template> + <template v-if="showActions && isInCall"> + <!-- Raise hand --> + <NcActionButton :close-after-click="true" + @click="toggleHandRaised"> + <!-- The following icon is much bigger than all the others + so we reduce its size --> + <template #icon> + <HandBackLeft :size="18" /> + </template> + {{ raiseHandButtonLabel }} + </NcActionButton> + <!-- Blur background --> + <NcActionButton v-if="isVirtualBackgroundAvailable" + :close-after-click="true" + @click="toggleVirtualBackground"> + <template #icon> + <BlurOff v-if="isVirtualBackgroundEnabled" + :size="20" /> + <Blur v-else + :size="20" /> + </template> + {{ toggleVirtualBackgroundButtonLabel }} + </NcActionButton> + <!-- Mute others --> + <template v-if="showModerationOptions && canFullModerate"> + <NcActionButton :close-after-click="true" + @click="forceMuteOthers"> + <template #icon> + <MicrophoneOff :size="20" /> + </template> + {{ t('spreed', 'Mute others') }} + </NcActionButton> + </template> + <!-- Device settings --> + <NcActionButton :close-after-click="true" + @click="showSettings"> + <template #icon> + <VideoIcon :size="20" /> + </template> + {{ t('spreed', 'Devices settings') }} + </NcActionButton> + <NcActionSeparator /> + </template> + <!-- Call layout switcher --> + <NcActionButton v-if="showActions && isInCall" + :close-after-click="true" + @click="changeView"> + <template #icon> + <GridView v-if="!isGrid" + :size="20" /> + <PromotedView v-else + :size="20" /> + </template> + {{ changeViewText }} + </NcActionButton> + <NcActionButton :icon="iconFullscreen" + :aria-label="t('spreed', 'Toggle fullscreen')" + :close-after-click="true" + @click="toggleFullscreen"> + {{ labelFullscreen }} + </NcActionButton> + <NcActionLink v-if="isFileConversation" + :href="linkToFile"> + <template #icon> + <File :size="20" /> + </template> + {{ t('spreed', 'Go to file') }} + </NcActionLink> + <NcActionSeparator v-if="showModerationOptions" /> + <template v-if="showModerationOptions"> + <NcActionButton :close-after-click="true" + icon="icon-rename" + @click="handleRenameConversation"> + {{ t('spreed', 'Rename conversation') }} + </NcActionButton> + </template> + <NcActionButton :close-after-click="true" + @click="openConversationSettings"> + <template #icon> + <Cog :size="20" /> + </template> + {{ t('spreed', 'Conversation settings') }} + </NcActionButton> + </NcActions> +</template> + +<script> +import NcActions from '@nextcloud/vue/dist/Components/NcActions.js' +import NcActionSeparator from '@nextcloud/vue/dist/Components/NcActionSeparator.js' +import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js' +import { emit } from '@nextcloud/event-bus' +import PromotedView from '../missingMaterialDesignIcons/PromotedView.vue' +import Cog from 'vue-material-design-icons/Cog.vue' +import DotsHorizontal from 'vue-material-design-icons/DotsHorizontal.vue' +import GridView from '../missingMaterialDesignIcons/GridView.vue' +import HandBackLeft from 'vue-material-design-icons/HandBackLeft.vue' +import isInCall from '../../mixins/isInCall.js' +import Blur from 'vue-material-design-icons/Blur.vue' +import BlurOff from 'vue-material-design-icons/BlurOff.vue' +import { callParticipantCollection } from '../../utils/webrtc/index.js' +import { generateUrl } from '@nextcloud/router' +import { CONVERSATION, PARTICIPANT } from '../../constants.js' +import VideoIcon from 'vue-material-design-icons/Video.vue' +import MicrophoneOff from 'vue-material-design-icons/MicrophoneOff.vue' + +export default { + name: 'TopBarMenu', + + components: { + NcActions, + NcActionSeparator, + NcActionButton, + PromotedView, + Cog, + DotsHorizontal, + GridView, + HandBackLeft, + Blur, + BlurOff, + VideoIcon, + MicrophoneOff, + }, + + mixins: [ + isInCall, + ], + + props: { + /** + * The conversation token + */ + token: { + type: String, + required: true, + }, + + /** + * The local media model + */ + model: { + type: Object, + required: true, + }, + + showActions: { + type: Boolean, + default: true, + }, + + /** + * In the sidebar the conversation settings are hidden + */ + isSidebar: { + type: Boolean, + default: false, + }, + }, + + data() { + return { + boundaryElement: document.querySelector('.main-view'), + } + }, + + computed: { + conversation() { + return this.$store.getters.conversation(this.token) || this.$store.getters.dummyConversation + }, + + isFullscreen() { + return this.$store.getters.isFullscreen() + }, + + iconFullscreen() { + if (this.isInCall) { + return 'forced-white icon-fullscreen' + } + return 'icon-fullscreen' + }, + + labelFullscreen() { + if (this.isFullscreen) { + return t('spreed', 'Exit fullscreen (F)') + } + return t('spreed', 'Fullscreen (F)') + }, + + conversationHasSettings() { + return this.conversation.type === CONVERSATION.TYPE.GROUP + || this.conversation.type === CONVERSATION.TYPE.PUBLIC + }, + + showModerationOptions() { + return !this.isOneToOneConversation && this.canModerate + }, + + isFileConversation() { + return this.conversation.objectType === 'file' && this.conversation.objectId + }, + + linkToFile() { + if (this.isFileConversation) { + return window.location.protocol + '//' + window.location.host + generateUrl('/f/' + this.conversation.objectId) + } else { + return '' + } + }, + + isOneToOneConversation() { + return this.conversation.type === CONVERSATION.TYPE.ONE_TO_ONE + }, + + toggleVirtualBackgroundButtonLabel() { + if (!this.isVirtualBackgroundEnabled) { + return t('spreed', 'Blur background') + } + return t('spreed', 'Disable background blur') + }, + + container() { + return this.$store.getters.getMainContainerSelector() + }, + + changeViewText() { + if (this.isGrid) { + return t('spreed', 'Speaker view') + } else { + return t('spreed', 'Grid view') + } + }, + + isGrid() { + return this.$store.getters.isGrid + }, + + isVirtualBackgroundAvailable() { + return this.model.attributes.virtualBackgroundAvailable + }, + + isVirtualBackgroundEnabled() { + return this.model.attributes.virtualBackgroundEnabled + }, + + raiseHandButtonLabel() { + if (!this.model.attributes.raisedHand.state) { + if (this.disableKeyboardShortcuts) { + return t('spreed', 'Raise hand') + } + return t('spreed', 'Raise hand (R)') + } + if (this.disableKeyboardShortcuts) { + return t('spreed', 'Lower hand') + } + return t('spreed', 'Lower hand (R)') + }, + + disableKeyboardShortcuts() { + return OCP.Accessibility.disableKeyboardShortcuts() + }, + + participantType() { + return this.conversation.participantType + }, + + canFullModerate() { + return this.participantType === PARTICIPANT.TYPE.OWNER || this.participantType === PARTICIPANT.TYPE.MODERATOR + }, + + canModerate() { + return this.canFullModerate || this.participantType === PARTICIPANT.TYPE.GUEST_MODERATOR + }, + }, + + methods: { + handleRenameConversation() { + this.$store.dispatch('isRenamingConversation', true) + this.$store.dispatch('showSidebar') + }, + forceMuteOthers() { + callParticipantCollection.callParticipantModels.forEach(callParticipantModel => { + callParticipantModel.forceMute() + }) + }, + + fullScreenChanged() { + this.$store.dispatch( + 'setIsFullscreen', + document.webkitIsFullScreen || document.mozFullScreen || document.msFullscreenElement + ) + }, + + toggleFullscreen() { + if (this.isFullscreen) { + this.disableFullscreen() + this.$store.dispatch('setIsFullscreen', false) + } else { + this.enableFullscreen() + this.$store.dispatch('setIsFullscreen', true) + } + }, + + enableFullscreen() { + const fullscreenElem = document.getElementById('content-vue') + + if (fullscreenElem.requestFullscreen) { + fullscreenElem.requestFullscreen() + } else if (fullscreenElem.webkitRequestFullscreen) { + fullscreenElem.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT) + } else if (fullscreenElem.mozRequestFullScreen) { + fullscreenElem.mozRequestFullScreen() + } else if (fullscreenElem.msRequestFullscreen) { + fullscreenElem.msRequestFullscreen() + } + }, + + disableFullscreen() { + if (document.exitFullscreen) { + document.exitFullscreen() + } else if (document.webkitExitFullscreen) { + document.webkitExitFullscreen() + } else if (document.mozCancelFullScreen) { + document.mozCancelFullScreen() + } else if (document.msExitFullscreen) { + document.msExitFullscreen() + } + }, + + toggleVirtualBackground() { + if (this.model.attributes.virtualBackgroundEnabled) { + this.model.disableVirtualBackground() + } else { + this.model.enableVirtualBackground() + } + }, + + changeView() { + this.$store.dispatch('setCallViewMode', { isGrid: !this.isGrid }) + this.$store.dispatch('selectedVideoPeerId', null) + }, + + showSettings() { + emit('show-settings', {}) + }, + + toggleHandRaised() { + const state = !this.model.attributes.raisedHand?.state + this.model.toggleHandRaised(state) + this.$store.dispatch( + 'setParticipantHandRaised', + { + sessionId: this.$store.getters.getSessionId(), + raisedHand: this.model.attributes.raisedHand, + } + ) + }, + + openConversationSettings() { + emit('show-conversation-settings', { token: this.token }) + }, + }, +} +</script> |