From 879ace49c77552e408dbdf1e377e8ff4aa874448 Mon Sep 17 00:00:00 2001 From: Maksim Sukharev Date: Mon, 27 Jan 2025 17:34:47 +0100 Subject: [PATCH 1/3] fix(SpeakingWhileMutedWarner): add timeout to hide message in case of constant noise (7 seconds) - also hide message on destroy Signed-off-by: Maksim Sukharev --- src/utils/webrtc/SpeakingWhileMutedWarner.js | 64 ++++++++++++-------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/src/utils/webrtc/SpeakingWhileMutedWarner.js b/src/utils/webrtc/SpeakingWhileMutedWarner.js index 34100cb634b..e7115383005 100644 --- a/src/utils/webrtc/SpeakingWhileMutedWarner.js +++ b/src/utils/webrtc/SpeakingWhileMutedWarner.js @@ -3,36 +3,38 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { showWarning, TOAST_PERMANENT_TIMEOUT } from '@nextcloud/dialogs' +import { showWarning, TOAST_PERMANENT_TIMEOUT, TOAST_DEFAULT_TIMEOUT } from '@nextcloud/dialogs' import { t } from '@nextcloud/l10n' /** - * Helper to warn the user if they are talking while muted. - * - * The WebRTC helper emits events when it detects that the user is speaking - * while muted; this helper shows a warning to the user based on those - * events. - * - * The warning is not immediately shown, though; the WebRTC helper flags - * even short sounds as "speaking" (provided they are strong enough), so to - * prevent unnecesary warnings the user has to speak for a few seconds for - * the warning to be shown. On the other hand, the warning is hidden as soon - * as the WebRTC helper detects that the speaking has stopped; in this case - * there is no delay, as the helper itself has a delay before emitting the - * event. - * - * The way of warning the user changes depending on whether Talk is visible - * or not; if it is visible the warning is shown in the Talk UI, but if it - * is not it is shown using a browser notification, which will be visible - * to the user even if the browser window is not in the foreground (provided - * the user granted the permissions to receive notifications from the site). - * - * @param {object} LocalMediaModel the model that emits "speakingWhileMuted" - * events. - * "setSpeakingWhileMutedNotification" method. - */ + * Helper to warn the user if they are talking while muted. + * + * The WebRTC helper emits events when it detects that the user is speaking + * while muted; this helper shows a warning to the user based on those + * events. + * + * The warning is not immediately shown, though; the WebRTC helper flags + * even short sounds as "speaking" (provided they are strong enough), so to + * prevent unnecessary warnings the user has to speak for a few seconds for + * the warning to be shown. On the other hand, the warning is hidden as soon + * as the WebRTC helper detects that the speaking has stopped; in this case + * there is no delay, as the helper itself has a delay before emitting the + * event. + * + * The way of warning the user changes depending on whether Talk is visible + * or not; if it is visible the warning is shown in the Talk UI, but if it + * is not it is shown using a browser notification, which will be visible + * to the user even if the browser window is not in the foreground (provided + * the user granted the permissions to receive notifications from the site). + * + * @param {object} LocalMediaModel the model that emits "speakingWhileMuted" + * events. + */ export default function SpeakingWhileMutedWarner(LocalMediaModel) { this._model = LocalMediaModel + this._startedSpeakingTimeout = undefined + this._startedShowWarningTimeout = undefined + this._toast = null this._handleSpeakingWhileMutedChangeBound = this._handleSpeakingWhileMutedChange.bind(this) @@ -42,6 +44,7 @@ export default function SpeakingWhileMutedWarner(LocalMediaModel) { SpeakingWhileMutedWarner.prototype = { destroy() { + this._hideWarning() this._model.off('change:speakingWhileMuted', this._handleSpeakingWhileMutedChangeBound) }, @@ -86,6 +89,12 @@ SpeakingWhileMutedWarner.prototype = { } }.bind(this)) } + + this._startedShowWarningTimeout = setTimeout(function() { + delete this._startedShowWarningTimeout + + this._hideWarning() + }.bind(this), TOAST_DEFAULT_TIMEOUT) }, _showNotification(message) { @@ -159,6 +168,11 @@ SpeakingWhileMutedWarner.prototype = { this._browserNotification = null } + + if (this._startedShowWarningTimeout) { + clearTimeout(this._startedShowWarningTimeout) + delete this._startedShowWarningTimeout + } }, } From d7fe6413abe4874aa61be0c27d4db3d24b113086 Mon Sep 17 00:00:00 2001 From: Maksim Sukharev Date: Mon, 27 Jan 2025 17:36:57 +0100 Subject: [PATCH 2/3] fix(SpeakingWhileMutedWarner): replace toast message with popup Signed-off-by: Maksim Sukharev --- src/utils/webrtc/SpeakingWhileMutedWarner.js | 40 ++++++-------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/src/utils/webrtc/SpeakingWhileMutedWarner.js b/src/utils/webrtc/SpeakingWhileMutedWarner.js index e7115383005..484d207bcfb 100644 --- a/src/utils/webrtc/SpeakingWhileMutedWarner.js +++ b/src/utils/webrtc/SpeakingWhileMutedWarner.js @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { showWarning, TOAST_PERMANENT_TIMEOUT, TOAST_DEFAULT_TIMEOUT } from '@nextcloud/dialogs' +import { TOAST_DEFAULT_TIMEOUT } from '@nextcloud/dialogs' import { t } from '@nextcloud/l10n' /** @@ -35,7 +35,9 @@ export default function SpeakingWhileMutedWarner(LocalMediaModel) { this._startedSpeakingTimeout = undefined this._startedShowWarningTimeout = undefined - this._toast = null + /** Public properties to use in Vue components */ + this.message = t('spreed', 'You seem to be talking while muted, please unmute yourself for others to hear you') + this.showPopup = false this._handleSpeakingWhileMutedChangeBound = this._handleSpeakingWhileMutedChange.bind(this) @@ -74,18 +76,16 @@ SpeakingWhileMutedWarner.prototype = { }, _showWarning() { - const message = t('spreed', 'You seem to be talking while muted, please unmute yourself for others to hear you') - if (!document.hidden) { - this._showNotification(message) + this.showPopup = true } else { this._pendingBrowserNotification = true - this._showBrowserNotification(message).catch(function() { + this._showBrowserNotification().catch(function() { if (this._pendingBrowserNotification) { this._pendingBrowserNotification = false - this._showNotification(message) + this.showPopup = true } }.bind(this)) } @@ -97,23 +97,7 @@ SpeakingWhileMutedWarner.prototype = { }.bind(this), TOAST_DEFAULT_TIMEOUT) }, - _showNotification(message) { - if (this._toast) { - return - } - - this._toast = showWarning(message, { - timeout: TOAST_PERMANENT_TIMEOUT, - onClick: () => { - this._toast.hideToast() - }, - onRemove: () => { - this._toast = null - } - }) - }, - - _showBrowserNotification(message) { + _showBrowserNotification() { return new Promise(function(resolve, reject) { if (this._browserNotification) { resolve() @@ -136,7 +120,7 @@ SpeakingWhileMutedWarner.prototype = { if (Notification.permission === 'granted') { this._pendingBrowserNotification = false - this._browserNotification = new Notification(message) + this._browserNotification = new Notification(this.message) resolve() return @@ -146,7 +130,7 @@ SpeakingWhileMutedWarner.prototype = { if (permission === 'granted') { if (this._pendingBrowserNotification) { this._pendingBrowserNotification = false - this._browserNotification = new Notification(message) + this._browserNotification = new Notification(this.message) } resolve() } else { @@ -159,8 +143,8 @@ SpeakingWhileMutedWarner.prototype = { _hideWarning() { this._pendingBrowserNotification = false - if (this._toast) { - this._toast.hideToast() + if (this.showPopup) { + this.showPopup = false } if (this._browserNotification) { From aadd013028cd40b756ad6570ee0fd9d02ed7fd94 Mon Sep 17 00:00:00 2001 From: Maksim Sukharev Date: Mon, 27 Jan 2025 17:37:20 +0100 Subject: [PATCH 3/3] fix(LocalAudioControlButton): show popup when microphone is muted - detach logic from TopBar Signed-off-by: Maksim Sukharev --- .../shared/LocalAudioControlButton.vue | 94 ++++++++++++++++--- src/components/TopBar/TopBarMediaControls.vue | 9 -- 2 files changed, 81 insertions(+), 22 deletions(-) diff --git a/src/components/CallView/shared/LocalAudioControlButton.vue b/src/components/CallView/shared/LocalAudioControlButton.vue index 613b3e46ec2..27aea5620b6 100644 --- a/src/components/CallView/shared/LocalAudioControlButton.vue +++ b/src/components/CallView/shared/LocalAudioControlButton.vue @@ -4,39 +4,57 @@ -->