Skip to content

Instantly share code, notes, and snippets.

@bwinton
Created March 30, 2015 17:27
Show Gist options
  • Save bwinton/2a00d538b1ada12eada4 to your computer and use it in GitHub Desktop.
Save bwinton/2a00d538b1ada12eada4 to your computer and use it in GitHub Desktop.
diff --git a/browser/components/readinglist/sidebar.js b/browser/components/readinglist/sidebar.js
--- a/browser/components/readinglist/sidebar.js
+++ b/browser/components/readinglist/sidebar.js
@@ -87,44 +87,67 @@ let RLSidebar = {
* TODO: We should guard against the list growing here.
*
* @param {ReadinglistItem} item - Item that was added.
*/
onItemAdded(item, append = false) {
log.trace(`onItemAdded: ${item}`);
let itemNode = document.importNode(this.itemTemplate.content, true).firstElementChild;
+
this.updateItem(item, itemNode);
+ itemNode.classList.add('pre-adding');
+
// XXX Inserting at the top by default is a temp hack that will stop
// working once we start including items received from sync.
if (append)
this.list.appendChild(itemNode);
else
this.list.insertBefore(itemNode, this.list.firstChild);
- this.itemNodesById.set(item.id, itemNode);
- this.itemsById.set(item.id, item);
- this.emptyListInfo.hidden = true;
+ let transitionend = (event) => {
+ itemNode.removeEventListener('transitionend', transitionend, false);
+
+ this.itemNodesById.set(item.id, itemNode);
+ this.itemsById.set(item.id, item);
+
+ this.emptyListInfo.hidden = true;
+ itemNode.classList.remove('adding');
+ }
+ itemNode.addEventListener('transitionend', transitionend, false);
+ itemNode.classList.remove('pre-adding');
+ itemNode.classList.add('adding');
},
/**
* Handle an item being deleted from the ReadingList.
* @param {ReadingListItem} item - Item that was deleted.
*/
onItemDeleted(item) {
log.trace(`onItemDeleted: ${item}`);
let itemNode = this.itemNodesById.get(item.id);
- itemNode.remove();
- this.itemNodesById.delete(item.id);
- this.itemsById.delete(item.id);
- // TODO: ensureListItems doesn't yet cope with needing to add one item.
- //this.ensureListItems();
+ itemNode.addEventListener('transitionend', (event) => {
+ if (event.propertyName == "opacity") {
+ // After the opacity is done, transition the max-height.
+ itemNode.classList.remove('removing');
+ itemNode.classList.add('removed');
+ } else if (event.propertyName == "max-height") {
+ this.itemNodesById.delete(item.id);
+ this.itemsById.delete(item.id);
+ itemNode.remove();
- this.emptyListInfo.hidden = (this.numItems > 0);
+ // TODO: ensureListItems doesn't yet cope with needing to add one item.
+ //this.ensureListItems();
+
+ this.emptyListInfo.hidden = (this.numItems > 0);
+ }
+ }, false);
+
+ itemNode.classList.add('removing');
},
/**
* Handle an item in the ReadingList having any of its properties changed.
* @param {ReadingListItem} item - Item that was updated.
*/
onItemUpdated(item) {
log.trace(`onItemUpdated: ${item}`);
diff --git a/browser/themes/shared/readinglist/readinglist.inc.css b/browser/themes/shared/readinglist/readinglist.inc.css
--- a/browser/themes/shared/readinglist/readinglist.inc.css
+++ b/browser/themes/shared/readinglist/readinglist.inc.css
@@ -1,17 +1,21 @@
/* Reading List button */
#urlbar:not([focused]):not(:hover) #readinglist-addremove-button {
- display: none;
+ opacity: 0;
+ width: 0px;
}
#readinglist-addremove-button {
list-style-image: url("chrome://browser/skin/readinglist/icons.svg#addpage");
-moz-image-region: rect(0, 14px, 14px, 0);
+ transition: width 150ms ease-in-out, opacity 150ms ease-in-out 150ms;
+ opacity: 1;
+ width: 20px;
}
#readinglist-addremove-button:hover {
list-style-image: url("chrome://browser/skin/readinglist/icons.svg#addpage-hover");
}
#readinglist-addremove-button:active {
list-style-image: url("chrome://browser/skin/readinglist/icons.svg#addpage-active");
diff --git a/browser/themes/shared/readinglist/sidebar.inc.css b/browser/themes/shared/readinglist/sidebar.inc.css
--- a/browser/themes/shared/readinglist/sidebar.inc.css
+++ b/browser/themes/shared/readinglist/sidebar.inc.css
@@ -26,16 +26,19 @@ body {
overflow-x: auto;
}
.item {
display: flex;
flex-flow: row;
cursor: pointer;
padding: 6px;
+ opacity: 1;
+ max-height: 80px;
+ transition: opacity 150ms ease-in-out, max-height 150ms ease-in-out;
}
.item.active {
background: #FEFEFE;
}
.item.selected {
background: #FDFDFD;
@@ -100,8 +103,26 @@ body {
padding: 0;
width: 16px;
height: 16px;
background-size: contain;
background-color: transparent;
border-width: 0;
}
+.item.pre-adding {
+ opacity: 0;
+ max-height: 0px;
+}
+
+.item.adding {
+ opacity: 0;
+ max-height: 80px;
+}
+
+.item.removing {
+ opacity: 0;
+}
+
+.item.removed {
+ opacity: 0;
+ max-height: 0;
+}
diff --git a/mobile/android/themes/core/aboutReader.css b/mobile/android/themes/core/aboutReader.css
--- a/mobile/android/themes/core/aboutReader.css
+++ b/mobile/android/themes/core/aboutReader.css
@@ -452,17 +452,18 @@ body {
color: #333333;
background-color: #ffffff;
}
/*======= Toolbar icons =======*/
/* desktop-only controls */
.close-button,
-.list-button {
+.list-button,
+.footer {
display: none;
}
.toggle-button.on {
background-image: url('chrome://browser/skin/images/reader-toggle-on-icon-mdpi.png');
}
.toggle-button {
diff --git a/toolkit/components/reader/AboutReader.jsm b/toolkit/components/reader/AboutReader.jsm
--- a/toolkit/components/reader/AboutReader.jsm
+++ b/toolkit/components/reader/AboutReader.jsm
@@ -56,18 +56,21 @@ let AboutReader = function(mm, win, arti
doc.addEventListener("visibilitychange", this, false);
this._setupStyleDropdown();
this._setupButton("close-button", this._onReaderClose.bind(this), "aboutReader.toolbar.close");
this._setupButton("share-button", this._onShare.bind(this), "aboutReader.toolbar.share");
try {
if (Services.prefs.getBoolPref("browser.readinglist.enabled")) {
- this._setupButton("toggle-button", this._onReaderToggle.bind(this), "aboutReader.toolbar.addToReadingList");
+ this._setupButton("toggle-button", this._onReaderToggle.bind(this, "button"), "aboutReader.toolbar.addToReadingList");
this._setupButton("list-button", this._onList.bind(this), "aboutReader.toolbar.openReadingList");
+ this._setupButton("remove-button", this._onReaderToggle.bind(this, "footer"),
+ "aboutReader.footer.deleteThisArticle", "aboutReader.footer.deleteThisArticle");
+ this._doc.getElementById("reader-footer").setAttribute('readinglist-enabled', "true");
}
} catch (e) {
// Pref doesn't exist.
}
let colorSchemeValues = JSON.parse(Services.prefs.getCharPref("reader.color_scheme.values"));
let colorSchemeOptions = colorSchemeValues.map((value) => {
return { name: gStrings.GetStringFromName("aboutReader.colorScheme." + value),
@@ -235,16 +238,17 @@ AboutReader.prototype = {
if (this._isReadingListItem == 1) {
button.classList.add("on");
button.setAttribute("title", gStrings.GetStringFromName("aboutReader.toolbar.removeFromReadingList"));
} else {
button.classList.remove("on");
button.setAttribute("title", gStrings.GetStringFromName("aboutReader.toolbar.addToReadingList"));
}
+ this._updateFooter();
},
_requestReadingListStatus: function Reader_requestReadingListStatus() {
let handleListStatusData = (message) => {
this._mm.removeMessageListener("Reader:ListStatusData", handleListStatusData);
let args = message.data;
if (args.url == this._article.url) {
@@ -265,26 +269,26 @@ AboutReader.prototype = {
this._mm.addMessageListener("Reader:ListStatusData", handleListStatusData);
this._mm.sendAsyncMessage("Reader:ListStatusRequest", { url: this._article.url });
},
_onReaderClose: function Reader_onToggle() {
this._win.location.href = this._getOriginalUrl();
},
- _onReaderToggle: function Reader_onToggle() {
+ _onReaderToggle: function Reader_onToggle(aMethod) {
if (!this._article)
return;
if (this._isReadingListItem == 0) {
this._mm.sendAsyncMessage("Reader:AddToList", { article: this._article });
- UITelemetry.addEvent("save.1", "button", null, "reader");
+ UITelemetry.addEvent("save.1", aMethod, null, "reader");
} else {
this._mm.sendAsyncMessage("Reader:RemoveFromList", { url: this._article.url });
- UITelemetry.addEvent("unsave.1", "button", null, "reader");
+ UITelemetry.addEvent("unsave.1", aMethod, null, "reader");
}
},
_onShare: function Reader_onShare() {
if (!this._article)
return;
this._mm.sendAsyncMessage("Reader:Share", {
@@ -409,16 +413,26 @@ AboutReader.prototype = {
}
currentSize--;
updateControls();
this._setFontSize(currentSize);
}, true);
},
+ _updateFooter: function RupdateFooter() {
+ let footer = this._doc.getElementById("reader-footer");
+ if (!this._article || this._isReadingListItem == 0 ||
+ footer.getAttribute("readinglist-enabled") != "true") {
+ footer.style.display = "none";
+ return;
+ }
+ footer.style.display = null;
+ },
+
_handleDeviceLight: function Reader_handleDeviceLight(newLux) {
// Desired size of the this._luxValues array.
let luxValuesSize = 10;
// Add new lux value at the front of the array.
this._luxValues.unshift(newLux);
// Add new lux value to this._totalLux for averaging later.
this._totalLux += newLux;
@@ -548,16 +562,17 @@ AboutReader.prototype = {
} else {
this._toolbarElement.removeAttribute("visible");
}
this._setSystemUIVisibility(visible);
if (!visible) {
this._mm.sendAsyncMessage("Reader:ToolbarHidden");
}
+ this._updateFooter();
},
_toggleToolbarVisibility: function Reader_toggleToolbarVisibility() {
this._setToolbarVisibility(!this._getToolbarVisibility());
},
_setSystemUIVisibility: function Reader_setSystemUIVisibility(visible) {
this._mm.sendAsyncMessage("Reader:SystemUIVisibility", { visible: visible });
@@ -722,17 +737,17 @@ AboutReader.prototype = {
this._maybeSetTextDirection(article);
this._contentElement.style.display = "block";
this._updateImageMargins();
this._requestReadingListStatus();
this._showListIntro();
this._requestFavicon();
- this._doc.body.classList.add("loaded");
+ this._doc.documentElement.classList.add("loaded");
},
_hideContent: function Reader_hideContent() {
this._headerElement.style.display = "none";
this._contentElement.style.display = "none";
},
_showProgressDelayed: function Reader_showProgressDelayed() {
@@ -809,20 +824,22 @@ AboutReader.prototype = {
callback(option.value);
}.bind(this), true);
if (option.value === initialValue)
item.classList.add("selected");
}
},
- _setupButton: function(id, callback, titleEntity) {
+ _setupButton: function(id, callback, titleEntity, textEntity) {
this._setButtonTip(id, titleEntity);
let button = this._doc.getElementById(id);
+ if (textEntity)
+ button.textContent = gStrings.GetStringFromName(textEntity);
button.removeAttribute("hidden");
button.addEventListener("click", function(aEvent) {
if (!aEvent.isTrusted)
return;
aEvent.stopPropagation();
callback();
}, true);
diff --git a/toolkit/components/reader/content/aboutReader.html b/toolkit/components/reader/content/aboutReader.html
--- a/toolkit/components/reader/content/aboutReader.html
+++ b/toolkit/components/reader/content/aboutReader.html
@@ -19,16 +19,20 @@
<div id="reader-credits" class="credits"></div>
</div>
<div id="reader-content" class="content">
</div>
<div id="reader-message" class="message">
</div>
+
+ <div id="reader-footer" class="footer">
+ <button id="remove-button" class="button remove-button"/>
+ </div>
</div>
<ul id="reader-toolbar" class="toolbar">
<li><button id="close-button" class="button close-button"/></li>
<li><button id="share-button" class="button share-button"/></li>
<ul id="style-dropdown" class="dropdown">
<li><button class="dropdown-toggle button style-button"/></li>
<li class="dropdown-popup">
diff --git a/toolkit/themes/windows/global/aboutReader.css b/toolkit/themes/windows/global/aboutReader.css
--- a/toolkit/themes/windows/global/aboutReader.css
+++ b/toolkit/themes/windows/global/aboutReader.css
@@ -1,20 +1,23 @@
/* 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/. */
+html.loaded {
+ transition: font-size 0.4s ease-in-out;
+}
+
body {
padding: 64px 0;
max-width: 660px;
- margin-left: auto;
- margin-right: auto;
+ margin: 0 auto;
}
-body.loaded {
+html.loaded > body {
transition: color 0.4s, background-color 0.4s;
}
.light,
.light-button {
color: #333333;
background-color: #ffffff;
}
@@ -26,21 +29,23 @@ body.loaded {
}
.sepia,
.sepia-button {
color: #333333;
background-color: #f0ece7;
}
-.sans-serif {
+.sans-serif,
+.sans-serif .remove-button {
font-family: "Fira Sans", Helvetica, Arial, sans-serif;
}
-.serif {
+.serif,
+.serif .remove-button {
font-family: "Charis SIL", Georgia, "Times New Roman", serif;
}
.font-size1 {
font-size: 10px;
}
.font-size2 {
@@ -241,79 +246,78 @@ body.loaded {
}
/*======= Controls toolbar =======*/
.toolbar {
font-family: "Fira Sans", Helvetica, Arial, sans-serif;
position: fixed;
height: 100%;
- top: 0px;
- left: 0px;
+ top: 0;
+ left: 0;
margin: 0;
padding: 0;
list-style: none;
- background-color: #FBFBFB;
+ background-color: #fbfbfb;
-moz-user-select: none;
- border-right: 1px solid #B5B5B5;
+ border-right: 1px solid #b5b5b5;
}
.button {
- color: white;
display: block;
- background-position: center;
background-size: 24px 24px;
background-repeat: no-repeat;
- background-color: transparent;
height: 40px;
+ padding: 0;
+}
+
+.toolbar .button {
+ color: white;
width: 40px;
+ background-position: center;
+ background-color: #fbfbfb;
border-top: 0;
border-left: 0;
border-right: 0;
border-bottom: 1px solid #c1c1c1;
- padding: 0;
}
.button[hidden] {
display: none;
}
.dropdown {
text-align: center;
list-style: none;
- margin: 0px;
- padding: 0px;
+ margin: 0;
+ padding: 0;
}
.dropdown li {
- margin: 0px;
- padding: 0px;
+ margin: 0;
+ padding: 0;
}
/*======= Font style popup =======*/
.dropdown-popup {
- min-width: 250px;
+ min-width: 300px;
text-align: start;
position: absolute;
left: 48px; /* offset to account for toolbar width */
z-index: 1000;
- background-color: #FBFBFB;
+ background-color: #fbfbfb;
visibility: hidden;
border-radius: 4px;
- border: 1px 1px 0 1px solid #B5B5B5;
- box-shadow: 0px 1px 12px #666;
+ border: 1px 1px 0 1px solid #b5b5b5;
+ box-shadow: 0 1px 12px #666;
}
.dropdown-popup > hr {
- width: 100%;
- height: 0px;
- border: 0px;
- border-top: 1px solid #B5B5B5;
- margin: 0;
+ display: none;
}
.open > .dropdown-popup {
visibility: visible;
}
.dropdown-arrow {
position: absolute;
@@ -344,89 +348,141 @@ body.loaded {
#color-scheme-buttons > button:last-child {
border-bottom-right-radius: 3px;
}
#font-type-buttons > button,
#font-size-buttons > button,
#color-scheme-buttons > button {
text-align: center;
- border-left: 1px solid #B5B5B5;
- border-right: 0;
- border-top: 0;
- border-bottom: 0;
- padding: 10px;
+ border: 0;
}
#font-type-buttons > button,
#font-size-buttons > button {
width: 50%;
background-color: transparent;
+ border-left: 1px solid #B5B5B5;
+ border-bottom: 1px solid #B5B5B5;
}
#color-scheme-buttons > button {
width: 33.33%;
font-size: 14px;
}
+#color-scheme-buttons > .dark-button {
+ margin-top: -1px;
+ height: 61px;
+}
+
#font-type-buttons > button:first-child,
-#font-size-buttons > button:first-child,
-#color-scheme-buttons > button:first-child {
- border-left: 0px;
+#font-size-buttons > button:first-child {
+ border-left: 0;
}
#font-type-buttons > button {
display: inline-block;
- font-size: 48px;
+ font-size: 58px;
+ height: 100px;
+}
+
+/* Make the serif button content the same size as the sans-serif button content. */
+#font-type-buttons > .serif-button {
+ padding-top: 1px;
+ font-size: 60px;
+}
+
+#font-size-buttons > button,
+#color-scheme-buttons > button {
+ height: 60px;
}
#font-type-buttons > button:active:hover,
#font-type-buttons > button.selected,
#color-scheme-buttons > button:active:hover,
#color-scheme-buttons > button.selected {
- box-shadow: inset 0 -3px 0 0 #FC6420;
+ box-shadow: inset 0 -3px 0 0 #fc6420;
+}
+
+#font-type-buttons > button:active:hover,
+#font-type-buttons > button.selected {
+ border-bottom: 1px solid #FC6420;
}
#font-type-buttons > button > div {
color: #666;
font-size: 12px;
+ margin-top: -4px;
}
.button:hover,
#font-size-buttons > button:hover,
#font-type-buttons > button:hover {
- background-color: #EBEBEB;
+ background-color: #ebebeb;
}
.dropdown.open,
.button:active,
#font-size-buttons > button:active,
#font-size-buttons > button.selected {
- background-color: #DADADA;
+ background-color: #dadada;
}
/* Only used on Android */
#font-size-sample {
display: none;
}
.serif-button {
font-family: "Charis SIL", Georgia, "Times New Roman", serif;
}
.minus-button,
.plus-button {
background-color: transparent;
border: 0;
- height: 50px;
background-size: 18px 18px;
background-repeat: no-repeat;
background-position: center;
}
+.footer {
+ height: 64px;
+ background-color: #ebebeb;
+ position: absolute;
+ left: 0;
+ width: 100%;
+ text-align: center;
+ padding: 12px 0;
+ box-sizing: border-box;
+ box-shadow: 0 9px 9px -9px #c1c1c1 inset;
+}
+
+.sepia .footer {
+ background-color: #dedad4;
+}
+
+.dark .footer {
+ background-color: #777;
+}
+
+.remove-button {
+ background-image: url("chrome://global/skin/reader/RM-Delete-24x24.svg");
+ margin: 0 auto;
+ border: 1px solid #c1c1c1;
+ background-position: 10px 7px;
+ padding-left: 42px;
+ padding-right: 10px;
+ border-radius: 2px;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
+ font-size: 18px;
+}
+
+
/*======= Toolbar icons =======*/
/* Android-only controls */
.share-button {
display: none;
}
.close-button {
@@ -467,9 +523,12 @@ body.loaded {
.plus-button {
background-image: url("chrome://global/skin/reader/RM-Plus-24x24.svg");
}
@media print {
.toolbar {
display: none;
}
+ .footer {
+ display: none;
+ }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment