Skip to content

Commit f10fbae

Browse files
committed
Display local media controls also when collapsed
Moved LocalMediaControls to the Grid view to make sure it's always visible even when the grid is collapsed. Signed-off-by: Vincent Petry <[email protected]>
1 parent ab95a9f commit f10fbae

File tree

4 files changed

+181
-199
lines changed

4 files changed

+181
-199
lines changed

src/components/CallView/CallView.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
<Grid
9393
v-if="showGrid"
9494
v-bind="$attrs"
95+
:is-sidebar="isSidebar"
9596
:is-stripe="!isGrid"
9697
:token="token"
9798
:fit-video="true"

src/components/CallView/Grid/Grid.vue

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@
3535
decorative
3636
:size="24" />
3737
</button>
38+
<LocalMediaControls
39+
class="local-media-controls"
40+
:model="localMediaModel"
41+
:local-call-participant-model="localCallParticipantModel"
42+
:screen-sharing-button-hidden="isSidebar"
43+
@switch-screen-to-id="$emit('switchScreenToId', $event)" />
3844
<transition name="slide-down">
3945
<div v-if="!isStripe || stripeOpen" class="wrapper" :style="wrapperStyle">
4046
<div :class="{'pagination-wrapper': isStripe, 'wrapper': !isStripe}">
@@ -143,6 +149,7 @@
143149
import debounce from 'debounce'
144150
import Video from '../shared/Video'
145151
import LocalVideo from '../shared/LocalVideo'
152+
import LocalMediaControls from '../shared/LocalMediaControls'
146153
import { EventBus } from '../../../services/EventBus'
147154
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
148155
import EmptyCallView from '../shared/EmptyCallView'
@@ -157,6 +164,7 @@ export default {
157164
components: {
158165
Video,
159166
LocalVideo,
167+
LocalMediaControls,
160168
EmptyCallView,
161169
ChevronRight,
162170
ChevronLeft,
@@ -219,6 +227,10 @@ export default {
219227
type: Boolean,
220228
default: false,
221229
},
230+
isSidebar: {
231+
type: Boolean,
232+
default: false,
233+
},
222234
callParticipantModels: {
223235
type: Array,
224236
required: true,
@@ -815,4 +827,13 @@ export default {
815827
background: none;
816828
}
817829
830+
.local-media-controls {
831+
position: absolute;
832+
width: 300px; /* same as .video-container-stripe */
833+
text-align: center;
834+
right: 0;
835+
bottom: 4px;
836+
z-index: 1;
837+
}
838+
818839
</style>

src/components/CallView/shared/LocalMediaControls.vue

Lines changed: 122 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<template>
2222
<div v-shortkey.push="['space']"
2323
@shortkey="toggleAudio">
24-
<div v-if="!isBig" class="nameIndicator">
24+
<div class="buttons-bar">
2525
<div id="muteWrapper">
2626
<button
2727
id="mute"
@@ -83,14 +83,6 @@
8383
</ul>
8484
</div>
8585
</div>
86-
<div class="bottom-bar">
87-
<button
88-
v-if="isBig"
89-
class="bottom-bar__button"
90-
@click="handleStopFollowing">
91-
{{ stopFollowingLabel }}
92-
</button>
93-
</div>
9486
<div class="network-connection-state">
9587
<Popover
9688
v-if="qualityWarningTooltip"
@@ -136,6 +128,8 @@ import Popover from '@nextcloud/vue/dist/Components/Popover'
136128
import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip'
137129
import SpeakingWhileMutedWarner from '../../../utils/webrtc/SpeakingWhileMutedWarner'
138130
import NetworkStrength2Alert from 'vue-material-design-icons/NetworkStrength2Alert'
131+
import { callAnalyzer } from '../../../utils/webrtc/index'
132+
import { CONNECTION_QUALITY } from '../../../utils/webrtc/analyzers/PeerConnectionAnalyzer'
139133
140134
export default {
141135
@@ -163,18 +157,6 @@ export default {
163157
type: Boolean,
164158
default: false,
165159
},
166-
qualityWarningAriaLabel: {
167-
type: String,
168-
default: '',
169-
},
170-
qualityWarningTooltip: {
171-
type: Object,
172-
default: null,
173-
},
174-
isBig: {
175-
type: Boolean,
176-
default: false,
177-
},
178160
},
179161
180162
data() {
@@ -186,6 +168,8 @@ export default {
186168
boundaryElement: document.querySelector('.main-view'),
187169
isQualityWarningTooltipDismissed: false,
188170
mouseover: false,
171+
callAnalyzer: callAnalyzer,
172+
qualityWarningInGracePeriodTimeout: null,
189173
}
190174
},
191175
@@ -208,7 +192,7 @@ export default {
208192
}
209193
}
210194
211-
if (this.speakingWhileMutedNotification) {
195+
if (this.speakingWhileMutedNotification && !this.screenSharingMenuOpen) {
212196
return {
213197
content: this.speakingWhileMutedNotification,
214198
show: true,
@@ -319,12 +303,112 @@ export default {
319303
return this.qualityWarningTooltip && (!this.isQualityWarningTooltipDismissed || this.mouseover)
320304
},
321305
322-
stopFollowingLabel() {
323-
return t('spreed', 'Back')
306+
showQualityWarning() {
307+
return this.senderConnectionQualityIsBad || this.qualityWarningInGracePeriodTimeout
308+
},
309+
310+
senderConnectionQualityIsBad() {
311+
return this.senderConnectionQualityAudioIsBad
312+
|| this.senderConnectionQualityVideoIsBad
313+
|| this.senderConnectionQualityScreenIsBad
314+
},
315+
316+
senderConnectionQualityAudioIsBad() {
317+
return callAnalyzer
318+
&& (callAnalyzer.attributes.senderConnectionQualityAudio === CONNECTION_QUALITY.VERY_BAD
319+
|| callAnalyzer.attributes.senderConnectionQualityAudio === CONNECTION_QUALITY.NO_TRANSMITTED_DATA)
320+
},
321+
322+
senderConnectionQualityVideoIsBad() {
323+
return callAnalyzer
324+
&& (callAnalyzer.attributes.senderConnectionQualityVideo === CONNECTION_QUALITY.VERY_BAD
325+
|| callAnalyzer.attributes.senderConnectionQualityVideo === CONNECTION_QUALITY.NO_TRANSMITTED_DATA)
326+
},
327+
328+
senderConnectionQualityScreenIsBad() {
329+
return callAnalyzer
330+
&& (callAnalyzer.attributes.senderConnectionQualityScreen === CONNECTION_QUALITY.VERY_BAD
331+
|| callAnalyzer.attributes.senderConnectionQualityScreen === CONNECTION_QUALITY.NO_TRANSMITTED_DATA)
332+
},
333+
334+
qualityWarningAriaLabel() {
335+
let label = ''
336+
if (!this.model.attributes.audioEnabled && this.model.attributes.videoEnabled && this.model.attributes.localScreen) {
337+
label = t('spreed', 'Bad sent video and screen quality.')
338+
} else if (!this.model.attributes.audioEnabled && this.model.attributes.localScreen) {
339+
label = t('spreed', 'Bad sent screen quality.')
340+
} else if (!this.model.attributes.audioEnabled && this.model.attributes.videoEnabled) {
341+
label = t('spreed', 'Bad sent video quality.')
342+
} else if (this.model.attributes.videoEnabled && this.model.attributes.localScreen) {
343+
label = t('spreed', 'Bad sent audio, video and screen quality.')
344+
} else if (this.model.attributes.localScreen) {
345+
label = t('spreed', 'Bad sent audio and screen quality.')
346+
} else if (this.model.attributes.videoEnabled) {
347+
label = t('spreed', 'Bad sent audio and video quality.')
348+
} else {
349+
label = t('spreed', 'Bad sent audio quality.')
350+
}
351+
352+
return label
353+
},
354+
355+
qualityWarningTooltip() {
356+
if (!this.showQualityWarning) {
357+
return null
358+
}
359+
360+
const tooltip = {}
361+
if (!this.model.attributes.audioEnabled && this.model.attributes.videoEnabled && this.model.attributes.localScreen) {
362+
tooltip.content = t('spreed', 'Your internet connection or computer are busy and other participants might be unable to see you. To improve the situation try to disable your video while doing a screenshare.')
363+
tooltip.actionLabel = t('spreed', 'Disable video')
364+
tooltip.action = 'disableVideo'
365+
} else if (!this.model.attributes.audioEnabled && this.model.attributes.localScreen) {
366+
tooltip.content = t('spreed', 'Your internet connection or computer are busy and other participants might be unable to see your screen.')
367+
tooltip.actionLabel = ''
368+
tooltip.action = ''
369+
} else if (!this.model.attributes.audioEnabled && this.model.attributes.videoEnabled) {
370+
tooltip.content = t('spreed', 'Your internet connection or computer are busy and other participants might be unable to see you.')
371+
tooltip.actionLabel = ''
372+
tooltip.action = ''
373+
} else if (this.model.attributes.videoEnabled && this.model.attributes.localScreen) {
374+
tooltip.content = t('spreed', 'Your internet connection or computer are busy and other participants might be unable to understand and see you. To improve the situation try to disable your video while doing a screenshare.')
375+
tooltip.actionLabel = t('spreed', 'Disable video')
376+
tooltip.action = 'disableVideo'
377+
} else if (this.model.attributes.localScreen) {
378+
tooltip.content = t('spreed', 'Your internet connection or computer are busy and other participants might be unable to understand and see your screen. To improve the situation try to disable your screenshare.')
379+
tooltip.actionLabel = t('spreed', 'Disable screenshare')
380+
tooltip.action = 'disableScreenShare'
381+
} else if (this.model.attributes.videoEnabled) {
382+
tooltip.content = t('spreed', 'Your internet connection or computer are busy and other participants might be unable to understand and see you. To improve the situation try to disable your video.')
383+
tooltip.actionLabel = t('spreed', 'Disable video')
384+
tooltip.action = 'disableVideo'
385+
} else {
386+
tooltip.content = t('spreed', 'Your internet connection or computer are busy and other participants might be unable to understand you.')
387+
tooltip.actionLabel = ''
388+
tooltip.action = ''
389+
}
390+
391+
return tooltip
324392
},
325393
326394
},
327395
396+
watch: {
397+
senderConnectionQualityIsBad: function(senderConnectionQualityIsBad) {
398+
if (!senderConnectionQualityIsBad) {
399+
return
400+
}
401+
402+
if (this.qualityWarningInGracePeriodTimeout) {
403+
window.clearTimeout(this.qualityWarningInGracePeriodTimeout)
404+
}
405+
406+
this.qualityWarningInGracePeriodTimeout = window.setTimeout(() => {
407+
this.qualityWarningInGracePeriodTimeout = null
408+
}, 10000)
409+
},
410+
},
411+
328412
created() {
329413
// The standard "getDisplayMedia" does not support pre-filtering the
330414
// type of display sources, so the unified menu is used in that case
@@ -476,10 +560,6 @@ export default {
476560
this.isQualityWarningTooltipDismissed = true
477561
}
478562
},
479-
480-
handleStopFollowing() {
481-
this.$store.dispatch('selectedVideoPeerId', null)
482-
},
483563
},
484564
}
485565
</script>
@@ -507,14 +587,7 @@ export default {
507587
border-bottom-color: transparent;
508588
}
509589
510-
.nameIndicator {
511-
position: absolute;
512-
right: 20px;
513-
bottom: 12px;
514-
z-index: 1;
515-
}
516-
517-
.nameIndicator button {
590+
.buttons-bar button {
518591
background-color: transparent;
519592
border: none;
520593
margin: 0;
@@ -523,34 +596,34 @@ export default {
523596
background-size: 24px;
524597
}
525598
526-
.nameIndicator #screensharing-menu button {
599+
.buttons-bar #screensharing-menu button {
527600
width: 100%;
528601
height: auto;
529602
}
530603
531-
.nameIndicator button.audio-disabled,
532-
.nameIndicator button.video-disabled,
533-
.nameIndicator button.screensharing-disabled {
604+
.buttons-bar button.audio-disabled,
605+
.buttons-bar button.video-disabled,
606+
.buttons-bar button.screensharing-disabled {
534607
opacity: .7;
535608
}
536609
537-
.nameIndicator button.audio-disabled:not(.no-audio-available),
538-
.nameIndicator button.video-disabled:not(.no-video-available),
539-
.nameIndicator button.screensharing-disabled {
610+
.buttons-bar button.audio-disabled:not(.no-audio-available),
611+
.buttons-bar button.video-disabled:not(.no-video-available),
612+
.buttons-bar button.screensharing-disabled {
540613
&:hover,
541614
&:focus {
542615
opacity: 1;
543616
}
544617
}
545618
546-
.nameIndicator button.no-audio-available,
547-
.nameIndicator button.no-video-available {
619+
.buttons-bar button.no-audio-available,
620+
.buttons-bar button.no-video-available {
548621
opacity: .7;
549622
cursor: not-allowed;
550623
}
551624
552-
.nameIndicator button.no-audio-available:active,
553-
.nameIndicator button.no-video-available:active {
625+
.buttons-bar button.no-audio-available:active,
626+
.buttons-bar button.no-video-available:active {
554627
background-color: transparent;
555628
}
556629
@@ -585,11 +658,10 @@ export default {
585658
586659
.network-connection-state {
587660
position: absolute;
588-
bottom: 0;
589-
right: 16px;
661+
bottom: 3px;
662+
right: 45px;
590663
width: 32px;
591664
height: 32px;
592-
filter: drop-shadow(1px 1px 4px var(--color-box-shadow));
593665
}
594666
595667
.hint {
@@ -606,29 +678,4 @@ export default {
606678
height: $clickable-area;
607679
}
608680
}
609-
610-
.bottom-bar {
611-
position: absolute;
612-
bottom: 0;
613-
width: 100%;
614-
padding: 0 20px 12px 24px;
615-
display: flex;
616-
justify-content: center;
617-
align-items: center;
618-
height: 40px;
619-
&--big {
620-
justify-content: center;
621-
height: 48px;
622-
}
623-
&__button {
624-
opacity: 0.8;
625-
margin-left: 4px;
626-
border: none;
627-
&:hover,
628-
&:focus {
629-
opacity: 1;
630-
border: none;
631-
}
632-
}
633-
}
634681
</style>

0 commit comments

Comments
 (0)