3 Commits

Author SHA1 Message Date
s2
81f731ad77 bo 2017-12-11 22:29:30 +01:00
s2
e13a5b4c3b nicyties 2017-12-11 21:28:27 +01:00
s2
23564b3c29 just text 2017-12-11 21:27:14 +01:00
10 changed files with 34 additions and 171 deletions

View File

@@ -2,8 +2,6 @@
## What it does ## What it does
**Please install [Tree Style Tab](https://addons.mozilla.org/firefox/addon/tree-style-tab/) before installing this extension, because this extension depends on it!**
This addon would like to color tabs based on the parent tab that opened the tab. This addon would like to color tabs based on the parent tab that opened the tab.
So say I am at work searching for a solution to a javascript problem on stackoverflow, so I open a bunch of tabs with possible solutions. Then I get distracted, and I start looking for honey badger images on google images, I open a bunch of tabs with honey badger images. So say I am at work searching for a solution to a javascript problem on stackoverflow, so I open a bunch of tabs with possible solutions. Then I get distracted, and I start looking for honey badger images on google images, I open a bunch of tabs with honey badger images.
Now all my tabs are mixed up with javascript snippets and honey badgers. Now all my tabs are mixed up with javascript snippets and honey badgers.
@@ -14,7 +12,4 @@ At the moment this is not possible because of Firefox bug [1320585](https://bugz
So this extension **tries** to get the favicon of the newly opened tab, and changes the color of the favicon to match that of the parent. So this extension **tries** to get the favicon of the newly opened tab, and changes the color of the favicon to match that of the parent.
But it will not work **Please install [Tree Style Tab](https://addons.mozilla.org/firefox/addon/tree-style-tab/) before installing this extension, because this extension depends on it!**
- on pages that don't allow content scripts (amo for example)
- on pages that dynamically change the favicon
- a lot of other cases

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

107
src/bg.js
View File

@@ -1,39 +1,22 @@
const kTST_ID = 'treestyletab@piro.sakura.ne.jp'; const kTST_ID = 'treestyletab@piro.sakura.ne.jp';
const MY_EXTENSION_NAME = 'tab-groupcolor'; const MY_EXTENSION_NAME = 'tab-groupcolor';
let tabIcons = {};
var changeIcon = function(color, currentIcon, options) { var changeIcon = function(color, currentIcon) {
var canvas = document.createElement('canvas'); var canvas = document.createElement('canvas');
canvas.width = 16;
canvas.height = 16;
var ctx = canvas.getContext('2d'); var ctx = canvas.getContext('2d');
var img = new Image(); var img = new Image();
img.src = currentIcon;
if (currentIcon && typeof(currentIcon) !== 'undefined' && currentIcon !== null && currentIcon !== 'undefined') {
img.src = currentIcon;
} else {
img.src = 'data:image/x-icon;base64,AAABAAEAEBACAAEAAQCwAAAAFgAAACgAAAAQAAAAIAAAAAEAAQAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA';
}
img.onload = function() { img.onload = function() {
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
ctx.drawImage(img, 0, 0); ctx.drawImage(img, 0, 0);
ctx.fillStyle = color; ctx.fillStyle = color;
if (options.globals.orientation === 'vertical') { ctx.fillRect(0, 0, 2, 16);
ctx.fillRect(0, 0, (options.globals.width / 16) * canvas.width, canvas.height);
} else {
ctx.fillRect(0, 0, canvas.width, (options.globals.width / 16) * canvas.height);
}
var link = document.createElement('link'); var link = document.createElement('link');
link.type = 'image/x-icon'; link.type = 'image/x-icon';
link.rel = 'shortcut icon'; link.rel = 'shortcut icon';
link.href = canvas.toDataURL("image/x-icon"); link.href = canvas.toDataURL("image/x-icon");
link.id = 'tab-groupcolor' + '-favicon';
var oldicon = document.getElementById('tab-groupcolor' + '-favicon');
if (oldicon) {
oldicon.outerHTML = '';
delete oldicon;
}
document.getElementsByTagName('head')[0].appendChild(link); document.getElementsByTagName('head')[0].appendChild(link);
} }
}; };
@@ -68,22 +51,14 @@ var getTabParent = (tabs, id, currentTopLevelTabPos) => {
for (let i = 0; i < tabs.length; i++) { for (let i = 0; i < tabs.length; i++) {
//on a root node because there is no opener //on a root node because there is no opener
if (!tabs[i].openerTabId || typeof(tabs[i].openerTabId) === 'undefined' || tabs[i].openerTabId === tabs[i].id) { if (typeof(tabs[i].openerTabId) === 'undefined' || tabs[i].openerTabId === tabs[i].id) {
currentTopLevelTabPos = i; currentTopLevelTabPos = i;
} }
if (tabs[i].id === id) { if (tabs[i].id === id) {
//get original favicon for this tab
let orginalFavIconUrl = tabIcons[id];
if (!orginalFavIconUrl) {
orginalFavIconUrl = tabs[i].favIconUrl;
tabIcons[id] = orginalFavIconUrl;
}
return { return {
parentIndex: currentTopLevelTabPos, parentIndex: currentTopLevelTabPos,
faviconUrl: orginalFavIconUrl faviconUrl: tabs[i].faviconUrl
}; };
} else { } else {
if (tabs[i].children && tabs[i].children.length > 0) { if (tabs[i].children && tabs[i].children.length > 0) {
@@ -101,36 +76,18 @@ var updateAllColorsOnAllTabs = async () => {
allWindows.forEach(async w => { allWindows.forEach(async w => {
var tstTabs = await browser.runtime.sendMessage(kTST_ID, { var tstTabs = await browser.runtime.sendMessage(kTST_ID, {
type: 'get-tree', type: 'get-tree',
window: w.id window: w.id
}); });
var changeTabs = async (tabs) => { for (let i = 0; i < tstTabs.length; i++) {
if (tstTabs[i].status === 'complete') {
for (let i = 0; i < tabs.length; i++) { let t = getTabParent(tstTabs, tstTabs[i].id);
browser.tabs.executeScript(tstTabs[i].id, {
if (tabs[i].status === 'complete') { code: '(' + changeIcon.toString() + ')' +
let t = getTabParent(tstTabs, tabs[i].id); '("' + generateRandomColor(t.parentIndex) + '", "' + t.faviconUrl + '")'
let options = await loadOptions(); });
let tabHost = new URL(tabs[i].url).host;
if (tabHost) {
tabHost = tabHost.toLowerCase();
}
if (!(options.ignore && options.ignore.split('\n').includes(tabHost))) {
browser.tabs.executeScript(tabs[i].id, {
code: '(' + changeIcon.toString() + ')' +
'("' + generateRandomColor(t.parentIndex) + '", "' + t.faviconUrl + '", ' + JSON.stringify(options) + ')'
});
}
}
if (tabs[i].children && tabs[i].children.length > 0) {
await changeTabs(tabs[i].children);
}
} }
}; }
await changeTabs(tstTabs);
}); });
} }
@@ -147,25 +104,21 @@ browser.runtime.onMessageExternal.addListener((aMessage, aSender) => {
} }
}); });
//when something happens with a tab //when a tab is created
let tabEvents = ['onAttached', 'onDetached', 'onMoved', 'onRemoved'] browser.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
tabEvents.forEach((ev) => { var tstTabs = await browser.runtime.sendMessage(kTST_ID, {
browser.tabs[ev].addListener((tabId, changeInfo, tab) => { type: 'get-tree',
updateAllColorsOnAllTabs(); window: tab.windowId
}); });
if (tab.status === 'complete') {
var t = getTabParent(tstTabs, tab.id);
browser.tabs.executeScript(tab.id, {
code: '(' + changeIcon.toString() + ')' +
'("' + generateRandomColor(t.parentIndex) + '", "' + t.faviconUrl + '")'
});
}
}); });
//when a tab reloads
browser.webNavigation.onCompleted.addListener((details) => {
delete tabIcons[details.tabId];
updateAllColorsOnAllTabs();
});
//when the options are updated
browser.storage.onChanged.addListener((changes) => {
updateAllColorsOnAllTabs();
});
registerToTST(); // aggressive registration on initial installation registerToTST(); // aggressive registration on initial installation

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 432 KiB

After

Width:  |  Height:  |  Size: 435 KiB

View File

@@ -2,7 +2,7 @@
"description": "Color tabs based on their parent.", "description": "Color tabs based on their parent.",
"manifest_version": 2, "manifest_version": 2,
"name": "Color Tab Group", "name": "Color Tab Group",
"version": "0.0.9", "version": "0.0.1",
"homepage_url": "https://git.e.tern.al/s2/tab-groupcolor", "homepage_url": "https://git.e.tern.al/s2/tab-groupcolor",
"icons": { "icons": {
"48": "img/icon-48.png" "48": "img/icon-48.png"
@@ -14,15 +14,9 @@
} }
}, },
"background": { "background": {
"scripts": ["bg.js", "utils.js"] "scripts": ["bg.js"]
}, },
"permissions": [ "permissions": [
"storage",
"webNavigation",
"<all_urls>" "<all_urls>"
], ]
"options_ui": {
"browser_style": true,
"page": "options/options.html"
}
} }

View File

@@ -1,44 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<section id="options-section" class="panel">
<div class="panel-section panel-section-header">
<span class="text-section-header">Indicator options</span>
</div>
<div class="panel-section panel-section-formElements">
<div class="panel-formElements-item browser-style">
<label for="indicator-width">Width:</label>
<input type="number" id="indicator-width" max="16" min="1">
</div>
<div class="panel-formElements-item browser-style">
<label for="indicator-orientation">Orientation:</label>
<select id="indicator-orientation">
<option value="vertical">Vertical</option>
<option value="horizontal">Horizontal</option>
</select>
</div>
<div class="panel-formElements-item browser-style">
<label for="ignore">Ignore hosts (one per line - ex.: google.com):</label>
</div>
<div class="panel-formElements-item browser-style">
<textarea id="ignore"></textarea>
</div>
</div>
</section>
<script src="../utils.js"></script>
<script src="options.js"></script>
</body>
</html>

View File

@@ -1,27 +0,0 @@
function persistOptions() {
var globals = {}; //global addon options
globals = {
width: document.querySelector('#indicator-width').value,
orientation: document.querySelector('#indicator-orientation').value,
ignore: document.querySelector('#ignore').value
};
return browser.storage.local.set({
globals: globals
});
}
document.addEventListener('DOMContentLoaded', () => {
loadOptions().then((options) => {
document.querySelector('#indicator-width').value = options.globals.width;
document.querySelector('#indicator-orientation').value = options.globals.orientation;
});
});
var list = document.querySelectorAll('select,input,textarea');
for (var i = 0; i < list.length; i++) {
list[i].addEventListener('change', (ev) => {
persistOptions();
});
}

View File

@@ -1,8 +0,0 @@
function loadOptions() {
return browser.storage.local.get({
globals: {
width: 3,
orientation: 'vertical'
}
});
}