mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 04:15:43 +00:00
Bug 1257953 - Update narrate to use new animated icon when speaking. r=Gijs
MozReview-Commit-ID: 4OnlJBmzu5T --HG-- extra : rebase_source : 8e2b63b3fc8e26ebec6a4624e92b623f88bea458
This commit is contained in:
parent
a1ab150136
commit
7733c185b1
@ -36,13 +36,59 @@ function NarrateControls(mm, win) {
|
|||||||
let dropdown = win.document.createElement("ul");
|
let dropdown = win.document.createElement("ul");
|
||||||
dropdown.className = "dropdown";
|
dropdown.className = "dropdown";
|
||||||
dropdown.id = "narrate-dropdown";
|
dropdown.id = "narrate-dropdown";
|
||||||
|
// We need inline svg here for the animation to work (bug 908634 & 1190881).
|
||||||
|
// The style animation can't be scoped (bug 830056).
|
||||||
dropdown.innerHTML =
|
dropdown.innerHTML =
|
||||||
localize`<style scoped>
|
localize`<style scoped>
|
||||||
@import url("chrome://global/skin/narrateControls.css");
|
@import url("chrome://global/skin/narrateControls.css");
|
||||||
</style>
|
</style>
|
||||||
<li>
|
<li>
|
||||||
<button class="dropdown-toggle button"
|
<button class="dropdown-toggle button" id="narrate-toggle" title="${"narrate"}">
|
||||||
id="narrate-toggle" title="${"narrate"}"></button>
|
<svg xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<style>
|
||||||
|
@keyframes grow {
|
||||||
|
0% { transform: scaleY(1); }
|
||||||
|
15% { transform: scaleY(1.5); }
|
||||||
|
15% { transform: scaleY(1.5); }
|
||||||
|
30% { transform: scaleY(1); }
|
||||||
|
100% { transform: scaleY(1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#waveform > rect {
|
||||||
|
fill: #808080;
|
||||||
|
}
|
||||||
|
|
||||||
|
.speaking #waveform > rect {
|
||||||
|
fill: #58bf43;
|
||||||
|
transform-box: fill-box;
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
animation-name: grow;
|
||||||
|
animation-duration: 1750ms;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
#waveform > rect:nth-child(2) { animation-delay: 250ms; }
|
||||||
|
#waveform > rect:nth-child(3) { animation-delay: 500ms; }
|
||||||
|
#waveform > rect:nth-child(4) { animation-delay: 750ms; }
|
||||||
|
#waveform > rect:nth-child(5) { animation-delay: 1000ms; }
|
||||||
|
#waveform > rect:nth-child(6) { animation-delay: 1250ms; }
|
||||||
|
#waveform > rect:nth-child(7) { animation-delay: 1500ms; }
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<g id="waveform">
|
||||||
|
<rect x="1" y="8" width="2" height="8" rx=".5" ry=".5" />
|
||||||
|
<rect x="4" y="5" width="2" height="14" rx=".5" ry=".5" />
|
||||||
|
<rect x="7" y="8" width="2" height="8" rx=".5" ry=".5" />
|
||||||
|
<rect x="10" y="4" width="2" height="16" rx=".5" ry=".5" />
|
||||||
|
<rect x="13" y="2" width="2" height="20" rx=".5" ry=".5" />
|
||||||
|
<rect x="16" y="4" width="2" height="16" rx=".5" ry=".5" />
|
||||||
|
<rect x="19" y="7" width="2" height="10" rx=".5" ry=".5" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-popup">
|
<li class="dropdown-popup">
|
||||||
<div id="narrate-control" class="narrate-row">
|
<div id="narrate-control" class="narrate-row">
|
||||||
@ -166,29 +212,15 @@ NarrateControls.prototype = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "narrate-toggle":
|
|
||||||
let dropdown = this._doc.getElementById("narrate-dropdown");
|
|
||||||
if (dropdown.classList.contains("open")) {
|
|
||||||
if (this.narrator.speaking) {
|
|
||||||
this.narrator.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to remove "keep-open" class here so that AboutReader
|
|
||||||
// closes this dropdown properly. This class is eventually removed in
|
|
||||||
// _updateSpeechControls which gets called after narration stops,
|
|
||||||
// but that happend asynchronously and is too late.
|
|
||||||
dropdown.classList.remove("keep-open");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_updateSpeechControls: function(speaking) {
|
_updateSpeechControls: function(speaking) {
|
||||||
let dropdown = this._doc.getElementById("narrate-dropdown");
|
let dropdown = this._doc.getElementById("narrate-dropdown");
|
||||||
dropdown.classList.toggle("keep-open", speaking);
|
dropdown.classList.toggle("keep-open", speaking);
|
||||||
|
dropdown.classList.toggle("speaking", speaking);
|
||||||
|
|
||||||
let startStopButton = this._doc.getElementById("narrate-start-stop");
|
let startStopButton = this._doc.getElementById("narrate-start-stop");
|
||||||
startStopButton.classList.toggle("speaking", speaking);
|
|
||||||
startStopButton.title =
|
startStopButton.title =
|
||||||
gStrings.GetStringFromName(speaking ? "stop" : "start");
|
gStrings.GetStringFromName(speaking ? "stop" : "start");
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@ this.NarrateTestUtils = {
|
|||||||
VOICE_SELECTED: "#narrate-voices .options .option.selected",
|
VOICE_SELECTED: "#narrate-voices .options .option.selected",
|
||||||
VOICE_SELECT_LABEL: "#narrate-voices .select-toggle .current-voice",
|
VOICE_SELECT_LABEL: "#narrate-voices .select-toggle .current-voice",
|
||||||
RATE: "#narrate-rate-input",
|
RATE: "#narrate-rate-input",
|
||||||
START: "#narrate-start-stop:not(.speaking)",
|
START: "#narrate-dropdown:not(.speaking) #narrate-start-stop",
|
||||||
STOP: "#narrate-start-stop.speaking",
|
STOP: "#narrate-dropdown.speaking #narrate-start-stop",
|
||||||
BACK: "#narrate-skip-previous",
|
BACK: "#narrate-skip-previous",
|
||||||
FORWARD: "#narrate-skip-next",
|
FORWARD: "#narrate-skip-next",
|
||||||
|
|
||||||
|
@ -94,10 +94,15 @@ add_task(function* testNarrate() {
|
|||||||
yield promiseEvent;
|
yield promiseEvent;
|
||||||
ok(NarrateTestUtils.isVisible(popup), "popup stays visible after scroll");
|
ok(NarrateTestUtils.isVisible(popup), "popup stays visible after scroll");
|
||||||
|
|
||||||
promiseEvent = ContentTaskUtils.waitForEvent(content, "paragraphend");
|
|
||||||
toggle.click();
|
toggle.click();
|
||||||
yield promiseEvent;
|
|
||||||
ok(!NarrateTestUtils.isVisible(popup), "popup is dismissed while speaking");
|
ok(!NarrateTestUtils.isVisible(popup), "popup is dismissed while speaking");
|
||||||
ok(true, "speech stopped when popup is dismissed");
|
NarrateTestUtils.isStartedState(content, ok);
|
||||||
|
|
||||||
|
promiseEvent = ContentTaskUtils.waitForEvent(content, "paragraphend");
|
||||||
|
$(NarrateTestUtils.STOP).click();
|
||||||
|
yield promiseEvent;
|
||||||
|
yield ContentTaskUtils.waitForCondition(
|
||||||
|
() => !$(NarrateTestUtils.STOP), "transitioned to stopped state");
|
||||||
|
NarrateTestUtils.isStoppedState(content, ok);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -222,7 +222,7 @@ AboutReader.prototype = {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "scroll":
|
case "scroll":
|
||||||
this._closeDropdowns();
|
this._closeDropdowns(true);
|
||||||
let isScrollingUp = this._scrollOffset > aEvent.pageY;
|
let isScrollingUp = this._scrollOffset > aEvent.pageY;
|
||||||
this._setSystemUIVisibility(isScrollingUp);
|
this._setSystemUIVisibility(isScrollingUp);
|
||||||
this._scrollOffset = aEvent.pageY;
|
this._scrollOffset = aEvent.pageY;
|
||||||
@ -771,10 +771,17 @@ AboutReader.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the ReaderView has open dropdowns, close them.
|
* If the ReaderView has open dropdowns, close them. If we are closing the
|
||||||
|
* dropdowns because the page is scrolling, allow popups to stay open with
|
||||||
|
* the keep-open class.
|
||||||
*/
|
*/
|
||||||
_closeDropdowns: function() {
|
_closeDropdowns: function(scrolling) {
|
||||||
let openDropdowns = this._doc.querySelectorAll(".dropdown.open:not(.keep-open)");
|
let selector = ".dropdown.open";
|
||||||
|
if (scrolling) {
|
||||||
|
selector += ":not(.keep-open)";
|
||||||
|
}
|
||||||
|
|
||||||
|
let openDropdowns = this._doc.querySelectorAll(selector);
|
||||||
for (let dropdown of openDropdowns) {
|
for (let dropdown of openDropdowns) {
|
||||||
dropdown.classList.remove("open");
|
dropdown.classList.remove("open");
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,6 @@ toolkit.jar:
|
|||||||
skin/classic/global/narrate/back.svg (../../shared/narrate/back.svg)
|
skin/classic/global/narrate/back.svg (../../shared/narrate/back.svg)
|
||||||
skin/classic/global/narrate/fast.svg (../../shared/narrate/fast.svg)
|
skin/classic/global/narrate/fast.svg (../../shared/narrate/fast.svg)
|
||||||
skin/classic/global/narrate/forward.svg (../../shared/narrate/forward.svg)
|
skin/classic/global/narrate/forward.svg (../../shared/narrate/forward.svg)
|
||||||
skin/classic/global/narrate/narrate.svg (../../shared/narrate/narrate.svg)
|
|
||||||
skin/classic/global/narrate/narrate-active.svg (../../shared/narrate/narrate-active.svg)
|
|
||||||
skin/classic/global/narrate/slow.svg (../../shared/narrate/slow.svg)
|
skin/classic/global/narrate/slow.svg (../../shared/narrate/slow.svg)
|
||||||
skin/classic/global/narrate/start.svg (../../shared/narrate/start.svg)
|
skin/classic/global/narrate/start.svg (../../shared/narrate/start.svg)
|
||||||
skin/classic/global/narrate/stop.svg (../../shared/narrate/stop.svg)
|
skin/classic/global/narrate/stop.svg (../../shared/narrate/stop.svg)
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<!-- 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" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
|
|
||||||
<style>
|
|
||||||
@keyframes grow {
|
|
||||||
0% { transform: scaleY(1); }
|
|
||||||
15% { transform: scaleY(1.5); }
|
|
||||||
15% { transform: scaleY(1.5); }
|
|
||||||
30% { transform: scaleY(1); }
|
|
||||||
100% { transform: scaleY(1); }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes shrink {
|
|
||||||
0% { transform: scaleY(1); }
|
|
||||||
15% { transform: scaleY(.5); }
|
|
||||||
15% { transform: scaleY(.5); }
|
|
||||||
30% { transform: scaleY(1); }
|
|
||||||
100% { transform: scaleY(1); }
|
|
||||||
}
|
|
||||||
|
|
||||||
.barAnimation {
|
|
||||||
transform-box: fill-box;
|
|
||||||
transform-origin: 50% 50%;
|
|
||||||
animation-name: grow;
|
|
||||||
animation-duration: 1750ms;
|
|
||||||
animation-iteration-count: infinite;
|
|
||||||
animation-timing-function: linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
.barAnimation01 { animation-delay: 0; }
|
|
||||||
.barAnimation02 { animation-delay: 250ms; }
|
|
||||||
.barAnimation03 { animation-delay: 500ms; }
|
|
||||||
.barAnimation04 { animation-delay: 750ms; }
|
|
||||||
.barAnimation05 { animation-delay: 1000ms; }
|
|
||||||
.barAnimation06 { animation-delay: 1250ms; }
|
|
||||||
.barAnimation07 { animation-delay: 1500ms; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<g id="glyph-waveform" fill="#58bf43">
|
|
||||||
<rect x="1" y="8" width="2" height="8" rx=".5" ry=".5" class="barAnimation barAnimation01" />
|
|
||||||
<rect x="4" y="5" width="2" height="14" rx=".5" ry=".5" class="barAnimation barAnimation02" />
|
|
||||||
<rect x="7" y="8" width="2" height="8" rx=".5" ry=".5" class="barAnimation barAnimation03" />
|
|
||||||
<rect x="10" y="4" width="2" height="16" rx=".5" ry=".5" class="barAnimation barAnimation04" />
|
|
||||||
<rect x="13" y="2" width="2" height="20" rx=".5" ry=".5" class="barAnimation barAnimation05" />
|
|
||||||
<rect x="16" y="4" width="2" height="16" rx=".5" ry=".5" class="barAnimation barAnimation06" />
|
|
||||||
<rect x="19" y="7" width="2" height="10" rx=".5" ry=".5" class="barAnimation barAnimation07" />
|
|
||||||
</g>
|
|
||||||
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 2.1 KiB |
@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<!-- 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" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
|
|
||||||
<g id="glyph-waveform" fill="#808080">
|
|
||||||
<rect x="1" y="8" width="2" height="8" rx=".5" ry=".5" />
|
|
||||||
<rect x="4" y="5" width="2" height="14" rx=".5" ry=".5" />
|
|
||||||
<rect x="7" y="8" width="2" height="8" rx=".5" ry=".5" />
|
|
||||||
<rect x="10" y="4" width="2" height="16" rx=".5" ry=".5" />
|
|
||||||
<rect x="13" y="2" width="2" height="20" rx=".5" ry=".5" />
|
|
||||||
<rect x="16" y="4" width="2" height="16" rx=".5" ry=".5" />
|
|
||||||
<rect x="19" y="7" width="2" height="10" rx=".5" ry=".5" />
|
|
||||||
</g>
|
|
||||||
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 865 B |
@ -2,8 +2,9 @@
|
|||||||
--border-color: #e5e5e5;
|
--border-color: #e5e5e5;
|
||||||
}
|
}
|
||||||
|
|
||||||
#narrate-toggle {
|
#narrate-toggle > svg {
|
||||||
background-image: url("chrome://global/skin/narrate/narrate.svg");
|
display: block;
|
||||||
|
margin: 0 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-popup button {
|
.dropdown-popup button {
|
||||||
@ -64,7 +65,7 @@
|
|||||||
background-image: url("chrome://global/skin/narrate/start.svg");
|
background-image: url("chrome://global/skin/narrate/start.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
#narrate-start-stop.speaking {
|
#narrate-dropdown.speaking #narrate-start-stop {
|
||||||
background-image: url("chrome://global/skin/narrate/stop.svg");
|
background-image: url("chrome://global/skin/narrate/stop.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user