Bug 1392157 - Implement new page loading indicator animation, part 2: add a "burst" when loading finishes. r?jaws
MozReview-Commit-ID: 6TUmwfcZXv0
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -720,16 +720,24 @@
this.mTabBrowser.mIsBusy = true;
}
}
} else if (aStateFlags & nsIWebProgressListener.STATE_STOP &&
aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
if (this.mTab.hasAttribute("busy")) {
this.mTab.removeAttribute("busy");
+
+ // Only animate the "burst" indicating the page has loaded if
+ // the top-level page is the one that finished loading.
+ if (aWebProgress.isTopLevel && !aWebProgress.isLoadingDocument &&
+ Services.prefs.getBoolPref("toolkit.cosmeticAnimations.enabled")) {
+ this.mTab.animateLoadingBurst();
+ }
+
this.mTabBrowser._tabAttrModified(this.mTab, ["busy"]);
if (!this.mTab.selected)
this.mTab.setAttribute("unread", "true");
}
this.mTab.removeAttribute("progress");
if (aWebProgress.isTopLevel) {
let isSuccessful = Components.isSuccessCode(aStatus);
@@ -7350,16 +7358,19 @@
<xul:stack class="tab-stack" flex="1">
<xul:vbox xbl:inherits="selected=visuallyselected,fadein"
class="tab-background">
<xul:hbox xbl:inherits="selected=visuallyselected"
class="tab-line"/>
<xul:spacer flex="1"/>
<xul:hbox class="tab-bottom-line"/>
</xul:vbox>
+ <xul:hbox xbl:inherits="pinned,bursting"
+ anonid="tab-loading-burst"
+ class="tab-loading-burst"/>
<xul:hbox xbl:inherits="pinned,selected=visuallyselected,titlechanged,attention"
class="tab-content" align="center">
<xul:hbox xbl:inherits="fadein,pinned,busy,progress,selected=visuallyselected"
class="tab-throbber"
layer="true"/>
<xul:image xbl:inherits="src=image,loadingprincipal=iconLoadingPrincipal,fadein,pinned,selected=visuallyselected,busy,crashed,sharing"
anonid="tab-icon-image"
class="tab-icon-image"
@@ -7636,16 +7647,28 @@
</method>
<method name="finishMediaBlockTimer">
<body><![CDATA[
TelemetryStopwatch.finish("TAB_MEDIA_BLOCKING_TIME_MS", this);
]]></body>
</method>
+ <method name="animateLoadingBurst">
+ <body><![CDATA[
+ if (this.hasAttribute("bursting")) {
+ // Stop the animation if it's already playing so we can restart it.
+ this.removeAttribute("bursting");
+ let burst = document.getAnonymousElementByAttribute(this, "anonid", "tab-loading-burst");
+ window.getComputedStyle(burst).animationName;
+ }
+ this.setAttribute("bursting", "true");
+ ]]></body>
+ </method>
+
<method name="toggleMuteAudio">
<parameter name="aMuteReason"/>
<body>
<![CDATA[
// Do not attempt to toggle mute state if browser is lazy.
if (!this.linkedPanel) {
return;
}
@@ -7743,16 +7766,24 @@
return;
}
if (this._overPlayingIcon) {
this.toggleMuteAudio();
}
]]>
</handler>
+ <handler event="animationend">
+ <![CDATA[
+ let anonid = event.originalTarget.getAttribute("anonid");
+ if (anonid == "tab-loading-burst") {
+ this.removeAttribute("bursting");
+ }
+ ]]>
+ </handler>
</handlers>
</binding>
<binding id="tabbrowser-alltabs-popup"
extends="chrome://global/content/bindings/popup.xml#popup">
<implementation implements="nsIDOMEventListener">
<method name="_tabOnAttrModified">
<parameter name="aEvent"/>
--- a/browser/themes/shared/jar.inc.mn
+++ b/browser/themes/shared/jar.inc.mn
@@ -186,16 +186,17 @@
skin/classic/browser/badge-add-engine.png (../shared/search/badge-add-engine.png)
skin/classic/browser/badge-add-engine@2x.png (../shared/search/badge-add-engine@2x.png)
skin/classic/browser/search-indicator-badge-add.png (../shared/search/search-indicator-badge-add.png)
skin/classic/browser/search-indicator-badge-add@2x.png (../shared/search/search-indicator-badge-add@2x.png)
skin/classic/browser/search-indicator-magnifying-glass.svg (../shared/search/search-indicator-magnifying-glass.svg)
skin/classic/browser/search-arrow-go.svg (../shared/search/search-arrow-go.svg)
skin/classic/browser/gear.svg (../shared/search/gear.svg)
skin/classic/browser/tabbrowser/loading.svg (../shared/tabbrowser/loading.svg)
+ skin/classic/browser/tabbrowser/loading-burst.svg (../shared/tabbrowser/loading-burst.svg)
skin/classic/browser/tabbrowser/crashed.svg (../shared/tabbrowser/crashed.svg)
skin/classic/browser/tabbrowser/newtab.svg (../shared/tabbrowser/newtab.svg)
skin/classic/browser/tabbrowser/indicator-tab-attention.svg (../shared/tabbrowser/indicator-tab-attention.svg)
skin/classic/browser/tabbrowser/pendingpaint.png (../shared/tabbrowser/pendingpaint.png)
skin/classic/browser/tabbrowser/tab-audio-playing.svg (../shared/tabbrowser/tab-audio-playing.svg)
skin/classic/browser/tabbrowser/tab-audio-muted.svg (../shared/tabbrowser/tab-audio-muted.svg)
skin/classic/browser/tabbrowser/tab-audio-blocked.svg (../shared/tabbrowser/tab-audio-blocked.svg)
skin/classic/browser/tabbrowser/tab-audio-small.svg (../shared/tabbrowser/tab-audio-small.svg)
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/tabbrowser/loading-burst.svg
@@ -0,0 +1,6 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
+ <circle cx="5" cy="5" r="5" fill="context-fill"/>
+</svg>
--- a/browser/themes/shared/tabs.inc.css
+++ b/browser/themes/shared/tabs.inc.css
@@ -57,16 +57,62 @@
.tab-content {
padding: 0 @horizontalTabPadding@;
}
.tab-content[pinned] {
padding: 0 12px;
}
+.tab-loading-burst {
+ position: relative;
+ overflow: hidden;
+}
+
+.tab-loading-burst::before {
+ position: absolute;
+ content: "";
+ /* We set the width to be a percentage of the tab's width so that we can use
+ the `scale` transform to scale it up to the full size of the tab when the
+ burst occurs. We also need to set the margin-inline-start so that the
+ center of the burst matches the center of the favicon. */
+ width: 5%;
+ height: 100%;
+ /* Center the burst over the .tab-loading-burst; it's 9px from the edge thanks
+ to .tab-content, plus 8px more since .tab-loading-burst is 16px wide. */
+ margin-inline-start: calc(17px - 2.5%);
+}
+
+.tab-loading-burst[pinned]::before {
+ /* This is like the margin-inline-start rule above, except that icons for
+ pinned tabs are 12px from the edge. */
+ margin-inline-start: calc(20px - 2.5%);
+}
+
+.tab-loading-burst[bursting]::before {
+ background-image: url("chrome://browser/skin/tabbrowser/loading-burst.svg");
+ background-position: center center;
+ background-size: 100% auto;
+ background-repeat: no-repeat;
+ animation: tab-burst-animation 1.8s var(--animation-easing-function);
+ -moz-context-properties: fill;
+ fill: var(--tab-loading-fill);
+}
+
+@keyframes tab-burst-animation {
+ 0% {
+ opacity: 0.4;
+ transform: scale(1);
+ }
+ 100% {
+ opacity: 0;
+ transform: scale(40);
+ }
+}
+
.tab-throbber,
.tab-icon-image,
.tab-sharing-icon-overlay,
.tab-icon-sound,
.tab-close-button {
margin-top: 1px;
}