diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-03-11 11:32:04 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-03-18 13:40:17 +0000 |
commit | 31ccca0778db85c159634478b4ec7997f6704860 (patch) | |
tree | 3d33fc3afd9d5ec95541e1bbe074a9cf8da12a0e /chromium/chrome/browser/resources/tab_strip/alert_indicator.js | |
parent | 248b70b82a40964d5594eb04feca0fa36716185d (diff) |
BASELINE: Update Chromium to 80.0.3987.136
Change-Id: I98e1649aafae85ba3a83e67af00bb27ef301db7b
Reviewed-by: Jüri Valdmann <juri.valdmann@qt.io>
Diffstat (limited to 'chromium/chrome/browser/resources/tab_strip/alert_indicator.js')
-rw-r--r-- | chromium/chrome/browser/resources/tab_strip/alert_indicator.js | 178 |
1 files changed, 174 insertions, 4 deletions
diff --git a/chromium/chrome/browser/resources/tab_strip/alert_indicator.js b/chromium/chrome/browser/resources/tab_strip/alert_indicator.js index 2d41eab42f6..f2120ba7ec1 100644 --- a/chromium/chrome/browser/resources/tab_strip/alert_indicator.js +++ b/chromium/chrome/browser/resources/tab_strip/alert_indicator.js @@ -2,17 +2,187 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import './strings.m.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; + import {CustomElement} from './custom_element.js'; +import {TabAlertState} from './tabs_api_proxy.js'; + +/** @const {string} */ +const MAX_WIDTH = '16px'; + +/** + * @param {!TabAlertState} alertState + * @return {string} + */ +function getAriaLabel(alertState) { + // The existing labels for alert states currently expects to format itself + // using the title of the tab (eg. "Website - Audio is playing"). The WebUI + // tab strip will provide the title of the tab elsewhere outside of this + // element, so just provide an empty string as the title here. This also + // allows for multiple labels for the same title (eg. "Website - Audio is + // playing - VR is presenting"). + switch (alertState) { + case TabAlertState.MEDIA_RECORDING: + return loadTimeData.getStringF('mediaRecording', ''); + case TabAlertState.TAB_CAPTURING: + return loadTimeData.getStringF('tabCapturing', ''); + case TabAlertState.AUDIO_PLAYING: + return loadTimeData.getStringF('audioPlaying', ''); + case TabAlertState.AUDIO_MUTING: + return loadTimeData.getStringF('audioMuting', ''); + case TabAlertState.BLUETOOTH_CONNECTED: + return loadTimeData.getStringF('bluetoothConnected', ''); + case TabAlertState.USB_CONNECTED: + return loadTimeData.getStringF('usbConnected', ''); + case TabAlertState.SERIAL_CONNECTED: + return loadTimeData.getStringF('serialConnected', ''); + case TabAlertState.PIP_PLAYING: + return loadTimeData.getStringF('pipPlaying', ''); + case TabAlertState.DESKTOP_CAPTURING: + return loadTimeData.getStringF('desktopCapturing', ''); + case TabAlertState.VR_PRESENTING_IN_HEADSET: + return loadTimeData.getStringF('vrPresenting', ''); + default: + return ''; + } +} export class AlertIndicatorElement extends CustomElement { static get template() { return `{__html_template__}`; } - /** @override */ - remove() { - this.toggleAttribute('fade-out', true); - this.addEventListener('animationend', () => super.remove(), {once: true}); + constructor() { + super(); + + /** @private {!TabAlertState} */ + this.alertState_; + + /** @private {number} */ + this.fadeDurationMs_ = 125; + + /** + * An animation that is currently in-flight to fade the element in. + * @private {?Animation} + */ + this.fadeInAnimation_ = null; + + /** + * An animation that is currently in-flight to fade the element out. + * @private {?Animation} + */ + this.fadeOutAnimation_ = null; + + /** + * A promise that resolves when the fade out animation finishes or rejects + * if a fade out animation is canceled. + * @private {?Promise} + */ + this.fadeOutAnimationPromise_ = null; + } + + /** @return {!TabAlertState} */ + get alertState() { + return this.alertState_; + } + + /** @param {!TabAlertState} alertState */ + set alertState(alertState) { + this.setAttribute('alert-state_', alertState); + this.setAttribute('aria-label', getAriaLabel(alertState)); + this.alertState_ = alertState; + } + + /** @param {number} duration */ + overrideFadeDurationForTesting(duration) { + this.fadeDurationMs_ = duration; + } + + show() { + if (this.fadeOutAnimation_) { + // Cancel any fade out animations to prevent the element from fading out + // and being removed. At this point, the tab's alertStates have changed + // to a state in which this indicator should be visible. + this.fadeOutAnimation_.cancel(); + this.fadeOutAnimation_ = null; + this.fadeOutAnimationPromise_ = null; + } + + if (this.fadeInAnimation_) { + // If the element was already faded in, don't fade it in again + return; + } + + + if (this.alertState_ === TabAlertState.MEDIA_RECORDING || + this.alertState_ === TabAlertState.TAB_CAPTURING || + this.alertState_ === TabAlertState.DESKTOP_CAPTURING) { + // Fade in and out 2 times and then fade in + const totalDuration = 2600; + this.fadeInAnimation_ = this.animate( + [ + {opacity: 0, maxWidth: 0, offset: 0}, + {opacity: 1, maxWidth: MAX_WIDTH, offset: 200 / totalDuration}, + {opacity: 0, maxWidth: MAX_WIDTH, offset: 1200 / totalDuration}, + {opacity: 1, maxWidth: MAX_WIDTH, offset: 1400 / totalDuration}, + {opacity: 0, maxWidth: MAX_WIDTH, offset: 2400 / totalDuration}, + {opacity: 1, maxWidth: MAX_WIDTH, offset: 1}, + ], + { + duration: totalDuration, + easing: 'linear', + fill: 'forwards', + }); + } else { + this.fadeInAnimation_ = this.animate( + [ + {opacity: 0, maxWidth: 0}, + {opacity: 1, maxWidth: MAX_WIDTH}, + ], + { + duration: this.fadeDurationMs_, + fill: 'forwards', + }); + } + } + + /** @return {!Promise} */ + hide() { + if (this.fadeInAnimation_) { + // Cancel any fade in animations to prevent the element from fading in. At + // this point, the tab's alertStates have changed to a state in which this + // indicator should not be visible. + this.fadeInAnimation_.cancel(); + this.fadeInAnimation_ = null; + } + + if (this.fadeOutAnimationPromise_) { + return this.fadeOutAnimationPromise_; + } + + this.fadeOutAnimationPromise_ = new Promise((resolve, reject) => { + this.fadeOutAnimation_ = this.animate( + [ + {opacity: 1, maxWidth: MAX_WIDTH}, + {opacity: 0, maxWidth: 0}, + ], + { + duration: this.fadeDurationMs_, + fill: 'forwards', + }); + this.fadeOutAnimation_.addEventListener('cancel', () => { + reject(); + }); + this.fadeOutAnimation_.addEventListener('finish', () => { + this.remove(); + this.fadeOutAnimation_ = null; + this.fadeOutAnimationPromise_ = null; + resolve(); + }); + }); + + return this.fadeOutAnimationPromise_; } } |