From 172c8bc6470fee85c417f49e2b22c3115faae267 Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Sun, 1 Oct 2017 21:28:30 +0200 Subject: [PATCH] Make compact (many in one row) pinned tabs configurable. While pinned tabs being outside of scrolling container are awesome, for old Tab Center-like configurations with autoshrinking sidebar the presentation of many tabs in one row is actually an antifeature. This PR makes it configurable, so custom userChrome.css configs like in #103 or #118 that restore old behavior can work properly. Also, the thumbnail reseting has been removed. This fixes a newly introduced issue of unpinned tab not having its thumbnail updated. While this could be fixed in other way, disabling thumbnail generation for pinned tabs is not desired when compact pins are disabled anyway. --- src/_locales/en/messages.json | 4 ++ src/img/glyph-pin-pinned-12.svg | 24 +++++++++ src/options/options.html | 2 + src/options/options.js | 13 +++-- src/tab.js | 13 ++--- src/tabcenter.css | 94 +++++++++++++++++++++++---------- src/tabcenter.html | 4 +- src/tablist.js | 31 ++++++++--- 8 files changed, 135 insertions(+), 50 deletions(-) create mode 100644 src/img/glyph-pin-pinned-12.svg diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index cbf5943..8257f03 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -91,6 +91,10 @@ "message": "Compact Mode" }, + "optionsCompactPins": { + "message": "Compact Pinned Tabs" + }, + "optionsDarkTheme": { "message": "Dark Theme" }, diff --git a/src/img/glyph-pin-pinned-12.svg b/src/img/glyph-pin-pinned-12.svg new file mode 100644 index 0000000..4e93758 --- /dev/null +++ b/src/img/glyph-pin-pinned-12.svg @@ -0,0 +1,24 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/options/options.html b/src/options/options.html index d9918e8..f5938c2 100644 --- a/src/options/options.html +++ b/src/options/options.html @@ -9,6 +9,8 @@

+
+
diff --git a/src/options/options.js b/src/options/options.js index 9b8d994..a2c8926 100644 --- a/src/options/options.js +++ b/src/options/options.js @@ -5,8 +5,9 @@ function TabCenterOptions() { TabCenterOptions.prototype = { setupLabels() { - const options = ["optionsTitle", "optionsCompactMode", "optionsDarkTheme", - "optionsAdvancedTitle", "optionsCustomCSS", "optionsSaveCustomCSS"]; + const options = ["optionsTitle", "optionsCompactMode", + "optionsCompactPins", "optionsDarkTheme", "optionsAdvancedTitle", + "optionsCustomCSS", "optionsSaveCustomCSS"]; for (let opt of options) { this._setupTextContentLabel(opt); } @@ -16,17 +17,19 @@ TabCenterOptions.prototype = { }, setupStateAndListeners() { this._setupCheckboxOption("compactMode", "compactMode"); + this._setupCheckboxOption("compactPins", "compactPins"); this._setupCheckboxOption("darkTheme", "darkTheme"); - // Custom CSS browser.storage.local.get({ - ["customCSS"]: "" + "compactPins": true, + "customCSS": "" }).then(prefs => { document.getElementById("customCSS").value = prefs["customCSS"]; + document.getElementById("compactPins").checked = prefs["compactPins"]; }); document.getElementById("optionsSaveCustomCSS").addEventListener("click", () => { browser.storage.local.set({ - ["customCSS"]: document.getElementById("customCSS").value + "customCSS": document.getElementById("customCSS").value }); }); }, diff --git a/src/tab.js b/src/tab.js index 7777908..99cead9 100644 --- a/src/tab.js +++ b/src/tab.js @@ -19,7 +19,7 @@ SideTab.prototype = { this.updateURL(tabInfo.url); this.updateAudible(tabInfo.audible); this.updatedMuted(tabInfo.mutedInfo.muted); - this.updateIcon(tabInfo.favIconUrl); + this.updateIcon(tabInfo.hasOwnProperty("favIconUrl") ? tabInfo.favIconUrl : null); this.updatePinned(tabInfo.pinned); if (tabInfo.cookieStoreId) { // This work is done in the background on purpose: making create() async @@ -67,6 +67,9 @@ SideTab.prototype = { titleWrapper.appendChild(host); this._hostView = host; + const pin = document.createElement("div"); + pin.className = "tab-pin"; + const close = document.createElement("div"); close.className = "tab-close clickable"; close.title = browser.i18n.getMessage("closeTabButtonTooltip"); @@ -75,6 +78,7 @@ SideTab.prototype = { tab.appendChild(iconOverlay); tab.appendChild(metaImage); tab.appendChild(titleWrapper); + tab.appendChild(pin); tab.appendChild(close); }, updateTitle(title) { @@ -131,9 +135,6 @@ SideTab.prototype = { updatePinned(pinned) { this.pinned = pinned; toggleClass(this.view, "pinned", pinned); - if (pinned) { - this.resetThumbnail(); - } }, updateContext(context) { if (!context) { @@ -145,10 +146,6 @@ SideTab.prototype = { updateThumbnail(thumbnail) { this._metaImageView.style.backgroundImage = `url(${thumbnail})`; this._metaImageView.classList.add("has-thumbnail"); - }, - resetThumbnail() { - this._metaImageView.style.backgroundImage = ""; - this._metaImageView.classList.remove("has-thumbnail"); } }; diff --git a/src/tabcenter.css b/src/tabcenter.css index 0a86dc3..c1d1f39 100644 --- a/src/tabcenter.css +++ b/src/tabcenter.css @@ -2,6 +2,7 @@ :root { --tab-background-normal: 0, 0%, 99%; + --tab-background-pinned: 0, 0%, 97%; --tab-background-active: 0, 0%, 87%; --tab-background-hover: 0, 0%, 91%; } @@ -246,11 +247,11 @@ img, .tab *:not(.clickable) { overflow-y: auto; } -#tablist { +.tablist { overflow-x: hidden; } -.tab:not(.pinned) { +.tablist:not(.compact) .tab { display: flex; align-items: center; height: 56px; @@ -306,7 +307,7 @@ img, .tab *:not(.clickable) { box-shadow: 0 1px 0 hsla(0, 0%, 0%, 0.5); } -#tablist.shrinked .tab-icon-overlay { +.tablist.shrinked .tab-icon-overlay { width: 13px; height: 13px; margin: 0 0 -13px -13px; @@ -326,7 +327,7 @@ img, .tab *:not(.clickable) { background-image: url("img/tab-audio-small.svg#tab-audio-muted"); } -#tablist:not(.shrinked) .tab-meta-image { +.tablist:not(.shrinked):not(.compact) .tab-meta-image { margin: 6px; min-width: 54px; height: 40px; @@ -338,8 +339,11 @@ img, .tab *:not(.clickable) { box-shadow: 0 0 2px 2px hsla(0, 0%, 0%, 0.02), 0 2px 0 hsla(0, 0%, 0%, 0.05), 0 0 0 1px hsla(0, 0%, 0%, 0.2); } -#tablist.shrinked .tab-meta-image { +.tablist.shrinked .tab-meta-image, .tablist.pinned.compact .tab-meta-image { background: none !important; /* Because the JS script sets it manually */ +} + +.tablist.shrinked:not(.compact) .tab-meta-image { /* Make it the same size as the favicon it contains */ height: 20px; width: 20px; @@ -352,7 +356,7 @@ img, .tab *:not(.clickable) { image-rendering: -moz-crisp-edges; } -#tablist:not(.shrinked) .tab-icon { +.tablist:not(.shrinked):not(.compact) .tab-icon { margin-left: 0px; margin-top: 20px; border-radius :2px; @@ -360,10 +364,10 @@ img, .tab *:not(.clickable) { box-shadow: 0 0 2px hsla(0, 0%, 0%, 0.08), 0 0 0 1px hsla(0, 0%, 0%, 0.08); } -#tablist:not(.shrinked) .tab-meta-image.has-thumbnail { +.tablist:not(.shrinked):not(.compact) .tab-meta-image.has-thumbnail { border: 2px solid white; } -#tablist:not(.shrinked) .tab-meta-image.has-thumbnail > .tab-icon { +.tablist:not(.shrinked):not(.compact) .tab-meta-image.has-thumbnail > .tab-icon { margin-left: -2px; margin-top: 18px; } @@ -375,7 +379,7 @@ img, .tab *:not(.clickable) { flex-direction: column; } -#tablist.shrinked .tab-title-wrapper { +.tablist.shrinked:not(.compact) .tab-title-wrapper { margin-left: 6px; } @@ -388,7 +392,7 @@ img, .tab *:not(.clickable) { color: rgb(127, 127, 127); } -#tablist.shrinked .tab-host { +.tablist.shrinked:not(.compact) .tab-host { display: none; } @@ -404,6 +408,10 @@ img, .tab *:not(.clickable) { transform: translateX(36px); } +.tablist.pinned .tab-title-wrapper::after { + --tab-background: var(--tab-background-pinned); +} + .tab.active > .tab-title-wrapper::after { --tab-background: var(--tab-background-active); } @@ -416,6 +424,26 @@ img, .tab *:not(.clickable) { transform: translateX(0); } +.tablist:not(.compact) .tab.pinned > .tab-title-wrapper::after { + transform: translateX(8px); +} + +.tab-pin { + display: none; +} + +.tablist:not(.compact) .tab.pinned .tab-pin { + min-width: 16px; + height: 16px; + margin-right: 12px; + display: block; + background-image: url("img/glyph-pin-pinned-12.svg#standard"); + background-position: center center; + background-repeat: no-repeat; + background-size: 12px; + z-index: 0; +} + .tab-close { position: absolute; display: block; @@ -434,6 +462,10 @@ img, .tab *:not(.clickable) { opacity: 0; } +.tab.pinned .tab-close { + display: none; +} + .tab:hover > .tab-close { opacity: 1; } @@ -445,21 +477,25 @@ img, .tab *:not(.clickable) { background-color: hsla(0, 0%, 0%, 0.2) !important; } -#tablist.shrinked .tab { +.tablist.shrinked:not(.compact) .tab { height: 35px; } -#pinnedtablist { +.tablist.pinned { + flex-shrink: 0; + background-color: hsl(var(--tab-background-pinned)); +} + +.tablist.pinned.compact { display: flex; flex-wrap: wrap; - background-color: hsla(0, 0%, 0%, 0.02); } -#pinnedtablist:empty { +.tablist.pinned:empty { display: none; } -.tab.pinned > .tab-icon-overlay { +.tablist.pinned.compact .tab.pinned > .tab-icon-overlay { width: 13px; height: 13px; margin: 0 0 -13px 0px; @@ -469,21 +505,21 @@ img, .tab *:not(.clickable) { right: -13px; } -.tab.pinned > .tab-meta-image { +.tablist.pinned.compact .tab.pinned > .tab-meta-image { display: flex; justify-content: center; align-items: center; } -.tab.pinned .tab-icon { +.tablist.pinned.compact .tab.pinned .tab-icon { width: 22px; height: 22px; margin: 2px; } -.tab.pinned > .tab-context, -.tab.pinned > .tab-title-wrapper, -.tab.pinned > .tab-close { +.tablist.pinned.compact .tab.pinned > .tab-context, +.tablist.pinned.compact .tab.pinned > .tab-title-wrapper, +.tablist.pinned.compact .tab.pinned > .tab-close { display: none; } @@ -509,6 +545,7 @@ img, .tab *:not(.clickable) { /* DARK THEME CUSTOMIZATIONS */ body.dark-theme { --tab-background-normal: 223, 15.2%, 18%; + --tab-background-pinned: 221, 18%, 21%; --tab-background-active: 221, 41.4%, 33.1%; --tab-background-hover: 222, 28.3%, 25.55%; color: #c0c0c0; @@ -566,19 +603,23 @@ body.dark-theme .tab-icon-overlay { } body.dark-theme #newtab-icon { - filter: brightness(200%); + filter: brightness(200%); } body.dark-theme #settings { background-image: url("img/settings.svg#inverted"); } +body.dark-theme .tablist:not(.compact) .tab.pinned .tab-pin { + background-image: url("img/glyph-pin-pinned-12.svg#inverted"); +} + body.dark-theme .tab-close { background-image: url("img/glyph-close-16.svg#inverted"); } -body.dark-theme #tablist.shrinked .tab:hover .tab-icon, -body.dark-theme #pinnedtablist .tab:hover .tab-icon { +body.dark-theme .tablist.shrinked .tab:hover .tab-icon, +body.dark-theme .tablist.compact .tab:hover .tab-icon { background-color: #e6e6e6; filter: brightness(75%); } @@ -591,7 +632,8 @@ body.dark-theme .tab.active { color: #fff; } -body.dark-theme #tablist.shrinked .tab.active .tab-icon { +body.dark-theme .tablist.shrinked .tab.active .tab-icon, +body.dark-theme .tablist.compact .tab.active .tab-icon { background-color: #fff; filter: brightness(100%); } @@ -600,7 +642,3 @@ body.dark-theme #topmenu { background-color: #393f4c; } -body.dark-theme #pinnedtablist { - background-color: #2c323f; -} - diff --git a/src/tabcenter.html b/src/tabcenter.html index 2c3cc97..26236a9 100644 --- a/src/tabcenter.html +++ b/src/tabcenter.html @@ -18,8 +18,8 @@
-
-
+
+
diff --git a/src/tablist.js b/src/tablist.js index 8bbd1e7..8b786e4 100644 --- a/src/tablist.js +++ b/src/tablist.js @@ -5,6 +5,7 @@ function SideTabList() { this.tabs = new Map(); this.active = null; this.compactMode = false; + this._compactPins = true; this._tabsShrinked = false; this.windowId = null; this._filterActive = false; @@ -17,9 +18,12 @@ function SideTabList() { SideTabList.prototype = { async init() { - this.compactMode = (await browser.storage.local.get({ - compactMode: false - })).compactMode; + let options = (await browser.storage.local.get({ + compactMode: false, + compactPins: true + })); + this.compactPins = options.compactPins; + this.compactMode = options.compactMode; if (this.compactMode) { this.maybeShrinkTabs(); } @@ -78,6 +82,10 @@ SideTabList.prototype = { // Pref changes browser.storage.onChanged.addListener(changes => { + if (changes.compactPins) { + this.compactPins = changes.compactPins.newValue; + this.maybeShrinkTabs(); + } if (changes.compactMode) { this.compactMode = changes.compactMode.newValue; this.maybeShrinkTabs(); @@ -417,6 +425,17 @@ SideTabList.prototype = { getTabById(tabId) { return this.tabs.get(tabId, null); }, + get compactPins() { + return this._compactPins; + }, + set compactPins(compact) { + this._compactPins = compact; + if (compact) { + this.pinnedview.classList.add("compact"); + } else { + this.pinnedview.classList.remove("compact"); + } + }, get tabsShrinked() { return this._tabsShrinked; }, @@ -424,8 +443,10 @@ SideTabList.prototype = { this._tabsShrinked = shrinked; if (shrinked) { this.view.classList.add("shrinked"); + this.pinnedview.classList.add("shrinked"); } else { this.view.classList.remove("shrinked"); + this.pinnedview.classList.remove("shrinked"); } }, maybeShrinkTabs() { @@ -617,10 +638,6 @@ SideTabList.prototype = { if (this.active != tabId) { return; } - let sidetab = this.getTabById(tabId); - if (!sidetab || sidetab.pinned) { - return; - } const thumbnailBase64 = await browser.tabs.captureVisibleTab(this.windowId, { format: "png" });