1
0
mirror of https://github.com/XFox111/TabsAsideExtension.git synced 2026-04-22 07:58:01 +03:00

Minor 1.7 (#31)

- Complete UI/UX overhaul
- Updated default hotkeys (#27)
- Added option to disable deletion confirmation (#29)
- Added Chinese translation
- Fixed font artifacts on Windows

Co-authored-by: Dustin-Jiang <56217843+Dustin-Jiang@users.noreply.github.com>
Co-Authored-By: Michael Gordeev <michael@xfox111.net>
This commit is contained in:
Michael Gordeev
2020-08-05 12:07:11 +03:00
committed by GitHub
parent 1b7b419168
commit c777f1a60a
10 changed files with 354 additions and 191 deletions
+8 -1
View File
@@ -27,21 +27,28 @@
<input type="checkbox" id="swapIconAction"/>
<label loc="swapIconAction" for="swapIconAction">Set tabs aside on extension icon click (Alt+P or right-click to open the pane)</label>
</p>
<p>
<input type="checkbox" id="showDeleteDialog"/>
<label loc="showDeleteDialog" for="showDeleteDialog">Show confirmation dialog before deleting an item</label>
</p>
<hr/>
<div>
<button loc="github" value="https://github.com/xfox111/ChromiumTabsAside">Visit GitHub page</button>
<button loc="contributors" value="https://github.com/XFox111/ChromiumTabsAside/graphs/contributors">Project contributors</button>
<button loc="feedback" feedback-button>Leave feedback</button>
<button loc="buyMeACoffee" value="https://buymeacoffee.com/xfox111">Buy me a coffee!</button>
</div>
<hr/>
<p>
<small>v1.0</small><br />
<span loc="credits">Developed by Michael Gordeev</span> (<a href="https://twitter.com/xfox111"
target="_blank">@xfox111</a>)
</p>
</nav>
<button loc_alt="closePanel" class="btn remove" title="Close panel"></button>
</div>
<a class="saveTabs"><span class="iconArrowRight"></span> <span loc="setAside">Set current tabs aside</span></a>
<hr />
</header>
<section>
+13 -43
View File
@@ -19,14 +19,24 @@
"message": "Options",
"description": "Alternative text for options button in the pane"
},
"closePanel":
{
"message": "Close",
"description": "Alternative text for close panel button"
},
"loadOnRestore":
{
"message": "Load tabs on restore",
"description": "Label for option"
},
"showDeleteDialog":
{
"message": "Show confirmation dialog before deleting an item",
"description": "Label for option"
},
"swapIconAction":
{
"message": "Set tabs aside on extension icon click (Alt+P or right-click to open the pane)",
"message": "Set tabs aside on extension icon click (%TOGGLE_SHORTCUT% or right-click to open the pane)",
"description": "Label for option"
},
"github":
@@ -111,47 +121,7 @@
},
"tabs":
{
"message": "Tabs",
"description": "Collection tabs counter label"
},
"ago":
{
"message": "ago",
"description": "Human friendly timestamp part (e.g. 15 hour(s) ago)"
},
"minutes":
{
"message": "minute(s)",
"description": "Human friendly timestamp part (e.g. 15 minute(s) ago)"
},
"hours":
{
"message": "hour(s)",
"description": "Human friendly timestamp part (e.g. 15 hour(s) ago)"
},
"days":
{
"message": "day(s)",
"description": "Human friendly timestamp part (e.g. 15 day(s) ago)"
},
"weeks":
{
"message": "week(s)",
"description": "Human friendly timestamp part (e.g. 15 week(s) ago)"
},
"months":
{
"message": "month(s)",
"description": "Human friendly timestamp part (e.g. 15 month(s) ago)"
},
"years":
{
"message": "years(s)",
"description": "Human friendly timestamp part (e.g. 15 years(s) ago)"
},
"justNow":
{
"message": "Just now",
"description": "Human friendly timestamp part"
"message": "items",
"description": "Collection tabs counter label (e.g. 8 items)"
}
}
+13 -43
View File
@@ -19,14 +19,24 @@
"message": "Настройки",
"description": "Alternative text for options button in the pane"
},
"closePanel":
{
"message": "Закрыть",
"description": "Alternative text for close panel button"
},
"loadOnRestore":
{
"message": "Загружать вкладки после открытия",
"description": "Label for option"
},
"showDeleteDialog":
{
"message": "Показывать окно подтверждения перед удалением элемента",
"description": "Label for option"
},
"swapIconAction":
{
"message": "Откладывать вкладки при нажатии на иконку расширения (Alt+P или правая кнопка мыши для открытия панели)",
"message": "Откладывать вкладки при нажатии на иконку расширения (%TOGGLE_SHORTCUT% или правая кнопка мыши для открытия панели)",
"description": "Label for option"
},
"github":
@@ -111,47 +121,7 @@
},
"tabs":
{
"message": "Вкладок",
"description": "Collection tabs counter label"
},
"ago":
{
"message": "назад",
"description": "Human friendly timestamp part (e.g. 15 hour(s) ago)"
},
"minutes":
{
"message": "минут(ы)",
"description": "Human friendly timestamp part (e.g. 15 minute(s) ago)"
},
"hours":
{
"message": "час(ов)",
"description": "Human friendly timestamp part (e.g. 15 hour(s) ago)"
},
"days":
{
"message": "дней",
"description": "Human friendly timestamp part (e.g. 15 day(s) ago)"
},
"weeks":
{
"message": "недель",
"description": "Human friendly timestamp part (e.g. 15 week(s) ago)"
},
"months":
{
"message": "месяц(ев)",
"description": "Human friendly timestamp part (e.g. 15 month(s) ago)"
},
"years":
{
"message": "лет",
"description": "Human friendly timestamp part (e.g. 15 years(s) ago)"
},
"justNow":
{
"message": "Только что",
"description": "Human friendly timestamp part"
"message": "вкладок",
"description": "Collection tabs counter label (e.g. 8 items)"
}
}
+127
View File
@@ -0,0 +1,127 @@
{
"name":
{
"message": "搁置的标签页",
"description": "Extension name. Displayed in the manifest and pane header"
},
"description":
{
"message": "为Chromium浏览器提供旧版 Microsoft Edge 中的\"搁置标签页\" 功能",
"description": "Extension description"
},
"author":
{
"message": "Michael \"XFox\" Gordeev",
"description": "Author name"
},
"options":
{
"message": "设置",
"description": "Alternative text for options button in the pane"
},
"closePanel":
{
"message": "关闭",
"description": "Alternative text for close panel button"
},
"loadOnRestore":
{
"message": "在重新打开时加载页面",
"description": "Label for option"
},
"showDeleteDialog":
{
"message": "在删除项目之前显示确认对话框",
"description": "Label for option"
},
"swapIconAction":
{
"message": "点击拓展图标来搁置所有标签页 (按%TOGGLE_SHORTCUT%或右键来打开侧栏)",
"description": "Label for option"
},
"github":
{
"message": "查看GitHub页面",
"description": "Link title"
},
"contributors":
{
"message": "项目贡献者",
"description": "Link title"
},
"feedback":
{
"message": "给我们反馈",
"description": "Link title"
},
"buyMeACoffee":
{
"message": "给我买杯咖啡!",
"description": "Link title"
},
"credits":
{
"message": "由Michael 'XFox' Gordeev开发",
"description": "Options menu credits"
},
"setAside":
{
"message": "搁置当前的所有标签页",
"description": "Save collection action name. Used in the pane, extension context menu and manifest shortcuts"
},
"nothingSaved":
{
"message": "你目前没有搁置的标签页",
"description": "Placeholder for empty pane"
},
"removeTab":
{
"message": "从标签页集中移除标签页",
"description": "Button hint on a tab card"
},
"restoreTabs":
{
"message": "恢复标签页",
"description": "Collection restore action link name"
},
"more":
{
"message": "更多...",
"description": "Collections' more button title"
},
"restoreNoRemove":
{
"message": "恢复但不移除标签页",
"description": "Context action item name"
},
"removeCollection":
{
"message": "移除标签页集",
"description": "Collection remove action name"
},
"removeCollectionConfirm":
{
"message": "你确定要移除这个标签页集吗?",
"description": "Prompt dialog content on collection deletion"
},
"removeTabConfirm":
{
"message": "你确定要移除这个标签页吗?",
"description": "Prompt dialog content on one tab deletion"
},
"togglePaneContext":
{
"message": "打开或关闭侧栏",
"description": "Context action name. Used in extension context menu and manifest shortcuts"
},
"noTabsToSave":
{
"message": "没有可以搁置的标签页",
"description": "Alert dialog message when there's no tabs to save"
},
"tabs":
{
"message": "项",
"description": "Collection tabs counter label (e.g. 8 items)"
}
}
+73 -40
View File
@@ -18,7 +18,9 @@
right: 0px;
top: 0px;
bottom: 0px;
overflow: auto;
overflow: hidden;
display: grid;
grid-template-rows: auto 1fr;
width: 100%;
min-width: 500px;
@@ -36,7 +38,7 @@
aside[embedded]
{
width: 40% !important;
width: 500px !important;
}
.tabsAside.pane[opened]
@@ -47,37 +49,32 @@
/* Pane header*/
.tabsAside.pane > header
{
margin: 20px 40px;
z-index: 1;
padding: 14px 20px 16px 20px;
box-shadow: 0px 0px 5px rgba(0,0,0,.5);
background-color: white;
}
.tabsAside.pane > header > div
{
display: grid;
grid-template-columns: 1fr auto;
grid-template-columns: 1fr auto auto;
grid-column-gap: 10px;
margin-bottom: 29px;
}
.tabsAside.pane > header > div > h1
{
margin: 10px 0px;
font-weight: normal;
font-size: 21pt;
}
.tabsAside.pane > header > div > button
{
margin: auto;
margin: 0px 5px;
font-weight: 500;
font-size: 15pt;
}
.tabsAside.pane > header > div > nav
{
top: 70px;
right: 40px;
top: 45px;
right: 55px;
}
.tabsAside.pane > header nav > div
{
box-shadow: 0px 4px 5px -2px rgba(100, 100, 100, .5);
}
.tabsAside.pane > header nav > p
{
margin: 10px;
@@ -88,25 +85,35 @@
text-decoration: none;
}
.iconArrowRight
.saveTabs
{
width: 13px;
height: 13px;
display: inline-block;
background-repeat: no-repeat;
background-size: 13px;
background-position: center;
background-image: url("chrome-extension://__MSG_@@extension_id__/icons/arrowRight.svg");
display: inline-grid;
grid-template-columns: 16px auto;
grid-column-gap: 15px;
font-weight: 600;
}
.tabsAside.pane > header > hr
.iconArrowRight
{
border: 1px solid #8a8a8a;
width: 16px;
height: 16px;
display: inline-block;
background-repeat: no-repeat;
background-size: 16px;
background-position: center;
background-image: url("chrome-extension://__MSG_@@extension_id__/icons/arrowRight.svg");
margin: 2px;
}
.tabsAside.pane section
{
overflow: auto;
}
.tabsAside.pane > section > h2
{
margin: 0px 40px;
margin: 20px;
font-weight: normal;
}
@@ -116,11 +123,34 @@
transition: .2s;
}
.collectionSet
{
background-color: white;
margin: 10px;
border-radius: 5px;
border: 1px solid #eee;
}
.collectionSet:hover
{
box-shadow: 0px 0px 5px rgba(0, 0, 0, .25);
}
.collectionSet .header > *
{
visibility: hidden;
}
.collectionSet:hover .header > *
{
visibility: visible;
}
.collectionSet > .header
{
margin: 0px 20px;
margin: 10px 10px 0px 20px;
display: grid;
grid-template-columns: auto 1fr auto auto auto;
grid-template-columns: 1fr auto auto auto;
grid-column-gap: 10px;
align-items: center;
}
@@ -128,11 +158,14 @@
.collectionSet > .header > small
{
color: gray;
visibility: visible !important;
}
.collectionSet > .header > span
.collectionSet > .header > h4
{
font-weight: 600;
margin: 0px;
visibility: visible !important;
font-weight: 500;
}
.collectionSet > .header > a
@@ -149,8 +182,7 @@
/* Tabs collection */
.collectionSet > .set
{
margin: 0px 0px 0px 20px;
padding: 10px 40px 10px 20px;
padding: 5px 10px;
white-space: nowrap;
overflow: auto;
}
@@ -179,14 +211,15 @@
display: inline-grid;
grid-template-rows: 1fr auto;
box-shadow: 0px 0px 5px rgba(100, 100, 100, .5);
transition: .25s;
cursor: pointer;
border: 1px solid #eee;
border-radius: 5px;
}
.collectionSet > .set > div:hover
{
filter: brightness(120%);
box-shadow: 0px 0px 15px rgba(100, 100, 100, .5);
box-shadow: 0px 0px 5px rgba(100, 100, 100, .5);
}
.collectionSet > .set > div > div
@@ -213,7 +246,7 @@
{
width: 20px;
height: 20px;
margin: 10px;
margin: 8px;
background-image: url("chrome-extension://__MSG_@@extension_id__/images/tab_icon.png");
background-size: 20px;
+17
View File
@@ -9,6 +9,16 @@
color: white;
}
.tabsAside[darkmode] .pane header .iconArrowRight
{
filter: invert();
}
.tabsAside[darkmode] .pane header
{
background-color: #3b3b3b;
}
.tabsAside[darkmode] .saveTabs > div
{
filter: invert();
@@ -50,11 +60,18 @@
background: dimgray;
}
.tabsAside[darkmode] .pane .collectionSet
{
background-color: #3b3b3b;
border-color: #444;
}
/* Tab style */
.tabsAside[darkmode] .pane .collectionSet > .set > div
{
background-color: #0c0c0c;
background-image: url("chrome-extension://__MSG_@@extension_id__/images/tab_thumbnail_dark.png");
border-color: #444;
}
.tabsAside[darkmode] .pane .collectionSet > .set > div > div
+23 -7
View File
@@ -17,7 +17,7 @@
.tabsAside
{
font-family: 'DefaultFont';
font-family: 'Segoe UI' ,'DefaultFont';
font-size: 14px;
user-select: none;
}
@@ -41,15 +41,15 @@
/* Buttons style */
.tabsAside button
{
width: 32px;
height: 32px;
width: 28px;
height: 28px;
background-color: transparent;
border: none;
cursor: pointer;
}
.tabsAside button:hover
{
background-color: #c6c6c6;
background-color: #f2f2f2;
}
.tabsAside button:active
{
@@ -62,25 +62,41 @@
user-select: none;
position: absolute;
width: 250px;
width: 290px;
box-shadow: 0px 0px 10px black;
box-shadow: 0px 0px 10px rgba(0,0,0,.5);
background-color: white;
border-radius: 5px;
z-index: 10;
visibility: hidden;
padding: 4px 0px;
}
.tabsAside nav hr
{
border: none;
height: 1px;
background-color: lightgray;
}
.tabsAside nav button
{
text-align: start;
padding: 0px 10px;
width: 100%;
height: 32px;
font-family: 'Segoe UI' ,'DefaultFont';
}
.tabsAside nav button:hover
{
background-color: #eeee;
}
.tabsAside button + nav:active,
.tabsAside button:focus + nav
{
@@ -91,7 +107,7 @@
.btn
{
background-repeat: no-repeat;
background-size: 15px;
background-size: 12px;
background-position: center;
}
+65 -53
View File
@@ -71,6 +71,9 @@ function Initialize()
}
document.querySelector(".tabsAside .saveTabs").onclick = SetTabsAside;
document.querySelector(".tabsAside header .btn.remove").addEventListener("click", () =>
chrome.runtime.sendMessage({ command: "togglePane" })
);
document.querySelector("nav > p > small").textContent = chrome.runtime.getManifest()["version"];
@@ -114,6 +117,26 @@ function Initialize()
})
);
// Deletion confirmation dialog
var showDeleteDialog = document.querySelector("#showDeleteDialog");
chrome.storage.sync.get(
{ "showDeleteDialog": true },
values => showDeleteDialog.checked = values.showDeleteDialog
);
chrome.storage.onChanged.addListener((changes, namespace) =>
{
if (namespace == 'sync')
for (key in changes)
if (key === 'showDeleteDialog')
showDeleteDialog.checked = changes[key].newValue
});
showDeleteDialog.addEventListener("click", () =>
chrome.storage.sync.set(
{
"showDeleteDialog": showDeleteDialog.checked
})
);
document.querySelectorAll(".tabsAside.pane > header nav button").forEach(i =>
i.onclick = () =>
{
@@ -142,6 +165,9 @@ function UpdateLocale()
{
document.querySelectorAll("*[loc]").forEach(i => i.textContent = chrome.i18n.getMessage(i.getAttribute("loc")));
document.querySelectorAll("*[loc_alt]").forEach(i => i.title = chrome.i18n.getMessage(i.getAttribute("loc_alt")));
var swapActionsLabel = document.querySelector("label[loc=swapIconAction]");
chrome.commands.getAll((commands) => swapActionsLabel.textContent = swapActionsLabel.textContent.replace("%TOGGLE_SHORTCUT%", commands[2].shortcut));
}
function AddCollection(collection)
@@ -159,7 +185,7 @@ function AddCollection(collection)
"<div>" +
"<div" + ((collection.icons[i] == 0 || collection.icons[i] == null) ? "" : " style='background-image: url(\"" + collection.icons[i] + "\")'") + "></div>" +
"<span>" + collection.titles[i] + "</span>" +
"<button loc_alt='name' class='btn remove' title='Remove tab from collection'></button>" +
"<button loc_alt='removeTab' class='btn remove' title='Remove tab from collection'></button>" +
"</div>" +
"</div>";
}
@@ -167,8 +193,7 @@ function AddCollection(collection)
list.innerHTML +=
"<div class='collectionSet'>" +
"<div class='header'>" +
"<span>" + chrome.i18n.getMessage("tabs") + ": " + collection.links.length + "</span>" +
"<small>" + GetAgo(collection.timestamp) + "</small>" +
"<h4>" + new Date(collection.timestamp).toDateString() + "</h4>" +
"<a loc='restoreTabs' class='restoreCollection'>Restore tabs</a>" +
"<div>" +
"<button loc_alt='more' class='btn more' title='More...'></button>" +
@@ -177,6 +202,7 @@ function AddCollection(collection)
"</nav>" +
"</div>" +
"<button loc_alt='removeCollection' class='btn remove' title='Remove collection'></button>" +
"<small>" + collection.links.length + " " + chrome.i18n.getMessage("tabs") +"</small>" +
"</div>" +
"<div class='set' class='tabsList'>" + rawTabs + "</div>" +
@@ -229,61 +255,47 @@ function RestoreTabs(collectionData, removeCollection = true)
function RemoveTabs(collectionData)
{
if (!confirm(chrome.i18n.getMessage("removeCollectionConfirm")))
return;
chrome.storage.sync.get({ "showDeleteDialog": true }, values =>
{
if (values.showDeleteDialog && !confirm(chrome.i18n.getMessage("removeCollectionConfirm")))
return;
chrome.runtime.sendMessage(
{
command: "deleteTabs",
collectionIndex: Array.prototype.slice.call(collectionData.parentElement.children).indexOf(collectionData) - 1
},
() => RemoveCollectionElement(collectionData)
);
chrome.runtime.sendMessage(
{
command: "deleteTabs",
collectionIndex: Array.prototype.slice.call(collectionData.parentElement.children).indexOf(collectionData) - 1
},
() => RemoveCollectionElement(collectionData)
);
});
}
function RemoveOneTab(tabData)
{
if (!confirm(chrome.i18n.getMessage("removeTabConfirm")))
return;
chrome.storage.sync.get({ "showDeleteDialog": true }, values =>
{
if (values.showDeleteDialog && !confirm(chrome.i18n.getMessage("removeTabConfirm")))
return;
chrome.runtime.sendMessage(
{
command: "removeTab",
collectionIndex: Array.prototype.slice.call(tabData.parentElement.parentElement.parentElement.children).indexOf(tabData.parentElement.parentElement) - 1,
tabIndex: Array.prototype.slice.call(tabData.parentElement.children).indexOf(tabData)
},
() =>
{
tabData.parentElement.previousElementSibling.children[0].textContent = chrome.i18n.getMessage("tabs") + ": " + (tabData.parentElement.children.length - 1);
if (tabData.parentElement.children.length < 2)
chrome.runtime.sendMessage(
{
RemoveElement(tabData.parentElement.parentElement);
if (document.querySelector("tabsAside.pane > section").children.length < 2)
setTimeout(() => document.querySelector(".tabsAside.pane > section > h2").removeAttribute("hidden"), 250);
}
else
RemoveElement(tabData);
});
}
function GetAgo(timestamp)
{
var minutes = (Date.now() - timestamp) / 60000;
if (minutes < 1)
return chrome.i18n.getMessage("justNow");
else if (minutes < 60)
return Math.floor(minutes) + " " + chrome.i18n.getMessage("minutes") + " " + chrome.i18n.getMessage("ago");
else if (minutes < 24 * 60)
return Math.floor(minutes / 60) + " " + chrome.i18n.getMessage("hours") + " " + chrome.i18n.getMessage("ago");
else if (minutes < 7 * 24 * 60)
return Math.floor(minutes / 24 / 60) + " " + chrome.i18n.getMessage("days") + " " + chrome.i18n.getMessage("ago");
else if (minutes < 30 * 24 * 60)
return Math.floor(minutes / 7 / 24 / 60) + " " + chrome.i18n.getMessage("weeks") + " " + chrome.i18n.getMessage("ago");
else if (minutes < 365 * 24 * 60)
return Math.floor(minutes / 30 / 24 / 60) + " " + chrome.i18n.getMessage("months") + " " + chrome.i18n.getMessage("ago");
else
return Math.floor(minutes / 365 / 24 / 60) + " " + chrome.i18n.getMessage("years") + " " + chrome.i18n.getMessage("ago");
command: "removeTab",
collectionIndex: Array.prototype.slice.call(tabData.parentElement.parentElement.parentElement.children).indexOf(tabData.parentElement.parentElement) - 1,
tabIndex: Array.prototype.slice.call(tabData.parentElement.children).indexOf(tabData)
},
() =>
{
tabData.parentElement.previousElementSibling.children[0].textContent = chrome.i18n.getMessage("tabs") + ": " + (tabData.parentElement.children.length - 1);
if (tabData.parentElement.children.length < 2)
{
RemoveElement(tabData.parentElement.parentElement);
if (document.querySelector("tabsAside.pane > section").children.length < 2)
setTimeout(() => document.querySelector(".tabsAside.pane > section > h2").removeAttribute("hidden"), 250);
}
else
RemoveElement(tabData);
});
});
}
function RemoveElement(el)
@@ -294,7 +306,7 @@ function RemoveElement(el)
function RemoveCollectionElement(el)
{
RemoveElement(el);
if (el.parentElement.children.length < 2)
if (el.parentElement.children.length < 3)
setTimeout(() => document.querySelector(".tabsAside.pane > section > h2").removeAttribute("hidden"), 250);
RemoveElement(el);
}
+9
View File
@@ -116,6 +116,15 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) =>
RemoveTab(message.collectionIndex, message.tabIndex);
sendResponse();
break;
case "togglePane":
chrome.tabs.query(
{
active: true,
currentWindow: true
},
(tabs) => TogglePane(tabs[0])
)
break;
}
});
+6 -4
View File
@@ -1,6 +1,6 @@
{
"name": "__MSG_name__",
"version": "1.6.1",
"version": "1.7",
"manifest_version": 2,
"description": "__MSG_description__",
"author": "__MSG_author__",
@@ -38,7 +38,8 @@
"description": "__MSG_setAside__",
"suggested_key":
{
"default": "Alt+Left"
"default": "Alt+Left",
"mac": "MacCtrl+T"
}
},
"toggle-pane":
@@ -46,8 +47,9 @@
"description": "__MSG_togglePaneContext__",
"suggested_key":
{
"default": "Alt+P"
"default": "Alt+P",
"mac": "Command+Shift+P"
}
}
}
}
}