Bug 1387557 - Transition to fatter progressbar. r=mikedeboer
* Pre-rendered animations to transition to the fatter progressbar
* Frames of the indicator graphic in the notifier replace and overlay the button indicator, so that we can control the ease-in of the progressbar and transition of the arrow from an attention state
* Forward selected attributes to the notifier element to drive animation behavior & specifics
* Transition from not-downloading to downloading state in the notifier, revealing the indicator when the animation complete
* Animate the transition from attention=success to none with a pre-rendered svg animation
MozReview-Commit-ID: BDguf62lTyt
--- a/browser/components/downloads/content/indicator.js
+++ b/browser/components/downloads/content/indicator.js
@@ -1,14 +1,15 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
/* eslint-env mozilla/browser-window */
+/* globals CustomizableUI, DownloadsCommon, browserDragAndDrop, gNavToolbox */
/**
* Handles the indicator that displays the progress of ongoing downloads, which
* is also used as the anchor for the downloads panel.
*
* This module includes the following constructors and global objects:
*
* DownloadsButton
@@ -22,18 +23,16 @@
* Builds and updates the actual downloads status widget, responding to changes
* in the global status data, or provides a neutral view if the indicator is
* removed from the toolbars and only used as a temporary anchor. In addition,
* handles the user interaction events raised by the widget.
*/
"use strict";
-Components.utils.import("resource://gre/modules/AppConstants.jsm");
-
// DownloadsButton
/**
* Main entry point for the downloads indicator. Depending on how the toolbars
* have been customized, this object determines if we should show a fully
* functional indicator, a placeholder used during customization and in the
* customization palette, or a neutral view as a temporary anchor for the
* downloads panel.
@@ -146,16 +145,19 @@ const DownloadsButton = {
let button = this._placeholder;
if (!button && includePalette) {
button = gNavToolbox.palette.querySelector("#downloads-button");
}
if (button && button.hasAttribute("hidden")) {
button.removeAttribute("hidden");
if (this._navBar.contains(button)) {
this._navBar.setAttribute("downloadsbuttonshown", "true");
+ if (DownloadsCommon.animateNotifications) {
+ button.setAttribute("animateunhiding", "true");
+ }
}
}
},
hide() {
let button = this._placeholder;
if (this.autoHideDownloadsButton && button && button.closest("toolbar")) {
DownloadsPanel.hidePanel();
@@ -420,61 +422,100 @@ const DownloadsIndicatorView = {
// The notification element is positioned to show in the same location as
// the downloads button. It's not in the downloads button itself in order to
// be able to anchor the notification elsewhere if required, and to ensure
// the notification isn't clipped by overflow properties of the anchor's
// container.
// Note: no notifier animation for download finished in Photon
let notifier = this.notifier;
+ // This value is determined by the overall duration of animation in CSS.
+ let animationDuration = aType == "start" ? 760 : 850;
+ this._currentNotificationType = aType;
+
+ // This value is determined by the overall duration of animation in CSS.
if (aType == "start") {
// Show the notifier before measuring for size/placement. Being hidden by default
// avoids the interference with scrolling/APZ when the notifier element is
// tall enough to overlap the tabbrowser element
notifier.removeAttribute("hidden");
- // the anchor height may vary if font-size is changed or
- // compact/tablet mode is selected so recalculate this each time
- let anchorRect = anchor.getBoundingClientRect();
- let notifierRect = notifier.getBoundingClientRect();
- let topDiff = anchorRect.top - notifierRect.top;
- let leftDiff = anchorRect.left - notifierRect.left;
- let heightDiff = anchorRect.height - notifierRect.height;
- let widthDiff = anchorRect.width - notifierRect.width;
- let translateX = (leftDiff + .5 * widthDiff) + "px";
- let translateY = (topDiff + .5 * heightDiff) + "px";
- notifier.style.transform = "translate(" + translateX + ", " + translateY + ")";
- notifier.setAttribute("notification", aType);
- }
- anchor.setAttribute("notification", aType);
+ requestAnimationFrame(() => {
+ // The anchor height may vary if font-size is changed or
+ // compact/tablet mode is selected so recalculate this each time
+ let anchorRect = anchor.getBoundingClientRect();
+ let notifierRect = notifier.getBoundingClientRect();
- let animationDuration;
- // This value is determined by the overall duration of animation in CSS.
- animationDuration = aType == "start" ? 760 : 850;
+ let topDiff = anchorRect.top - notifierRect.top;
+ let leftDiff = anchorRect.left - notifierRect.left;
+ let heightDiff = anchorRect.height - notifierRect.height;
+ let widthDiff = anchorRect.width - notifierRect.width;
+ let translateX = (leftDiff + .5 * widthDiff) + "px";
+ let translateY = (topDiff + .5 * heightDiff) + "px";
+
+ // Forward selected attributes onto the notification element which will
+ // animate in the space over the downloads button
+
+ // Did the button just get un-hidden?
+ if (anchor.hasAttribute("animateunhiding")) {
+ notifier.setAttribute("animateunhiding", "true");
+ }
- this._currentNotificationType = aType;
-
- setTimeout(() => {
- requestAnimationFrame(() => {
- notifier.setAttribute("hidden", "true");
- notifier.removeAttribute("notification");
- notifier.style.transform = "";
- anchor.removeAttribute("notification");
+ // Is the button in the overflow menu?
+ if (widget.overflowed) {
+ notifier.setAttribute("overflowed", "true");
+ }
+ // Is a previous download already in-progress?
+ if (anchor.hasAttribute("progress") &&
+ !anchor.hasAttribute("startprogress")) {
+ notifier.setAttribute("progress", "true");
+ } else if (this._attention !== DownloadsCommon.ATTENTION_NONE) {
+ // The indicator was in an attention state when download started.
+ notifier.setAttribute("attention", "true");
+ }
+ notifier.style.transform = "translate(" + translateX + ", " + translateY + ")";
+ notifier.setAttribute("notification", aType);
+ anchor.setAttribute("notification", aType);
- requestAnimationFrame(() => {
- let nextType = this._nextNotificationType;
- this._currentNotificationType = null;
- this._nextNotificationType = null;
- if (nextType) {
- this._showNotification(nextType);
- }
- });
+ setTimeout(() => {
+ requestAnimationFrame(() => this._showNotificationEnd(anchor, notifier));
+ }, animationDuration);
});
- }, animationDuration);
+ } else {
+ anchor.setAttribute("notification", aType);
+ setTimeout(() => {
+ requestAnimationFrame(() => this._showNotificationEnd(anchor));
+ }, animationDuration);
+ }
+ },
+
+ _showNotificationEnd(anchor, notifier) {
+ if (notifier) {
+ // Clear the attributes forwarded from the indicator earlier.
+ notifier.setAttribute("hidden", "true");
+ notifier.removeAttribute("notification");
+ notifier.removeAttribute("overflowed");
+ notifier.removeAttribute("progress");
+ notifier.removeAttribute("attention");
+ notifier.removeAttribute("animateunhiding");
+ notifier.style.transform = "";
+ }
+ anchor.removeAttribute("notification");
+ anchor.removeAttribute("startprogress");
+ anchor.removeAttribute("animateunhiding");
+
+ requestAnimationFrame(() => {
+ let nextType = this._nextNotificationType;
+ this._currentNotificationType = null;
+ this._nextNotificationType = null;
+ if (nextType) {
+ this._showNotification(nextType);
+ }
+ });
},
// Callback functions from DownloadsIndicatorData
/**
* Indicates whether the indicator should be shown because there are some
* downloads to be displayed.
*/
@@ -502,22 +543,29 @@ const DownloadsIndicatorView = {
* Progress indication to display, from 0 to 100, or -1 if unknown.
* Progress is not visible if the current progress is unknown.
*/
set percentComplete(aValue) {
if (!this._operational) {
return this._percentComplete;
}
- if (this._percentComplete !== aValue) {
+ let previousValue = this._percentComplete;
+ if (previousValue !== aValue) {
this._percentComplete = aValue;
this._refreshAttention();
if (this._percentComplete >= 0) {
this.indicator.setAttribute("progress", "true");
+ // Setter may be called before showEventNotification
+ // so mark the element when a new download begins.
+ // Attribute will be removed when the notification ends.
+ if (previousValue < 0 && DownloadsCommon.animateNotifications) {
+ this.indicator.setAttribute("startprogress", "true");
+ }
// For arrow type only:
// We set animationDelay to a minus value (0s ~ -100s) to show the
// corresponding frame needed for progress.
this._progressIcon.style.animationDelay = (-this._percentComplete) + "s";
} else {
this.indicator.removeAttribute("progress");
this._progressIcon.style.animationDelay = "1s";
}
@@ -546,22 +594,35 @@ const DownloadsIndicatorView = {
let widgetGroup = CustomizableUI.getWidget("downloads-button");
let inMenu = widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL;
// For arrow-Styled indicator, suppress success attention if we have
// progress in toolbar
let suppressAttention = !inMenu &&
this._attention == DownloadsCommon.ATTENTION_SUCCESS &&
this._percentComplete >= 0;
+ let hadAttention = this.indicator.hasAttribute("attention");
if (suppressAttention || this._attention == DownloadsCommon.ATTENTION_NONE) {
this.indicator.removeAttribute("attention");
} else {
this.indicator.setAttribute("attention", this._attention);
}
+ if (!inMenu && hadAttention && DownloadsCommon.animateNotifications &&
+ this._attention == DownloadsCommon.ATTENTION_NONE) {
+ let indicator = this.indicator;
+ indicator.setAttribute("animateindicator", "true");
+ indicator.addEventListener("animationend", function animListener(event) {
+ if (event.animationName == "downloads-attention-transition" &&
+ indicator.hasAttribute("animateindicator")) {
+ indicator.removeAttribute("animateindicator");
+ indicator.removeEventListener("animationend", animListener);
+ }
+ });
+ }
},
_attention: DownloadsCommon.ATTENTION_NONE,
// User interface event functions
onWindowUnload() {
// This function is registered as an event listener, we can't use "this".
DownloadsIndicatorView.ensureTerminated();
--- a/browser/components/downloads/content/indicatorOverlay.xul
+++ b/browser/components/downloads/content/indicatorOverlay.xul
@@ -24,11 +24,14 @@
state changes, otherwise the panel could change its position or lose
its arrow unexpectedly. -->
<stack id="downloads-indicator-anchor"
consumeanchor="downloads-button">
<box id="downloads-indicator-icon"/>
<stack id="downloads-indicator-progress-outer">
<box id="downloads-indicator-progress-inner"/>
</stack>
+ <hbox id="downloads-indicator-animatable-box">
+ <image id="downloads-indicator-animatable-image"/>
+ </hbox>
</stack>
</toolbarbutton>
</overlay>
--- a/browser/themes/shared/downloads/download-icons.svg
+++ b/browser/themes/shared/downloads/download-icons.svg
@@ -6,19 +6,18 @@
:root > use:not(:target),
:root > g:not(:target) {
display: none;
}
</style>
<defs>
<path id="arrow-icon" d="M7.293 12.725a1 1 0 0 0 1.414 0l5-5a1 1 0 0 0-1.414-1.413L9 9.605V1.019a1 1 0 0 0-2 0v8.586L3.707 6.312a1 1 0 0 0-1.414 1.413l5 5z"/>
<path id="short-bar-icon" d="m 13,14 a 1,1 0 1 1 0,2 h -10 a 1,1 0 1 1 0,-2 z"/>
- <path id="long-bar-icon" d="m 14,14 a 1,1 0 1 1 0,2 h -12 a 1,1 0 1 1 0,-2"/>
+ <path id="long-bar-icon" d="M14.193 13.32h-13a1.35 1.35 0 0 0 0 2.7h13a1.35 1.35 0 0 0 0 -2.7z"/>
</defs>
<use id="arrow" fill="context-fill" fill-opacity="context-fill-opacity" href="#arrow-icon"/>
<g id="arrow-with-bar" fill="context-fill" fill-opacity="context-fill-opacity">
<use href="#arrow-icon"/>
<use href="#short-bar-icon"/>
</g>
<use id="default-bar" fill="context-fill" fill-opacity="context-fill-opacity" href="#short-bar-icon"/>
- <use id="progress-bar-bg" fill="context-fill" fill-opacity="0.2" href="#long-bar-icon"/>
- <use id="progress-bar-fg" fill="context-fill" fill-opacity="context-fill-opacity" href="#long-bar-icon"/>
+ <use id="progress-bar" fill="context-fill" fill-opacity="context-fill-opacity" href="#long-bar-icon"/>
</svg>
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/downloads/faux-indicator-animation.svg
@@ -0,0 +1,98 @@
+<!-- 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 xmlns="http://www.w3.org/2000/svg" width="1260" height="98">
+ <defs>
+ <path id="indicator" d="M25.692 55h-9.629a1 1 0 0 0 0 2h9.629a1 1 0 0 0 0 -2zm-5.399 -1.275a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025 0.999 0.999 0 0 0 0 1.388l5 5z"/>
+ </defs>
+ <svg x="0">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="42">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="84">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="126">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="168">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="210">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="252">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="294">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="336">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="378">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="420">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="462">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="504">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="546">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="588">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="630">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="672">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="714">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="756">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="798">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="840">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="882">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="924">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="966">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="1008">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="1050">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="1092">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="1134">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="1176">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+ <svg x="1218">
+ <use fill="context-stroke" href="#indicator"/>
+ </svg>
+</svg>
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/downloads/indicator-state-transition.svg
@@ -0,0 +1,51 @@
+<!-- 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 xmlns="http://www.w3.org/2000/svg" width="128" height="16">
+ <svg width="16" height="16">
+ <path fill="context-stroke" d="M7.364 11.41a.9.9 0 0 0 1.272 0l4.5-4.5a.9.9 0 0 0-1.273-1.272L8.9 8.603V.875a.9.9 0 0 0-1.8 0v7.727L4.136 5.64a.9.9 0 0 0-1.273 1.27l4.5 4.5z"/>
+ <path fill="context-stroke" d="M14.318 13.352H1.32a1.35 1.35 0 0 0 0 2.7h13a1.35 1.35 0 0 0 0-2.7z"/>
+ </svg>
+ <svg width="16" height="16" x="16">
+ <path fill="context-stroke" d="M7.364 11.41a.9.9 0 0 0 1.272 0l4.5-4.5a.9.9 0 0 0-1.273-1.272L8.9 8.603V.875a.9.9 0 0 0-1.8 0v7.727L4.136 5.64a.9.9 0 0 0-1.272 1.27l4.5 4.5z"/>
+ <path fill="context-stroke" d="M14.318 13.352H1.32a1.35 1.35 0 0 0 0 2.7h13a1.35 1.35 0 0 0 0-2.7z"/>
+ </svg>
+ <svg width="16" height="16" x="32">
+ <path fill="context-fill" fill-opacity=".074" d="M7.352 11.545a.917.917 0 0 0 1.296 0l4.583-4.583a.917.917 0 0 0-1.296-1.295L8.917 8.684V.815a.917.917 0 0 0-1.834 0v7.87L4.065 5.666a.916.916 0 0 0-1.296 1.296l4.583 4.583z"/>
+ <path fill="context-stroke" fill-opacity=".926" d="M7.358 11.5a.908.908 0 0 0 1.284 0l4.537-4.536a.907.907 0 0 0-1.283-1.282L8.907 8.67V.879a.908.908 0 0 0-1.814 0v7.79L4.104 5.683a.907.907 0 0 0-1.283 1.282L7.358 11.5z"/>
+ <path fill="context-fill" fill-opacity=".074" d="M14.047 13.465H1.609a1.292 1.292 0 0 0 0 2.584h12.438a1.292 1.292 0 0 0 0-2.584z"/>
+ <path fill="context-stroke" fill-opacity=".926" d="M14.047 13.465H1.609a1.292 1.292 0 0 0 0 2.584h12.438a1.292 1.292 0 0 0 0-2.584z"/>
+ </svg>
+ <svg width="16" height="16" x="48">
+ <path fill="context-fill" fill-opacity=".259" d="M7.34 11.762a.934.934 0 0 0 1.32 0l4.667-4.666a.933.933 0 0 0-1.32-1.319L8.933 8.85V.837a.934.934 0 0 0-1.866 0V8.85L3.993 5.777a.932.932 0 0 0-1.32 1.319l4.667 4.666z"/>
+ <path fill="context-stroke" fill-opacity=".741" d="M7.345 11.727a.927.927 0 0 0 1.31 0l4.63-4.63a.926.926 0 0 0-1.31-1.308l-3.05 3.049V.888a.926.926 0 0 0-1.85 0v7.95l-3.05-3.05a.925.925 0 0 0-1.31 1.31l4.63 4.629z"/>
+ <path fill="context-fill" fill-opacity=".259" d="M13.776 13.579H1.9a1.233 1.233 0 0 0 0 2.466h11.876a1.233 1.233 0 0 0 0-2.466z"/>
+ <path fill="context-stroke" fill-opacity=".741" d="M13.776 13.579H1.9a1.233 1.233 0 0 0 0 2.466h11.876a1.233 1.233 0 0 0 0-2.466z"/>
+ </svg>
+ <svg width="16" height="16" x="64">
+ <path fill="context-fill" fill-opacity=".5" d="M7.328 12.021a.95.95 0 0 0 1.344 0l4.75-4.75a.95.95 0 0 0-1.343-1.342L8.95 9.057V.9a.95.95 0 0 0-1.9 0v8.157L3.922 5.93a.95.95 0 0 0-1.344 1.34l4.75 4.75z"/>
+ <path fill="context-stroke" fill-opacity=".5" d="M7.328 12.02a.95.95 0 0 0 1.344 0l4.75-4.75a.95.95 0 0 0-1.343-1.342L8.95 9.057V.9a.95.95 0 0 0-1.9 0v8.157L3.922 5.928a.95.95 0 0 0-1.344 1.343l4.75 4.75z"/>
+ <path fill="context-fill" fill-opacity=".5" d="M13.505 13.692H2.191a1.175 1.175 0 0 0 0 2.35h11.314a1.175 1.175 0 0 0 0-2.35z"/>
+ <path fill="context-stroke" fill-opacity=".5" d="M13.505 13.692H2.191a1.175 1.175 0 0 0 0 2.35h11.314a1.175 1.175 0 0 0 0-2.35z"/>
+ </svg>
+ <svg width="16" height="16" x="80">
+ <path fill="context-fill" fill-opacity=".741" d="M7.317 12.28a.967.967 0 0 0 1.366 0l4.834-4.833A.967.967 0 0 0 12.15 6.08L8.967 9.264v-8.3a.967.967 0 0 0-1.934 0v8.3L3.85 6.081a.966.966 0 0 0-1.367 1.366l4.834 4.833z"/>
+ <path fill="context-stroke" fill-opacity=".259" d="M7.311 12.314c.381.38.997.38 1.378 0l4.87-4.87a.974.974 0 0 0-1.377-1.376L8.974 9.275V.912a.974.974 0 0 0-1.948 0v8.363L3.818 6.068a.973.973 0 0 0-1.377 1.376l4.87 4.87z"/>
+ <path fill="context-fill" fill-opacity=".741" d="M13.234 13.805H2.482a1.117 1.117 0 0 0 0 2.234h10.752a1.117 1.117 0 0 0 0-2.234z"/>
+ <path fill="context-stroke" fill-opacity=".259" d="M13.234 13.805H2.482a1.117 1.117 0 0 0 0 2.234h10.752a1.117 1.117 0 0 0 0-2.234z"/>
+ </svg>
+ <svg width="16" height="16" x="96">
+ <path fill="context-fill" fill-opacity=".926" d="M7.305 12.497a.984.984 0 0 0 1.39 0l4.917-4.916a.983.983 0 0 0-1.39-1.39L8.982 9.43V.987a.984.984 0 0 0-1.966 0v8.442L3.779 6.191a.982.982 0 0 0-1.39 1.39l4.916 4.916z"/>
+ <path fill="context-stroke" fill-opacity=".074" d="M7.298 12.54a.993.993 0 0 0 1.404 0l4.963-4.962a.993.993 0 0 0-1.404-1.403L8.993 9.444V.92a.993.993 0 0 0-1.986 0v8.523L3.74 6.175a.992.992 0 0 0-1.404 1.403l4.963 4.962z"/>
+ <path fill="context-fill" fill-opacity=".926" d="M12.963 13.919H2.772a1.058 1.058 0 0 0 0 2.116h10.19a1.058 1.058 0 0 0 0-2.116z"/>
+ <path fill="context-stroke" fill-opacity=".074" d="M12.963 13.919H2.772a1.058 1.058 0 0 0 0 2.116h10.19a1.058 1.058 0 0 0 0-2.116z"/>
+ </svg>
+ <svg width="16" height="16" x="112">
+ <path fill="context-fill" d="M7.293 12.631a1 1 0 0 0 1.414 0l5-5a1 1 0 0 0-1.414-1.413L9 9.511V.925a1 1 0 0 0-2 0v8.586L3.707 6.218a1 1 0 0 0-1.414 1.413l5 5z"/>
+ <path fill="context-fill" d="M12.692 14.032H3.063a1 1 0 0 0 0 2h9.629a1 1 0 0 0 0-2z"/>
+ </svg>
+ <svg width="16" height="16" x="128">
+ <path fill="context-stroke" d="M7.364 11.41a.9.9 0 0 0 1.272 0l4.5-4.5a.9.9 0 0 0-1.273-1.272L8.9 8.603V.875a.9.9 0 0 0-1.8 0v7.727L4.136 5.64a.9.9 0 0 0-1.273 1.27l4.5 4.5z"/>
+ <path fill="context-stroke" d="M14.318 13.352H1.32a1.35 1.35 0 0 0 0 2.7h13a1.35 1.35 0 0 0 0-2.7z"/>
+ </svg>
+</svg>
--- a/browser/themes/shared/downloads/indicator.inc.css
+++ b/browser/themes/shared/downloads/indicator.inc.css
@@ -4,46 +4,65 @@
/*** Status and progress indicator ***/
#downloads-indicator-anchor {
min-width: 16px;
min-height: 16px;
}
+#downloads-indicator-icon {
+ -moz-context-properties: fill, fill-opacity;
+ background-image: url("chrome://browser/skin/downloads/download-icons.svg#arrow"),
+ url("chrome://browser/skin/downloads/inprogress-arrow.svg");
+ background-size: 16px, 0px;
+ fill-opacity: 1;
+ width: 16px;
+ height: 16px;
+}
+
+#downloads-button[attention="success"] > #downloads-indicator-anchor > #downloads-indicator-icon {
+ background-size: 0px, 16px;
+ fill: var(--toolbarbutton-icon-fill-attention);
+}
+
+/* show the smaller arrow when downloading. */
+#downloads-button[progress] > #downloads-indicator-anchor > #downloads-indicator-icon {
+ background-size: 0px, 16px;
+}
+
#downloads-indicator-progress-outer {
width: 16px;
height: 16px;
background-size: 16px;
- background: url("chrome://browser/skin/downloads/download-icons.svg#default-bar") center no-repeat;
+ background-repeat: no-repeat;
+ background-position: center;
+ -moz-context-properties: fill, fill-opacity;
+ fill-opacity: 1;
+ background-image: url("chrome://browser/skin/downloads/download-icons.svg#default-bar");
}
-#downloads-button[attention="success"] > #downloads-indicator-anchor > #downloads-indicator-icon,
-#downloads-button[attention="success"] > #downloads-indicator-anchor > #downloads-indicator-progress-outer {
- -moz-context-properties: fill, fill-opacity;
+/* show the fatter progressbar when downloading and on successful download */
+#downloads-button[attention="success"] #downloads-indicator-progress-outer {
+ background-image: url("chrome://browser/skin/downloads/download-icons.svg#progress-bar");
fill: var(--toolbarbutton-icon-fill-attention);
- fill-opacity: 1;
}
-#downloads-button[progress] > #downloads-indicator-anchor > #downloads-indicator-progress-outer {
- background: url("chrome://browser/skin/downloads/download-icons.svg#progress-bar-bg") center no-repeat;
-}
-
-#downloads-indicator-icon {
- -moz-context-properties: fill, fill-opacity;
- background-image: url("chrome://browser/skin/downloads/download-icons.svg#arrow");
- width: 16px;
- height: 16px;
+#downloads-button[progress] #downloads-indicator-progress-outer {
+ background-image: url("chrome://browser/skin/downloads/download-icons.svg#progress-bar");
+ fill-opacity: 0.2;
}
#downloads-indicator-progress-inner {
- background: url("chrome://browser/skin/downloads/download-icons.svg#progress-bar-fg") left no-repeat;
+ background: url("chrome://browser/skin/downloads/download-icons.svg#progress-bar") left no-repeat;
margin-right: 16px;
- -moz-context-properties: fill;
+ -moz-context-properties: fill, fill-opacity;
+ fill-opacity: 1;
fill: var(--toolbarbutton-icon-fill-attention);
background-size: 16px;
+
/* From javascript side we use animation delay from 0s to -100s to show
* corresponding frames needed for progress.
* animation-delay is set to a positive value to make nothing shown.
*/
animation-play-state: paused;
animation-delay: 1s;
animation-duration: 100s;
animation-timing-function: linear;
@@ -52,16 +71,33 @@
#downloads-indicator-progress-inner:-moz-locale-dir(rtl) {
background-position: right;
animation-name: indicatorArrowProgressRTL;
margin-left: 16px;
margin-right: 0;
}
+/* When a download starts (and animated notifications are enabled) we'll hide
+ the indicator while the notification plays.
+ startprogress is set when a download first starts and is removed when the notification ends.
+ If a download was already in progress, we do want to show it
+ Note: sometimes download progress/attention is set before the notification event,
+ othertimes not.
+ */
+#downloads-button[startprogress] #downloads-indicator-anchor,
+#downloads-button[notification="start"] #downloads-indicator-anchor {
+ visibility: hidden;
+}
+
+#downloads-button:not([startprogress])[progress] #downloads-indicator-anchor,
+#downloads-button[notification="start"]:not([startprogress])[progress] #downloads-indicator-anchor {
+ visibility: visible;
+}
+
@keyframes indicatorArrowProgress {
0% {
margin-right: 15px;
}
100% {
margin-right: 1px;
}
}
@@ -70,16 +106,67 @@
0% {
margin-left: 15px;
}
100% {
margin-left: 1px;
}
}
+@keyframes downloads-attention-transition {
+ 0% { transform: translateX(0px); }
+ 100% { transform: translateX(-112px); }
+}
+
+#downloads-button[animateindicator],
+#downloads-button[startprogress] {
+ fill: transparent;
+}
+
+#downloads-indicator-animatable-box {
+ overflow: hidden;
+ min-width: 16px;
+ min-height: 16px;
+ max-width: 16px;
+ max-height: 16px;
+ visibility: hidden;
+ list-style-image: none;
+ /* animation is not directional and shouldn't be reversed in RTL */
+ direction: ltr;
+}
+
+#downloads-button[animateindicator] #downloads-indicator-animatable-box {
+ visibility: visible;
+}
+#downloads-button[animateindicator] > #downloads-indicator-anchor > #downloads-indicator-icon,
+#downloads-button[animateindicator] > #downloads-indicator-anchor > #downloads-indicator-progress-outer {
+ visibility: hidden;
+}
+
+#downloads-indicator-animatable-image {
+ background-image: url(chrome://browser/skin/downloads/indicator-state-transition.svg);
+ background-repeat: no-repeat;
+ background-position: left center;
+ min-width: 128px;
+ max-width: 128px;
+ min-height: 16px;
+ max-height: 16px;
+ -moz-context-properties: fill, stroke;
+ stroke: var(--toolbarbutton-icon-fill-attention);
+ fill: currentColor;
+}
+
+/* play an animation when the button changes from attention to none state */
+#downloads-button:not([notification])[animateindicator] #downloads-indicator-animatable-image {
+ animation-name: downloads-attention-transition;
+ animation-duration: 116.67ms;
+ animation-timing-function: steps(7);
+ animation-fill-mode: forwards;
+}
+
/*** Status badges ***/
#downloads-button[attention="warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
#downloads-button[attention="severe"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
display: -moz-box;
height: 8px;
width: 8px;
min-width: 0;
@@ -104,43 +191,50 @@
#downloads-button[attention="severe"] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive,
#downloads-button[attention="warning"] > .toolbarbutton-badge-stack > .toolbarbutton-badge:-moz-window-inactive {
filter: none;
}
/*** Download notifications ***/
-#downloads-button[notification="start"] > #downloads-indicator-anchor > #downloads-indicator-icon {
- animation-name: downloadsIndicatorStartDip;
- /* Upon changing the duration_delay below, please keep the delay time of
- setTimeout() identical in indicator.js for this animation.
+/* We distinguish between 3 scenarios:
+ Download indicator not currently in toolbar, e.g. first download of the session
+ Indicator in toolbar, no download currently in progress
+ Download already in progress
+*/
- Timing here needs to align with the animation on #downloads-indicator-notification
- */
- animation-duration: 360ms;
- animation-delay: 400ms;
- animation-iteration-count: 1;
+@keyframes downloadsNotifierArrowDropIndicatorDip {
+ from {
+ transform: translateX(0);
+ }
+ to {
+ transform: translateX(-1722px);
+ }
}
-@keyframes downloadsIndicatorStartDip {
- 0% {
- transform: translateY(0);
- animation-timing-function: linear;
+@keyframes downloadsNotifierArrowDrop {
+ from {
+ transform: translateX(0);
+ }
+ to {
+ transform: translateX(-1218px);
}
- 50% {
- transform: translateY(0);
- animation-timing-function: ease-out;
+}
+
+/*
+ To ensure the indicator is made visible in the correct frame, we use an
+ animation run in parallel with the start notifications (downloadsNotifierArrowDrop_ animations
+*/
+@keyframes downloadsIndicatorAppear {
+ 0% {
+ visibility: hidden;
}
- 88% {
- transform: translateY(3px);
- animation-timing-function: ease-out;
- }
- 100% {
- transform: translateY(0);
+ 99.9% {
+ visibility: visible;
}
}
@keyframes downloadsIndicatorFinishPulse {
from { transform: scale(1); }
37.5% { transform: scale(1.4); animation-timing-function: ease-out; }
to { transform: scale(1); animation-timing-function: ease-in; }
}
@@ -176,32 +270,59 @@
max-height: 98px;
overflow: hidden;
/* animation is not directional and shouldn't be reversed in RTL */
direction: ltr;
}
#downloads-indicator-notification {
opacity: 0;
- min-width: 1344px;
+ min-width: 1764px; /* The full combined width of the svg filmstrip images */
height: 98px; /* Height is equal to height of each frame in the SVG animation */
- -moz-context-properties: fill;
- fill: #737373;
+ -moz-context-properties: fill, stroke;
+ fill: #494949;
+ stroke: #494949;
+ /* Preload the animation images */
+ background-image: url('chrome://browser/skin/downloads/notification-start-animation.svg'), /* the arrow-drop animation */
+ url('chrome://browser/skin/downloads/progressbar-start-animation.svg'), /* the ease-in of the progressbar on first use */
+ url('chrome://browser/skin/downloads/faux-indicator-animation.svg'); /* a static indicator animation to replace a real one during the animation */
+ background-size: 0px, 0px, 0px;
+ background-repeat: no-repeat;
+ background-position: 0 center;
+}
+
+#downloads-notification-anchor[attention] > #downloads-indicator-notification {
+ stroke: var(--toolbarbutton-icon-fill-attention);
}
-@keyframes downloadsIndicatorNotificationStart {
- from {
- transform: translateX(0);
- }
- to {
- transform: translateX(-1302px);
- }
+/* download starts - first of the session */
+#downloads-notification-anchor[notification="start"][animateunhiding] > #downloads-indicator-notification {
+ opacity: 1;
+ /* show notifier arrow, progressbar ease-in */
+ background-size: 1764px 98px, 1260px 98px, 0 0;
+ animation-name: downloadsNotifierArrowDropIndicatorDip;
+ animation-duration: 0.683s;
+ animation-timing-function: steps(41);
+ animation-fill-mode: forwards;
}
+/* download starts, no download current in-progress */
#downloads-notification-anchor[notification="start"] > #downloads-indicator-notification {
opacity: 1;
- background: url("chrome://browser/skin/downloads/notification-start-animation.svg") 0 center no-repeat;
+ /* show notifier arrow and indicator replacement */
+ background-size: 1764px 98px, 0 0, 1260px 98px;
+ animation-name: downloadsNotifierArrowDropIndicatorDip;
+ animation-duration: 0.683s;
+ animation-timing-function: steps(41);
+}
+
+/* download starts, download already in-progress
+ or download button in overflow menu */
+#downloads-notification-anchor[progress][notification="start"] > #downloads-indicator-notification,
+#downloads-notification-anchor[overflowed][notification="start"] > #downloads-indicator-notification {
+ opacity: 1;
+ /* just show notifier arrow - the first 29 frames of notification-start-animation.svg */
+ background-size: 1764px 98px, 0 0, 0 0;
transform: translateX(0px);
- animation-name: downloadsIndicatorNotificationStart;
- animation-duration: 540ms;
- animation-delay: 64ms;
- animation-timing-function: steps(31);
+ animation-name: downloadsNotifierArrowDrop;
+ animation-timing-function: steps(29);
+ animation-duration: 0.483s;
}
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/downloads/inprogress-arrow.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 xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+ <path fill="context-fill" d="M7.24 11.4a .900,.900 0 0 0 1.27 0l4.50-4.50a .900,.900 0 0 0-1.27-1.27l-2.96 2.96v-7.73a .900,.900 0 0 0-1.80 0v7.73l-2.96-2.96a .900,.900 0 0 0-1.27 .0200a .900,.900 0 0 0 0 1.25l4.50 4.50z"/>
+</svg>
--- a/browser/themes/shared/downloads/notification-start-animation.svg
+++ b/browser/themes/shared/downloads/notification-start-animation.svg
@@ -1,95 +1,159 @@
<!-- 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 xmlns="http://www.w3.org/2000/svg" width="1344" height="98">
- <svg width="42" height="98"/>
- <svg width="42" height="98" x="42"/>
+<svg xmlns="http://www.w3.org/2000/svg" width="1764" height="98">
+ <defs>
+ <clipPath id="f30_animationMask_558KQGBcMr">
+ <path d="M0 0h42v59h-42z"/>
+ </clipPath>
+ <clipPath id="f30_uW1U4lQV3i">
+ <path fill="#fff" d="M1.688 14v2h12.373v-2h-12.373"/>
+ </clipPath>
+ <path id="notifyarrow" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z"/>
+ <path id="indicatorarrow" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025 0.999 0.999 0 0 0 0 1.388l5 5z"/>
+ <path id="bar" d="M4.629 -1h-9.629a1 1 0 0 0 0 2h9.629a1 1 0 0 0 0 -2z"/>
+ </defs>
+ <svg width="42" height="98" x="0"/>
+ <svg width="42" height="98" x="42">
+ <use fill="context-fill" fill-opacity=".257" href="#notifyarrow" transform="translate(21.018 22.854) scale(3.50932)"/>
+ </svg>
<svg width="42" height="98" x="84">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" opacity=".333" transform="translate(21.018 22.854) scale(3.50932)"/>
+ <use fill="context-fill" fill-opacity=".52" href="#notifyarrow" transform="translate(21.017 23.815) scale(3.41419)"/>
</svg>
<svg width="42" height="98" x="126">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" opacity=".667" transform="translate(21.017 23.815) scale(3.41419)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.017 24.798) scale(3.31695)"/>
</svg>
<svg width="42" height="98" x="168">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.017 24.798) scale(3.31695)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.016 25.793) scale(3.21855)"/>
</svg>
<svg width="42" height="98" x="210">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.016 25.793) scale(3.21855)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.016 26.795) scale(3.11952)"/>
</svg>
<svg width="42" height="98" x="252">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.016 26.795) scale(3.11952)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.015 27.8) scale(3.02017)"/>
</svg>
<svg width="42" height="98" x="294">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.015 27.8) scale(3.02017)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.015 28.805) scale(2.92072)"/>
</svg>
<svg width="42" height="98" x="336">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.015 28.805) scale(2.92072)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.014 29.81) scale(2.82134)"/>
</svg>
<svg width="42" height="98" x="378">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.014 29.81) scale(2.82134)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.014 30.813) scale(2.72216)"/>
</svg>
<svg width="42" height="98" x="420">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.014 30.813) scale(2.72216)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.013 31.813) scale(2.6233)"/>
</svg>
<svg width="42" height="98" x="462">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.013 31.813) scale(2.6233)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.013 32.809) scale(2.52484)"/>
</svg>
<svg width="42" height="98" x="504">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.013 32.809) scale(2.52484)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.012 33.799) scale(2.42691)"/>
</svg>
<svg width="42" height="98" x="546">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.012 33.799) scale(2.42691)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.012 34.783) scale(2.32959)"/>
</svg>
<svg width="42" height="98" x="588">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.012 34.783) scale(2.32959)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.011 35.76) scale(2.23297)"/>
</svg>
<svg width="42" height="98" x="630">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.011 35.76) scale(2.23297)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.01 36.727) scale(2.13718)"/>
</svg>
<svg width="42" height="98" x="672">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.01 36.727) scale(2.13718)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.01 37.686) scale(2.0423)"/>
</svg>
<svg width="42" height="98" x="714">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.01 37.686) scale(2.0423)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.01 38.634) scale(1.94849)"/>
</svg>
<svg width="42" height="98" x="756">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.01 38.634) scale(1.94849)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.01 39.57) scale(1.85587)"/>
</svg>
<svg width="42" height="98" x="798">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.01 39.57) scale(1.85587)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.009 40.491) scale(1.76462)"/>
</svg>
<svg width="42" height="98" x="840">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.009 40.491) scale(1.76462)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.008 41.397) scale(1.67492)"/>
</svg>
<svg width="42" height="98" x="882">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.008 41.397) scale(1.67492)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.008 42.284) scale(1.58703)"/>
</svg>
<svg width="42" height="98" x="924">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.008 42.284) scale(1.58703)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.008 43.15) scale(1.50124)"/>
</svg>
<svg width="42" height="98" x="966">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.008 43.15) scale(1.50124)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.007 43.99) scale(1.41793)"/>
</svg>
<svg width="42" height="98" x="1008">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.007 43.99) scale(1.41793)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.007 44.8) scale(1.33758)"/>
</svg>
<svg width="42" height="98" x="1050">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.007 44.8) scale(1.33758)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.006 45.573) scale(1.26087)"/>
</svg>
<svg width="42" height="98" x="1092">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.006 45.573) scale(1.26087)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.006 46.299) scale(1.18877)"/>
</svg>
<svg width="42" height="98" x="1134">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.006 46.299) scale(1.18877)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.006 46.963) scale(1.1227)"/>
</svg>
<svg width="42" height="98" x="1176">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.006 46.963) scale(1.1227)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.005 47.541) scale(1.0651)"/>
</svg>
<svg width="42" height="98" x="1218">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.005 47.541) scale(1.0651)"/>
+ <use fill="context-fill" fill-opacity="0.78" href="#notifyarrow" transform="translate(21.005 47.988) scale(1.02049)"/>
</svg>
+
<svg width="42" height="98" x="1260">
- <path fill="context-fill" d="M-0.712 6.158a1 1 0 0 0 1.414 0l5 -5a1 1 0 0 0 -1.414 -1.413l-3.293 3.293v-8.586a1 1 0 0 0 -2 0v8.586l-3.293 -3.293a1 1 0 0 0 -1.414 0.025a0.999 0.999 0 0 0 0 1.388l5 5z" transform="translate(21.005 47.988) scale(1.02049)"/>
+ <use fill="context-fill" fill-opacity="0.2" href="#bar" transform="matrix(1.35 0 0 1.35 20.975 56.514)"/>
+ <g clip-path="url(#f30_uW1U4lQV3i)">
+ <path fill="context-fill" href="#bar" transform="matrix(1.35 0 0 1.35 20.975 56.514)"/>
+ </g>
+ <use fill="context-stroke" href="#indicatorarrow" transform="translate(20.91 48.555) scale(.98585)"/>
+ </svg>
+ <svg width="42" height="98" x="1302">
+ <use fill="context-fill" fill-opacity="0.2" href="#bar" transform="translate(20.975 56.47) scale(1.39697)"/>
+ <use fill="context-stroke" href="#indicatorarrow" transform="translate(20.911 48.946) scale(.99283)"/>
+ </svg>
+ <svg width="42" height="98" x="1344">
+ <use fill="context-fill" fill-opacity="0.2" href="#bar" transform="translate(20.977 56.376) scale(1.49637)"/>
+ <use fill="context-stroke" href="#indicatorarrow" transform="translate(20.911 49.23) scale(.9979)"/>
+ </svg>
+ <svg width="42" height="98" x="1386">
+ <use fill="context-fill" fill-opacity="0.2" href="#bar" transform="translate(20.979 56.266) scale(1.61367)"/>
+ <use fill="context-stroke" href="#indicatorarrow" transform="translate(20.911 49.348)"/>
+ </svg>
+ <svg width="42" height="98" x="1428">
+ <use fill="context-fill" fill-opacity="0.2" href="#bar" transform="matrix(1.7 0 0 1.7 20.98 56.185)"/>
+ <use fill="context-fill" href="#indicatorarrow" transform="translate(20.911 48.918) scale(.99234)"/>
+ </svg>
+ <svg width="42" height="98" x="1470">
+ <use fill="context-fill" fill-opacity="0.2" href="#bar" transform="translate(20.98 56.235) scale(1.6465)"/>
+ <use fill="context-fill" href="#indicatorarrow" transform="translate(20.91 48.449) scale(.98396)"/>
</svg>
- <svg width="42" height="98" x="1302"/>
+ <svg width="42" height="98" x="1512">
+ <use fill="context-fill" fill-opacity="0.2" href="#bar" transform="translate(20.978 56.31) scale(1.56687)"/>
+ <use fill="context-fill" href="#indicatorarrow" transform="translate(20.91 47.99) scale(.97578)"/>
+ </svg>
+ <svg width="42" height="98" x="1554">
+ <use fill="context-fill" fill-opacity="0.2" href="#bar" transform="translate(20.977 56.389) scale(1.48313)"/>
+ <use fill="context-fill" href="#indicatorarrow" transform="translate(20.91 47.563) scale(.96816)"/>
+ </svg>
+ <svg width="42" height="98" x="1596">
+ <use fill="context-fill" fill-opacity="0.2" href="#bar" transform="translate(20.975 56.464) scale(1.4035)"/>
+ <use fill="context-fill" href="#indicatorarrow" transform="translate(20.91 47.182) scale(.96135)"/>
+ </svg>
+ <svg width="42" height="98" x="1638">
+ <use fill="context-fill" fill-opacity="0.2" href="#bar" transform="matrix(1.35 0 0 1.35 20.975 56.514)"/>
+ <use fill="context-fill" href="#indicatorarrow" transform="translate(20.91 46.864) scale(.95569)"/>
+ </svg>
+ <svg width="42" height="98" x="1680">
+ <use fill="context-fill" fill-opacity="0.2" href="#bar" transform="matrix(1.35 0 0 1.35 20.975 56.514)"/>
+ <use fill="context-fill" href="#indicatorarrow" transform="translate(20.91 46.637) scale(.95164)"/>
+ </svg>
+ <svg width="42" height="98" x="1722">
+ <use fill="context-fill" fill-opacity="0.2" href="#bar" transform="matrix(1.35 0 0 1.35 20.975 56.514)"/>
+ <g clip-path="url(#f30_uW1U4lQV3i)">
+ <use fill="context-fill" href="#bar" transform="matrix(1.35 0 0 1.35 20.975 56.514)"/>
+ </g>
+ <use fill="context-fill" href="#indicatorarrow" transform="matrix(.95 0 0 .95 20.91 47.546)"/>
+ </svg>
</svg>
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/downloads/progressbar-start-animation.svg
@@ -0,0 +1,167 @@
+<!-- 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 xmlns="http://www.w3.org/2000/svg" width="1260" height="98">
+ <defs>
+ <clipPath id="a">
+ <path fill="#fff" d="M1.134 15.616v2.236h13.194v-2.236h-13.194"/>
+ </clipPath>
+ <clipPath id="b">
+ <path fill="#fff" d="M0.926 14.806v2.293h13.57v-2.293h-13.57"/>
+ </clipPath>
+ <clipPath id="c">
+ <path fill="#fff" d="M0.763 14.167v2.338h13.865v-2.338h-13.865"/>
+ </clipPath>
+ <path id="progressbar" d="M12.629 14h-9.629a1 1 0 0 0 0 2h9.629a1 1 0 0 0 0 -2z"/>
+ </defs>
+ <svg width="42" height="98">
+ <g clip-path="url(#a)" transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="42">
+ <g clip-path="url(#b)" transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="84">
+ <g clip-path="url(#c)" transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="126">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="168">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="210">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="252">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="294">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="336">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="378">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="420">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="462">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="504">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="546">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="588">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="630">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="672">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="714">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="756">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="798">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="840">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="882">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="924">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="966">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="1008">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="1050">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="1092">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="1134">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="1176">
+ <g transform="translate(12.938 42)">
+ <use fill="context-fill" fill-opacity="0.2" href="#progressbar"/>
+ </g>
+ </svg>
+ <svg width="42" height="98" x="1218">
+ <g transform="translate(12.938 42)">
+ <path fill="context-use" fill-opacity=".33" href="#progressbar"/>
+ </g>
+ </svg>
+</svg>
--- a/browser/themes/shared/jar.inc.mn
+++ b/browser/themes/shared/jar.inc.mn
@@ -42,16 +42,20 @@
skin/classic/browser/customizableui/subView-arrow-back-inverted-rtl@2x.png (../shared/customizableui/subView-arrow-back-inverted-rtl@2x.png)
skin/classic/browser/customizableui/whimsy.png (../shared/customizableui/whimsy.png)
skin/classic/browser/customizableui/whimsy@2x.png (../shared/customizableui/whimsy@2x.png)
skin/classic/browser/downloads/contentAreaDownloadsView.css (../shared/downloads/contentAreaDownloadsView.css)
skin/classic/browser/downloads/download-blocked.svg (../shared/downloads/download-blocked.svg)
skin/classic/browser/downloads/download-summary.svg (../shared/downloads/download-summary.svg)
skin/classic/browser/downloads/download-icons.svg (../shared/downloads/download-icons.svg)
skin/classic/browser/downloads/notification-start-animation.svg (../shared/downloads/notification-start-animation.svg)
+ skin/classic/browser/downloads/progressbar-start-animation.svg (../shared/downloads/progressbar-start-animation.svg)
+ skin/classic/browser/downloads/faux-indicator-animation.svg (../shared/downloads/faux-indicator-animation.svg)
+ skin/classic/browser/downloads/inprogress-arrow.svg (../shared/downloads/inprogress-arrow.svg)
+ skin/classic/browser/downloads/indicator-state-transition.svg (../shared/downloads/indicator-state-transition.svg)
skin/classic/browser/drm-icon.svg (../shared/drm-icon.svg)
skin/classic/browser/fullscreen/insecure.svg (../shared/fullscreen/insecure.svg)
skin/classic/browser/fullscreen/secure.svg (../shared/fullscreen/secure.svg)
skin/classic/browser/connection-secure.svg (../shared/identity-block/connection-secure.svg)
skin/classic/browser/connection-mixed-passive-loaded.svg (../shared/identity-block/connection-mixed-passive-loaded.svg)
skin/classic/browser/connection-mixed-active-loaded.svg (../shared/identity-block/connection-mixed-active-loaded.svg)
skin/classic/browser/identity-icon.svg (../shared/identity-block/identity-icon.svg)
skin/classic/browser/identity-icon-notice.svg (../shared/identity-block/identity-icon-notice.svg)