Skip to content

Commit

Permalink
Add presenter overlay when sharing screen
Browse files Browse the repository at this point in the history
Signed-off-by: DorraJaouad <dorra.jaoued7@gmail.com>
  • Loading branch information
DorraJaouad committed Oct 18, 2023
1 parent 5a09831 commit 2692b84
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 12 deletions.
94 changes: 94 additions & 0 deletions src/components/CallView/CallView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,32 @@
:call-participant-model="callParticipantModel"
:shared-data="sharedDatas[shownRemoteScreenPeerId]"
:is-big="true" />
<!-- presenter overlay -->
<TransitionWrapper v-if="shouldShowPresenterOverlay(callParticipantModel)"
:key="'presenter-overlay-video' + callParticipantModel.attributes.peerId"
name="slide-down">
<VideoVue :key="'video-overlay-' + callParticipantModel.attributes.peerId"
class="presenter-overlay__video"
:token="token"
:model="callParticipantModel"
:shared-data="sharedDatas[shownRemoteScreenPeerId]"
is-presenter-overlay
un-selectable
hide-bottom-bar
@click-video="toggleShowPresenterOverlay" />
</TransitionWrapper>
<!-- presenter button when presenter overlay is collapsed -->
<NcButton v-else-if="isPresenterCollapsed(callParticipantModel)"
:key="'presenter-overlay-button' + callParticipantModel.attributes.peerId"
:aria-label="t('spreed', 'Show presenter')"
:title="t('spreed', 'Show presenter')"
class="presenter-overlay--collapse"
type="tertiary-no-background"
@click="toggleShowPresenterOverlay">
<template #icon>
<AccountBox fill-color="#ffffff" :size="20" />
</template>
</NcButton>
</template>
</template>
</div>
Expand Down Expand Up @@ -153,32 +179,39 @@ import { showMessage } from '@nextcloud/dialogs'
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
import { loadState } from '@nextcloud/initial-state'

import AccountBox from 'vue-material-design-icons/AccountBoxOutline.vue'

import Grid from './Grid/Grid.vue'
import EmptyCallView from './shared/EmptyCallView.vue'
import LocalVideo from './shared/LocalVideo.vue'
import ReactionToaster from './shared/ReactionToaster.vue'
import Screen from './shared/Screen.vue'
import VideoVue from './shared/VideoVue.vue'
import ViewerOverlayCallView from './shared/ViewerOverlayCallView.vue'
import TransitionWrapper from '../TransitionWrapper.vue'

import { SIMULCAST } from '../../constants.js'
import BrowserStorage from '../../services/BrowserStorage.js'
import { fetchPeers } from '../../services/callsService.js'
import { EventBus } from '../../services/EventBus.js'
import { localMediaModel, localCallParticipantModel, callParticipantCollection } from '../../utils/webrtc/index.js'
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import RemoteVideoBlocker from '../../utils/webrtc/RemoteVideoBlocker.js'

export default {
name: 'CallView',

components: {
AccountBox,
EmptyCallView,
ViewerOverlayCallView,
Grid,
LocalVideo,
NcButton,
ReactionToaster,
Screen,
VideoVue,
TransitionWrapper,
},

props: {
Expand Down Expand Up @@ -214,6 +247,7 @@ export default {
},
callParticipantCollection,
isBackgroundBlurred: true,
showPresenterOverlay: true,
}
},
computed: {
Expand Down Expand Up @@ -362,6 +396,11 @@ export default {
supportedReactions() {
return getCapabilities()?.spreed?.config?.call?.['supported-reactions']
},

presenterVideoBlockerEnabled() {
return this.sharedDatas[this.shownRemoteScreenPeerId]?.remoteVideoBlocker?.isVideoEnabled()
},

},
watch: {
'localCallParticipantModel.attributes.peerId'(newValue, previousValue) {
Expand Down Expand Up @@ -436,6 +475,10 @@ export default {
this.$store.dispatch('setCallViewMode', { isGrid: false })
}
},

presenterVideoBlockerEnabled(value) {
this.showPresenterOverlay = value
},
},
created() {
// Ensure that data is properly initialized before mounting the
Expand Down Expand Up @@ -713,6 +756,28 @@ export default {
setBackgroundBlurred(value) {
this.isBackgroundBlurred = value
},

isPresenterCollapsed(callParticipantModel) {
return (callParticipantModel.attributes.peerId === this.shownRemoteScreenPeerId
&& !this.showPresenterOverlay
&& callParticipantModel.attributes.videoAvailable)

},

shouldShowPresenterOverlay(callParticipantModel) {
return callParticipantModel.attributes.peerId === this.shownRemoteScreenPeerId
&& this.showPresenterOverlay
&& this.callParticipantModelsWithVideo.includes(callParticipantModel)

},

toggleShowPresenterOverlay() {
if (!this.presenterVideoBlockerEnabled) {
this.sharedDatas[this.shownRemoteScreenPeerId].remoteVideoBlocker.setVideoEnabled(true)
} else {
this.showPresenterOverlay = !this.showPresenterOverlay
}
},
},
}
</script>
Expand All @@ -737,6 +802,35 @@ export default {
}
}

.presenter-overlay__video {
position: absolute;
bottom: 48px;
right: 8px;
--max-size: 242px;
width: 10vw;
height: 10vw;
max-width: var(--max-size);
max-height: var(--max-size);
z-index: 10;
}

.presenter-overlay--collapse {
position : absolute !important;
opacity: .7;
bottom: 48px;
right: 0;

#call-container:hover & {
background-color: rgba(0, 0, 0, 0.1) !important;

&:hover,
&:focus {
opacity: 1;
background-color: rgba(0, 0, 0, 0.2) !important;
}
}
}

#videos {
position: absolute;
width: 100%;
Expand Down
50 changes: 38 additions & 12 deletions src/components/CallView/shared/VideoVue.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@
<div v-show="!placeholderForPromoted || sharedData.promoted"
:id="(placeholderForPromoted ? 'placeholder-' : '') + 'container_' + peerId + '_video_incoming'"
ref="videoContainer"
class="videoContainer"
:class="containerClass"
class="video-container"
:class="[containerClass, {
speaking: isSpeaking && !isBig,
hover: mouseover && !unSelectable && !isBig,
presenter: isPresenterOverlay && mouseover
}]"
@mouseover="showShadow"
@mouseleave="hideShadow"
@click="handleClickVideo">
Expand Down Expand Up @@ -77,8 +81,7 @@
:has-shadow="hasVideo"
:participant-name="participantName" />
</slot>
<div v-if="isSpeaking && !isStripe && !isBig" class="speaking-shadow" />
<div v-if="!unSelectable && mouseover && !isBig" class="hover-shadow" />
<AccountOff v-if="isPresenterOverlay && mouseover" class="presenter-icon__hide" :size="30" />
</div>
</template>

Expand All @@ -88,6 +91,7 @@ import Hex from 'crypto-js/enc-hex.js'
import SHA1 from 'crypto-js/sha1.js'

import AccountCircle from 'vue-material-design-icons/AccountCircle.vue'
import AccountOff from 'vue-material-design-icons/AccountOff.vue'

import AvatarWrapper from '../../AvatarWrapper/AvatarWrapper.vue'
import TransitionWrapper from '../../TransitionWrapper.vue'
Expand All @@ -109,9 +113,11 @@ export default {
AvatarWrapper,
TransitionWrapper,
VideoBackground,
AccountCircle,
Screen,
VideoBottomBar,
// icons
AccountCircle,
AccountOff,
},

mixins: [video],
Expand Down Expand Up @@ -141,6 +147,12 @@ export default {
type: Boolean,
default: false,
},

isPresenterOverlay: {
type: Boolean,
default: false,
},

// True if this video component is used in the promoted view's video stripe
isStripe: {
type: Boolean,
Expand Down Expand Up @@ -449,15 +461,15 @@ export default {
// Grid
} else {
// Always show shared screen if there's one
return this.hasSharedScreen
return this.hasSharedScreen && !this.isPresenterOverlay
}
},

showVideo() {
// Screenshare have higher priority so return false if screenshare
// is shown
if (this.hasSharedScreen) {
return !this.showSharedScreen && this.hasVideo && !this.isSelected
return (!this.showSharedScreen && this.hasVideo && !this.isSelected) || this.isPresenterOverlay
} else {
if (this.isStripe) {
if (this.hasSelectedVideo) {
Expand Down Expand Up @@ -680,24 +692,38 @@ export default {
top: calc(50% + 80px);
}

.speaking-shadow {
.video-container::after {
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
box-shadow: inset 0 0 0 2px white;
border-radius: calc(var(--default-clickable-area) / 2);
}
.video-container.speaking::after {
content: '';
box-shadow: inset 0 0 0 2px white;
}

.hover-shadow {
.video-container.hover::after {
content: '';
box-shadow: inset 0 0 0 3px white;
cursor: pointer;
}

.presenter-icon__hide {
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
box-shadow: inset 0 0 0 3px white;
color: white;
}

.video-container.presenter::after {
content: '' ;
background-color: rgba(0, 0, 0, 0.5);
cursor: pointer;
border-radius: calc(var(--default-clickable-area) / 2);
}

</style>

0 comments on commit 2692b84

Please sign in to comment.