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"
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'
136128import Tooltip from ' @nextcloud/vue/dist/Directives/Tooltip'
137129import SpeakingWhileMutedWarner from ' ../../../utils/webrtc/SpeakingWhileMutedWarner'
138130import NetworkStrength2Alert from ' vue-material-design-icons/NetworkStrength2Alert'
131+ import { callAnalyzer } from ' ../../../utils/webrtc/index'
132+ import { CONNECTION_QUALITY } from ' ../../../utils/webrtc/analyzers/PeerConnectionAnalyzer'
139133
140134export 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 : 16 px ;
661+ bottom : 3 px ;
662+ right : 45 px ;
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