From 7e2fe30472c51d553ec26bbd99be49dcbc488d56 Mon Sep 17 00:00:00 2001 From: hristoterezov Date: Thu, 27 Oct 2016 13:19:11 -0500 Subject: [PATCH 1/2] feat(JitsiLocalStorage): Implement localStorage wrapper --- connection.js | 5 +- modules/UI/UI.js | 7 +- modules/UI/videolayout/RemoteVideo.js | 20 +++-- modules/settings/Settings.js | 108 +++++++++++--------------- modules/util/JitsiLocalStorage.js | 64 +++++++++++++++ 5 files changed, 124 insertions(+), 80 deletions(-) create mode 100644 modules/util/JitsiLocalStorage.js diff --git a/connection.js b/connection.js index 94f73e5e4..81ecec3de 100644 --- a/connection.js +++ b/connection.js @@ -1,5 +1,6 @@ /* global APP, JitsiMeetJS, config */ import AuthHandler from './modules/UI/authentication/AuthHandler'; +import jitsiLocalStorage from './modules/util/JitsiLocalStorage'; const ConnectionEvents = JitsiMeetJS.events.connection; const ConnectionErrors = JitsiMeetJS.errors.connection; @@ -107,9 +108,9 @@ function connect(id, password, roomName) { export function openConnection({id, password, retry, roomName}) { let usernameOverride - = window.localStorage.getItem("xmpp_username_override"); + = jitsiLocalStorage.getItem("xmpp_username_override"); let passwordOverride - = window.localStorage.getItem("xmpp_password_override"); + = jitsiLocalStorage.getItem("xmpp_password_override"); if (usernameOverride && usernameOverride.length > 0) { id = usernameOverride; diff --git a/modules/UI/UI.js b/modules/UI/UI.js index 76a919988..be00bd1c8 100644 --- a/modules/UI/UI.js +++ b/modules/UI/UI.js @@ -31,6 +31,7 @@ var messageHandler = UI.messageHandler; var JitsiPopover = require("./util/JitsiPopover"); var Feedback = require("./feedback/Feedback"); import FollowMe from "../FollowMe"; +import jitsiLocalStorage from '../util/JitsiLocalStorage'; var eventEmitter = new EventEmitter(); UI.eventEmitter = eventEmitter; @@ -1239,7 +1240,7 @@ UI.showDeviceErrorDialog = function (micError, cameraError) { } if (showDoNotShowWarning) { - if (window.localStorage[localStoragePropName] === "true") { + if (jitsiLocalStorage.getItem(localStoragePropName) === "true") { return; } } @@ -1308,8 +1309,8 @@ UI.showDeviceErrorDialog = function (micError, cameraError) { let input = form.find("#doNotShowWarningAgain"); if (input.length) { - window.localStorage[localStoragePropName] = - input.prop("checked"); + jitsiLocalStorage.setItem(localStoragePropName, + input.prop("checked")); } } }, diff --git a/modules/UI/videolayout/RemoteVideo.js b/modules/UI/videolayout/RemoteVideo.js index 1a918b1a3..c51578724 100644 --- a/modules/UI/videolayout/RemoteVideo.js +++ b/modules/UI/videolayout/RemoteVideo.js @@ -6,6 +6,7 @@ import SmallVideo from "./SmallVideo"; import UIUtils from "../util/UIUtil"; import UIEvents from '../../../service/UI/UIEvents'; import JitsiPopover from "../util/JitsiPopover"; +import jitsiLocalStorage from '../../util/JitsiLocalStorage'; const MUTED_DIALOG_BUTTON_VALUES = { cancel: 0, @@ -654,8 +655,7 @@ RemoteVideo.createContainer = function (spanId) { RemoteVideo.showMuteParticipantDialog = function () { //FIXME: don't show again checkbox is implemented very dirty. we should add // this functionality to MessageHandler class. - if (window.localStorage - && window.localStorage.getItem( + if (jitsiLocalStorage.getItem( "dontShowMuteParticipantDialog") === "true") { return Promise.resolve(MUTED_DIALOG_BUTTON_VALUES.muted); } @@ -672,15 +672,13 @@ RemoteVideo.showMuteParticipantDialog = function () { msgString, leftButtonKey: 'dialog.muteParticipantButton', submitFunction: () => { - if(window.localStorage) { - let form = $.prompt.getPrompt(); - if (form) { - let input = form.find("#doNotShowMessageAgain"); - if (input.length) { - window.localStorage.setItem( - "dontShowMuteParticipantDialog", - input.prop("checked")); - } + let form = $.prompt.getPrompt(); + if (form) { + let input = form.find("#doNotShowMessageAgain"); + if (input.length) { + jitsiLocalStorage.setItem( + "dontShowMuteParticipantDialog", + input.prop("checked")); } } resolve(MUTED_DIALOG_BUTTON_VALUES.muted); diff --git a/modules/settings/Settings.js b/modules/settings/Settings.js index ac1b7293d..66368b34f 100644 --- a/modules/settings/Settings.js +++ b/modules/settings/Settings.js @@ -1,26 +1,6 @@ /* global JitsiMeetJS */ - import UIUtil from '../UI/util/UIUtil'; - -let email = ''; -let avatarId = ''; -let displayName = ''; -let language = null; -let cameraDeviceId = ''; -let micDeviceId = ''; -let welcomePageDisabled = false; -let localFlipX = null; -let avatarUrl = ''; - -function supportsLocalStorage() { - try { - return 'localStorage' in window && window.localStorage !== null; - } catch (e) { - console.log("localstorage is not supported"); - return false; - } -} - +import jitsiLocalStorage from '../util/JitsiLocalStorage'; function generateUniqueId() { function _p8() { @@ -29,45 +9,43 @@ function generateUniqueId() { return _p8() + _p8() + _p8() + _p8(); } -if (supportsLocalStorage()) { - if (!window.localStorage.jitsiMeetId) { - window.localStorage.jitsiMeetId = generateUniqueId(); - console.log("generated id", window.localStorage.jitsiMeetId); - } +if (!jitsiLocalStorage.getItem("jitsiMeetId")) { + jitsiLocalStorage.setItem("jitsiMeetId",generateUniqueId()); + console.log("generated id", jitsiLocalStorage.getItem("jitsiMeetId")); +} - email = UIUtil.unescapeHtml(window.localStorage.email || ''); - avatarId = UIUtil.unescapeHtml(window.localStorage.avatarId || ''); - if (!avatarId) { - // if there is no avatar id, we generate a unique one and use it forever - avatarId = generateUniqueId(); - window.localStorage.avatarId = avatarId; - } +let avatarUrl = ''; - localFlipX = JSON.parse(window.localStorage.localFlipX || true); - displayName = UIUtil.unescapeHtml(window.localStorage.displayname || ''); - language = window.localStorage.language; - cameraDeviceId = window.localStorage.cameraDeviceId || ''; - micDeviceId = window.localStorage.micDeviceId || ''; - welcomePageDisabled = JSON.parse( - window.localStorage.welcomePageDisabled || false - ); +let email = UIUtil.unescapeHtml(jitsiLocalStorage.getItem("email") || ''); +let avatarId = UIUtil.unescapeHtml(jitsiLocalStorage.getItem("avatarId") || ''); +if (!avatarId) { + // if there is no avatar id, we generate a unique one and use it forever + avatarId = generateUniqueId(); + jitsiLocalStorage.setItem("avatarId", avatarId); +} - // Currently audio output device change is supported only in Chrome and - // default output always has 'default' device ID - var audioOutputDeviceId = window.localStorage.audioOutputDeviceId - || 'default'; +let localFlipX = JSON.parse(jitsiLocalStorage.getItem("localFlipX") || true); +let displayName = UIUtil.unescapeHtml( + jitsiLocalStorage.getItem("displayname") || ''); +let language = jitsiLocalStorage.getItem("language"); +let cameraDeviceId = jitsiLocalStorage.getItem("cameraDeviceId") || ''; +let micDeviceId = jitsiLocalStorage.getItem("micDeviceId") || ''; +let welcomePageDisabled = JSON.parse( + jitsiLocalStorage.getItem("welcomePageDisabled") || false); - if (audioOutputDeviceId !== - JitsiMeetJS.mediaDevices.getAudioOutputDevice()) { - JitsiMeetJS.mediaDevices.setAudioOutputDevice(audioOutputDeviceId) - .catch((ex) => { - console.warn('Failed to set audio output device from local ' + - 'storage. Default audio output device will be used' + - 'instead.', ex); - }); - } -} else { - console.log("local storage is not supported"); +// Currently audio output device change is supported only in Chrome and +// default output always has 'default' device ID +let audioOutputDeviceId = jitsiLocalStorage.getItem("audioOutputDeviceId") + || 'default'; + +if (audioOutputDeviceId !== + JitsiMeetJS.mediaDevices.getAudioOutputDevice()) { + JitsiMeetJS.mediaDevices.setAudioOutputDevice(audioOutputDeviceId) + .catch((ex) => { + console.warn('Failed to set audio output device from local ' + + 'storage. Default audio output device will be used' + + 'instead.', ex); + }); } export default { @@ -82,7 +60,8 @@ export default { displayName = newDisplayName; if (!disableLocalStore) - window.localStorage.displayname = UIUtil.escapeHtml(displayName); + jitsiLocalStorage.setItem("displayname", + UIUtil.escapeHtml(displayName)); }, /** @@ -102,7 +81,7 @@ export default { email = newEmail; if (!disableLocalStore) - window.localStorage.email = UIUtil.escapeHtml(newEmail); + jitsiLocalStorage.setItem("email", UIUtil.escapeHtml(newEmail)); }, /** @@ -142,7 +121,7 @@ export default { }, setLanguage: function (lang) { language = lang; - window.localStorage.language = lang; + jitsiLocalStorage.setItem("language", lang); }, /** @@ -151,7 +130,7 @@ export default { */ setLocalFlipX: function (val) { localFlipX = val; - window.localStorage.localFlipX = val; + jitsiLocalStorage.setItem("localFlipX", val); }, /** @@ -179,7 +158,7 @@ export default { setCameraDeviceId: function (newId, store) { cameraDeviceId = newId; if (store) - window.localStorage.cameraDeviceId = newId; + jitsiLocalStorage.setItem("cameraDeviceId", newId); }, /** @@ -199,7 +178,7 @@ export default { setMicDeviceId: function (newId, store) { micDeviceId = newId; if (store) - window.localStorage.micDeviceId = newId; + jitsiLocalStorage.setItem("micDeviceId", newId); }, /** @@ -218,7 +197,8 @@ export default { */ setAudioOutputDeviceId: function (newId = 'default') { return JitsiMeetJS.mediaDevices.setAudioOutputDevice(newId) - .then(() => window.localStorage.audioOutputDeviceId = newId); + .then(() => + jitsiLocalStorage.setItem("audioOutputDeviceId", newId)); }, /** @@ -235,6 +215,6 @@ export default { */ setWelcomePageEnabled (enabled) { welcomePageDisabled = !enabled; - window.localStorage.welcomePageDisabled = welcomePageDisabled; + jitsiLocalStorage.setItem("welcomePageDisabled", welcomePageDisabled); } }; diff --git a/modules/util/JitsiLocalStorage.js b/modules/util/JitsiLocalStorage.js new file mode 100644 index 000000000..4aa60ec5e --- /dev/null +++ b/modules/util/JitsiLocalStorage.js @@ -0,0 +1,64 @@ +/** + * Dummy implementation of Storage interface with empty methods. + */ +class DummyLocalStorage { + /** + * Empty function + */ + getItem() { } + + /** + * Empty function + */ + setItem() { } + + /** + * Empty function + */ + removeItem() { } +} + +/** + * Wrapper class for browser's local storage object. + */ +class JitsiLocalStorage extends DummyLocalStorage { + /** + * @constructor + * @param {Storage} storage browser's local storage object. + */ + constructor(storage) { + super(); + this.storage = storage || new DummyLocalStorage(); + } + + /** + * Returns that passed key's value. + * @param {string} keyName the name of the key you want to retrieve + * the value of. + * @returns {String|null} the value of the key. If the key does not exist, + * null is returned. + */ + getItem(keyName) { + return this.storage.getItem(keyName); + } + + /** + * Adds a key to the storage, or update key's value if it already exists. + * @param {string} keyName the name of the key you want to create/update. + * @param {string} keyValue the value you want to give the key you are + * creating/updating. + */ + setItem(keyName, keyValue) { + return this.storage.setItem(keyName, keyValue); + } + + /** + * Remove a key from the storage. + * @param {string} keyName the name of the key you want to remove. + */ + removeItem(keyName) { + return this.storage.removeItem(keyName); + } +} + +export default new JitsiLocalStorage(window.localStorage); From a8b69d5cd8495825cd92e6ede793353bcdd259d8 Mon Sep 17 00:00:00 2001 From: hristoterezov Date: Thu, 27 Oct 2016 18:31:00 -0500 Subject: [PATCH 2/2] feat(MessageHandler): Implement dont show again utility --- modules/UI/UI.js | 41 ++------ modules/UI/util/MessageHandler.js | 144 ++++++++++++++++++++++++-- modules/UI/videolayout/RemoteVideo.js | 35 ++----- 3 files changed, 152 insertions(+), 68 deletions(-) diff --git a/modules/UI/UI.js b/modules/UI/UI.js index be00bd1c8..99b437e8b 100644 --- a/modules/UI/UI.js +++ b/modules/UI/UI.js @@ -31,7 +31,6 @@ var messageHandler = UI.messageHandler; var JitsiPopover = require("./util/JitsiPopover"); var Feedback = require("./feedback/Feedback"); import FollowMe from "../FollowMe"; -import jitsiLocalStorage from '../util/JitsiLocalStorage'; var eventEmitter = new EventEmitter(); UI.eventEmitter = eventEmitter; @@ -1215,7 +1214,11 @@ UI.showExtensionExternalInstallationDialog = function (url) { * @param {JitsiTrackError} cameraError */ UI.showDeviceErrorDialog = function (micError, cameraError) { - let localStoragePropName = "doNotShowErrorAgain"; + let dontShowAgain = { + id: "doNotShowWarningAgain", + localStorageKey: "doNotShowErrorAgain", + textKey: "dialog.doNotShowWarningAgain" + }; let isMicJitsiTrackErrorAndHasName = micError && micError.name && micError instanceof JitsiMeetJS.errorTypes.JitsiTrackError; let isCameraJitsiTrackErrorAndHasName = cameraError && cameraError.name && @@ -1232,17 +1235,11 @@ UI.showDeviceErrorDialog = function (micError, cameraError) { } if (micError) { - localStoragePropName += "-mic-" + micError.name; + dontShowAgain.localStorageKey += "-mic-" + micError.name; } if (cameraError) { - localStoragePropName += "-camera-" + cameraError.name; - } - - if (showDoNotShowWarning) { - if (jitsiLocalStorage.getItem(localStoragePropName) === "true") { - return; - } + dontShowAgain.localStorageKey += "-camera-" + cameraError.name; } let cameraJitsiTrackErrorMsg = cameraError @@ -1267,12 +1264,6 @@ UI.showDeviceErrorDialog = function (micError, cameraError) { micError.message ? `
${micError.message}
` : ``; - let doNotShowWarningAgainSection = showDoNotShowWarning - ? `` - : ``; let message = ''; if (micError) { @@ -1291,8 +1282,6 @@ UI.showDeviceErrorDialog = function (micError, cameraError) { ${additionalCameraErrorMsg}`; } - message = `${message}${doNotShowWarningAgainSection}`; - // To make sure we don't have multiple error dialogs open at the same time, // we will just close the previous one if we are going to show a new one. deviceErrorDialog && deviceErrorDialog.close(); @@ -1302,24 +1291,14 @@ UI.showDeviceErrorDialog = function (micError, cameraError) { message, false, {Ok: true}, - function () { - let form = $.prompt.getPrompt(); - - if (form) { - let input = form.find("#doNotShowWarningAgain"); - - if (input.length) { - jitsiLocalStorage.setItem(localStoragePropName, - input.prop("checked")); - } - } - }, + function () {}, null, function () { // Reset dialog reference to null to avoid memory leaks when // user closed the dialog manually. deviceErrorDialog = null; - } + }, + showDoNotShowWarning ? dontShowAgain : undefined ); function getTitleKey() { diff --git a/modules/UI/util/MessageHandler.js b/modules/UI/util/MessageHandler.js index 54c996cea..2f63abbf4 100644 --- a/modules/UI/util/MessageHandler.js +++ b/modules/UI/util/MessageHandler.js @@ -1,6 +1,7 @@ /* global $, APP, toastr, Impromptu */ import UIUtil from './UIUtil'; +import jitsiLocalStorage from '../../util/JitsiLocalStorage'; /** * Flag for enable/disable of the notifications. @@ -20,6 +21,91 @@ let popupEnabled = true; */ let twoButtonDialog = null; +/** + * Generates html for dont show again checkbox. + * @param {object} options options + * @param {string} options.id the id of the checkbox. + * @param {string} options.textKey the key for the text displayed next to + * checkbox + * @param {boolean} options.checked if true the checkbox is foing to be checked + * by default. + * @returns {string} + */ +function generateDontShowCheckbox(options) { + if(!isDontShowAgainEnabled(options)) { + return ""; + } + + let checked + = (options.checked === true) ? "checked" : ""; + return `
+ `; +} + +/** + * Checks whether the dont show again checkbox was checked before. + * @param {object} options - options for dont show again checkbox. + * @param {string} options.id the id of the checkbox. + * @param {string} options.localStorageKey the key for the local storage. if + * not provided options.id will be used. + * @returns {boolean} true if the dialog mustn't be displayed and + * false otherwise. + */ +function dontShowTheDialog(options) { + if(isDontShowAgainEnabled(options)) { + if(jitsiLocalStorage.getItem(options.localStorageKey || options.id) + === "true") { + return true; + } + } + return false; +} + +/** + * Wraps the submit function to process the dont show again status and store + * it. + * @param {object} options - options for dont show again checkbox. + * @param {string} options.id the id of the checkbox. + * @param {Array} options.buttonValues The button values that will trigger + * storing he checkbox value + * @param {string} options.localStorageKey the key for the local storage. if + * not provided options.id will be used. + * @param {Function} submitFunction the submit function to be wrapped + * @returns {Function} wrapped function + */ +function dontShowAgainSubmitFunctionWrapper(options, submitFunction) { + if(isDontShowAgainEnabled(options)) { + return (...args) => { + console.debug(args, options.buttonValues); + //args[1] is the value associated with the pressed button + if(!options.buttonValues || options.buttonValues.length === 0 + || options.buttonValues.indexOf(args[1]) !== -1 ) { + let checkbox = $(`#${options.id}`); + if (checkbox.length) { + jitsiLocalStorage.setItem( + options.localStorageKey || options.id, + checkbox.prop("checked")); + } + } + submitFunction(...args); + }; + } else { + return submitFunction; + } +} + +/** + * Check whether dont show again checkbox is enabled or not. + * @param {object} options - options for dont show again checkbox. + * @returns {boolean} true if enabled and false if not. + */ +function isDontShowAgainEnabled(options) { + return typeof options === "object"; +} + var messageHandler = { OK: "dialog.OK", CANCEL: "dialog.Cancel", @@ -72,6 +158,16 @@ var messageHandler = { * the dialog is opened * @param defaultButton index of default button which will be activated when * the user press 'enter'. Indexed from 0. + * @param {object} dontShowAgain - options for dont show again checkbox. + * @param {string} dontShowAgain.id the id of the checkbox. + * @param {string} dontShowAgain.textKey the key for the text displayed + * next to checkbox + * @param {boolean} dontShowAgain.checked if true the checkbox is foing to + * be checked + * @param {Array} dontShowAgain.buttonValues The button values that will + * trigger storing the checkbox value + * @param {string} dontShowAgain.localStorageKey the key for the local + * storage. if not provided dontShowAgain.id will be used. * @return the prompt that was created, or null */ openTwoButtonDialog: function(options) { @@ -87,12 +183,20 @@ var messageHandler = { size, defaultButton, wrapperClass, - classes + classes, + dontShowAgain } = options; if (!popupEnabled || twoButtonDialog) return null; + if(dontShowTheDialog(dontShowAgain)) { + // Maybe we should pass some parameters here? I'm not sure + // and currently we don't need any parameters. + submitFunction(); + return null; + } + var buttons = []; var leftButton = leftButtonKey ? @@ -108,6 +212,7 @@ var messageHandler = { if (msgKey) { message = APP.translation.generateTranslationHTML(msgKey); } + message += generateDontShowCheckbox(dontShowAgain); classes = classes || this._getDialogClasses(size); if (wrapperClass) { classes.prompt += ` ${wrapperClass}`; @@ -122,13 +227,13 @@ var messageHandler = { loaded: loadedFunction, promptspeed: 0, classes, - submit: function (e, v, m, f) { - twoButtonDialog = null; - if (v){ - if (submitFunction) + submit: dontShowAgainSubmitFunctionWrapper(dontShowAgain, + function (e, v, m, f) { + twoButtonDialog = null; + if (v && submitFunction) { submitFunction(e, v, m, f); - } - }, + } + }), close: function (e, v, m, f) { twoButtonDialog = null; if (closeFunction) { @@ -155,12 +260,29 @@ var messageHandler = { * @param loadedFunction function to be called after the prompt is fully * loaded * @param closeFunction function to be called on dialog close + * @param {object} dontShowAgain - options for dont show again checkbox. + * @param {string} dontShowAgain.id the id of the checkbox. + * @param {string} dontShowAgain.textKey the key for the text displayed + * next to checkbox + * @param {boolean} dontShowAgain.checked if true the checkbox is foing to + * be checked + * @param {Array} dontShowAgain.buttonValues The button values that will + * trigger storing the checkbox value + * @param {string} dontShowAgain.localStorageKey the key for the local + * storage. if not provided dontShowAgain.id will be used. */ openDialog: function (titleKey, msgString, persistent, buttons, - submitFunction, loadedFunction, closeFunction) { + submitFunction, loadedFunction, closeFunction, dontShowAgain) { if (!popupEnabled) return; + if(dontShowTheDialog(dontShowAgain)) { + // Maybe we should pass some parameters here? I'm not sure + // and currently we don't need any parameters. + submitFunction(); + return; + } + let args = { title: this._getFormattedTitleString(titleKey), persistent: persistent, @@ -168,7 +290,8 @@ var messageHandler = { defaultButton: 1, promptspeed: 0, loaded: loadedFunction, - submit: submitFunction, + submit: dontShowAgainSubmitFunctionWrapper( + dontShowAgain, submitFunction), close: closeFunction, classes: this._getDialogClasses() }; @@ -177,7 +300,8 @@ var messageHandler = { args.closeText = ''; } - let dialog = new Impromptu(msgString, args); + let dialog = new Impromptu( + msgString + generateDontShowCheckbox(dontShowAgain), args); APP.translation.translateElement(dialog.getPrompt()); return dialog; }, diff --git a/modules/UI/videolayout/RemoteVideo.js b/modules/UI/videolayout/RemoteVideo.js index c51578724..43ea0bbc3 100644 --- a/modules/UI/videolayout/RemoteVideo.js +++ b/modules/UI/videolayout/RemoteVideo.js @@ -6,7 +6,6 @@ import SmallVideo from "./SmallVideo"; import UIUtils from "../util/UIUtil"; import UIEvents from '../../../service/UI/UIEvents'; import JitsiPopover from "../util/JitsiPopover"; -import jitsiLocalStorage from '../../util/JitsiLocalStorage'; const MUTED_DIALOG_BUTTON_VALUES = { cancel: 0, @@ -653,36 +652,18 @@ RemoteVideo.createContainer = function (spanId) { * participant. */ RemoteVideo.showMuteParticipantDialog = function () { - //FIXME: don't show again checkbox is implemented very dirty. we should add - // this functionality to MessageHandler class. - if (jitsiLocalStorage.getItem( - "dontShowMuteParticipantDialog") === "true") { - return Promise.resolve(MUTED_DIALOG_BUTTON_VALUES.muted); - } - let msgString = - `
-
- `; return new Promise(resolve => { APP.UI.messageHandler.openTwoButtonDialog({ titleKey : "dialog.muteParticipantTitle", - msgString, - leftButtonKey: 'dialog.muteParticipantButton', - submitFunction: () => { - let form = $.prompt.getPrompt(); - if (form) { - let input = form.find("#doNotShowMessageAgain"); - if (input.length) { - jitsiLocalStorage.setItem( - "dontShowMuteParticipantDialog", - input.prop("checked")); - } - } - resolve(MUTED_DIALOG_BUTTON_VALUES.muted); + msgString: "
", + leftButtonKey: "dialog.muteParticipantButton", + dontShowAgain: { + id: "dontShowMuteParticipantDialog", + textKey: "dialog.doNotShowMessageAgain", + checked: true, + buttonValues: [true] }, + submitFunction: () => resolve(MUTED_DIALOG_BUTTON_VALUES.muted), closeFunction: () => resolve(MUTED_DIALOG_BUTTON_VALUES.cancel) }); });