summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDorra <dorra.jaoued7@gmail.com>2024-03-14 11:02:31 +0100
committerGitHub <noreply@github.com>2024-03-14 11:02:31 +0100
commitd206d551618df7d30997068d5c59f03776928839 (patch)
treee5e49a7a5581ca890fda2ab1ce7247c9098656ac
parent891ede4d46e9f5b139c5928b3734415f47bb8ba1 (diff)
parent9e15ea3897f2b2750d371b46b76b43b165132029 (diff)
Merge pull request #11701 from nextcloud/feat/noid/draggable-presenter-overlay
feat(PresenterOverlay): make the overlay draggable.
-rw-r--r--package-lock.json19
-rw-r--r--package.json1
-rw-r--r--src/components/CallView/CallView.vue35
-rw-r--r--src/components/CallView/shared/VideoVue.vue42
4 files changed, 75 insertions, 22 deletions
diff --git a/package-lock.json b/package-lock.json
index 9b9d74bf4..764700362 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -43,6 +43,7 @@
"util": "^0.12.5",
"vue": "^2.7.16",
"vue-cropperjs": "^4.2.0",
+ "vue-draggable-resizable": "^1.7.5",
"vue-frag": "^1.4.3",
"vue-material-design-icons": "^5.3.0",
"vue-observe-visibility": "^1.0.0",
@@ -19806,6 +19807,18 @@
"cropperjs": "^1.5.6"
}
},
+ "node_modules/vue-draggable-resizable": {
+ "version": "1.7.5",
+ "resolved": "https://registry.npmjs.org/vue-draggable-resizable/-/vue-draggable-resizable-1.7.5.tgz",
+ "integrity": "sha512-+L0tqbZYuskfSpKlk1EfsB9OOuy7NNFPaIry4nZ7g+Sr4JaL5xQ6pEaE5IavkV9M/riX/1pr6uAPc9pLxcqfLg==",
+ "engines": {
+ "node": ">= 4.0.0",
+ "npm": ">= 3.0.0"
+ },
+ "peerDependencies": {
+ "vue": "^2.3.0"
+ }
+ },
"node_modules/vue-eslint-parser": {
"version": "9.3.1",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.3.1.tgz",
@@ -35491,6 +35504,12 @@
"cropperjs": "^1.5.6"
}
},
+ "vue-draggable-resizable": {
+ "version": "1.7.5",
+ "resolved": "https://registry.npmjs.org/vue-draggable-resizable/-/vue-draggable-resizable-1.7.5.tgz",
+ "integrity": "sha512-+L0tqbZYuskfSpKlk1EfsB9OOuy7NNFPaIry4nZ7g+Sr4JaL5xQ6pEaE5IavkV9M/riX/1pr6uAPc9pLxcqfLg==",
+ "requires": {}
+ },
"vue-eslint-parser": {
"version": "9.3.1",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.3.1.tgz",
diff --git a/package.json b/package.json
index 83d606920..a745e3a21 100644
--- a/package.json
+++ b/package.json
@@ -58,6 +58,7 @@
"util": "^0.12.5",
"vue": "^2.7.16",
"vue-cropperjs": "^4.2.0",
+ "vue-draggable-resizable": "^1.7.5",
"vue-frag": "^1.4.3",
"vue-material-design-icons": "^5.3.0",
"vue-observe-visibility": "^1.0.0",
diff --git a/src/components/CallView/CallView.vue b/src/components/CallView/CallView.vue
index 3641e747c..e278f0544 100644
--- a/src/components/CallView/CallView.vue
+++ b/src/components/CallView/CallView.vue
@@ -75,8 +75,14 @@
:shared-data="sharedDatas[shownRemoteScreenPeerId]"
is-big />
<!-- presenter overlay -->
- <TransitionWrapper v-if="shouldShowPresenterOverlay"
- name="slide-down">
+ <VueDraggableResizable v-if="shouldShowPresenterOverlay"
+ :key="presenterOverlaySize"
+ parent
+ :resizable="false"
+ :h="presenterOverlaySize"
+ :w="presenterOverlaySize"
+ :x="10"
+ :y="10">
<VideoVue class="presenter-overlay__video"
:token="token"
:model="shownRemoteScreenCallParticipantModel"
@@ -84,8 +90,8 @@
is-presenter-overlay
un-selectable
hide-bottom-bar
- @click-video="toggleShowPresenterOverlay" />
- </TransitionWrapper>
+ @click-presenter="toggleShowPresenterOverlay" />
+ </VueDraggableResizable>
<!-- presenter button when presenter overlay is collapsed -->
<NcButton v-else-if="isPresenterCollapsed"
:aria-label="t('spreed', 'Show presenter')"
@@ -153,6 +159,7 @@
<script>
import debounce from 'debounce'
+import VueDraggableResizable from 'vue-draggable-resizable'
import AccountBox from 'vue-material-design-icons/AccountBoxOutline.vue'
@@ -169,7 +176,6 @@ 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'
@@ -187,13 +193,13 @@ export default {
AccountBox,
EmptyCallView,
ViewerOverlayCallView,
+ VueDraggableResizable,
Grid,
LocalVideo,
NcButton,
ReactionToaster,
Screen,
VideoVue,
- TransitionWrapper,
},
props: {
@@ -236,6 +242,7 @@ export default {
isBackgroundBlurred: true,
showPresenterOverlay: true,
debounceFetchPeers: () => {},
+ presenterOverlaySize: 128,
}
},
computed: {
@@ -372,7 +379,6 @@ export default {
presenterVideoBlockerEnabled() {
return this.sharedDatas[this.shownRemoteScreenPeerId]?.remoteVideoBlocker?.isVideoEnabled()
},
-
},
watch: {
'localCallParticipantModel.attributes.peerId'(newValue, previousValue) {
@@ -470,6 +476,8 @@ export default {
subscribe('switch-screen-to-id', this._switchScreenToId)
subscribe('set-background-blurred', this.setBackgroundBlurred)
+
+ window.addEventListener('resize', this.updateSize)
},
beforeDestroy() {
this.debounceFetchPeers.clear?.()
@@ -479,6 +487,8 @@ export default {
unsubscribe('switch-screen-to-id', this._switchScreenToId)
unsubscribe('set-background-blurred', this.setBackgroundBlurred)
+
+ window.removeEventListener('resize', this.updateSize)
},
methods: {
/**
@@ -758,6 +768,10 @@ export default {
this.showPresenterOverlay = !this.showPresenterOverlay
}
},
+
+ updateSize() {
+ this.presenterOverlaySize = Math.min(Math.max(window.innerWidth * 0.1, 100), 242)
+ },
},
}
</script>
@@ -783,14 +797,15 @@ export default {
}
.presenter-overlay__video {
- position: absolute;
- bottom: 48px;
- right: 8px;
+ position: relative;
--max-size: 242px;
+ --min-size: 100px;
width: 10vw;
height: 10vw;
max-width: var(--max-size);
max-height: var(--max-size);
+ min-width: var(--min-size);
+ min-height: var(--min-size);
z-index: 10;
}
diff --git a/src/components/CallView/shared/VideoVue.vue b/src/components/CallView/shared/VideoVue.vue
index 918debb1b..075481de9 100644
--- a/src/components/CallView/shared/VideoVue.vue
+++ b/src/components/CallView/shared/VideoVue.vue
@@ -37,6 +37,12 @@
:class="fitVideo ? 'video--fit' : 'video--fill'"
class="video"
@playing="updateVideoAspectRatio" />
+ <AccountOff v-if="isPresenterOverlay && mouseover"
+ class="presenter-icon__hide"
+ :aria-label="t('spreed', 'Hide presenter video')"
+ :title="t('spreed', 'Hide presenter video')"
+ :size="32"
+ @click="$emit('click-presenter')" />
</div>
</TransitionWrapper>
<TransitionWrapper name="fade">
@@ -78,7 +84,6 @@
:has-shadow="hasVideo"
:participant-name="participantName" />
</slot>
- <AccountOff v-if="isPresenterOverlay && mouseover" class="presenter-icon__hide" :size="30" />
</div>
</template>
@@ -191,7 +196,7 @@ export default {
},
},
- emits: ['click-video'],
+ emits: ['click-video', 'click-presenter'],
setup() {
const guestNameStore = useGuestNameStore()
@@ -304,12 +309,14 @@ export default {
'video-container-grid': this.isGrid,
'video-container-big': this.isBig,
'one-to-one': this.isOneToOne,
+ 'presenter-overlay': this.isPresenterOverlay
}
},
videoWrapperClass() {
return {
'icon-loading': this.isLoading,
+ 'presenter-overlay': this.isPresenterOverlay
}
},
@@ -660,6 +667,10 @@ export default {
border-radius: calc(var(--default-clickable-area) / 2);
}
+.videoWrapper.presenter-overlay > video {
+ border-radius: 50%;
+}
+
.videoWrapper.icon-loading:after {
height: 60px;
width: 60px;
@@ -703,6 +714,10 @@ export default {
border-radius: calc(var(--default-clickable-area) / 2);
}
+.video-container.presenter-overlay::after {
+ border-radius: 50%;
+}
+
.video-container.speaking::after {
content: '';
box-shadow: inset 0 0 0 2px white;
@@ -715,18 +730,21 @@ export default {
}
.presenter-icon__hide {
- position: absolute;
- height: 100%;
- width: 100%;
- top: 0;
- left: 0;
+ position: relative;
color: white;
-}
-
-.video-container.presenter::after {
- content: '';
+ left: 50%;
+ transform: translate(-50%, -52px);
+ opacity: 0.7;
background-color: rgba(0, 0, 0, 0.5);
- cursor: pointer;
+ border-radius: 50%;
+ padding: 6px;
+ width: 44px;
+
+ &:hover {
+ cursor: pointer;
+ opacity: 0.9;
+ }
+
}
</style>