10 Commits

Author SHA1 Message Date
s2
ebeeab9ed5 v0.0.5 2017-12-12 22:31:55 +01:00
s2
1f8fb529d6 fix icons 2017-12-12 22:28:29 +01:00
s2
56c58896b8 reformat 2017-12-12 15:00:45 +01:00
s2
ac83798388 v0.0.4 2017-12-12 14:24:25 +01:00
s2
ad4af7871a add options 2017-12-12 14:22:32 +01:00
s2
01aa8eba44 make indicator larger 2017-12-12 09:36:51 +01:00
s2
594e53b38f screenshot 2017-12-12 09:20:19 +01:00
s2
b393e4f859 v0.0.3 2017-12-12 09:01:00 +01:00
s2
ffa5b59615 handle no favicon 2017-12-12 09:00:41 +01:00
s2
e73e806dca readme 2017-12-12 08:34:23 +01:00
7 changed files with 132 additions and 16 deletions

View File

@@ -2,6 +2,8 @@
## 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.
@@ -12,4 +14,7 @@ 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.
**Please install [Tree Style Tab](https://addons.mozilla.org/firefox/addon/tree-style-tab/) before installing this extension, because this extension depends on it!** But it will not work
- on pages that don't allow content scripts (amo for example)
- on pages that dynamically change the favicon
- a lot of other cases

View File

@@ -1,17 +1,29 @@
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) { var changeIcon = function(color, currentIcon, options) {
var canvas = document.createElement('canvas'); var canvas = document.createElement('canvas');
canvas.width = 16; canvas.width = 16;
canvas.height = 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() {
ctx.drawImage(img, 0, 0); ctx.drawImage(img, 0, 0);
ctx.fillStyle = color; ctx.fillStyle = color;
ctx.fillRect(0, 0, 2, 16); if (options.globals.orientation === 'vertical') {
ctx.fillRect(0, 0, options.globals.width, 16);
} else {
ctx.fillRect(0, 0, 16, options.globals.width);
}
var link = document.createElement('link'); var link = document.createElement('link');
link.type = 'image/x-icon'; link.type = 'image/x-icon';
@@ -51,14 +63,22 @@ 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 (typeof(tabs[i].openerTabId) === 'undefined' || tabs[i].openerTabId === tabs[i].id) { if (!tabs[i].openerTabId || 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: tabs[i].favIconUrl faviconUrl: orginalFavIconUrl
}; };
} else { } else {
if (tabs[i].children && tabs[i].children.length > 0) { if (tabs[i].children && tabs[i].children.length > 0) {
@@ -76,28 +96,30 @@ 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 = (tabs) => { var changeTabs = async (tabs) => {
for (let i = 0; i < tabs.length; i++) { for (let i = 0; i < tabs.length; i++) {
if (tabs[i].status === 'complete') { if (tabs[i].status === 'complete') {
let t = getTabParent(tstTabs, tabs[i].id); let t = getTabParent(tstTabs, tabs[i].id);
let options = await loadOptions();
browser.tabs.executeScript(tabs[i].id, { browser.tabs.executeScript(tabs[i].id, {
code: '(' + changeIcon.toString() + ')' + code: '(' + changeIcon.toString() + ')' +
'("' + generateRandomColor(t.parentIndex) + '", "' + t.faviconUrl + '")' '("' + generateRandomColor(t.parentIndex) + '", "' + t.faviconUrl + '", ' + JSON.stringify(options) + ')'
}); });
} }
if (tabs[i].children && tabs[i].children.length > 0) { if (tabs[i].children && tabs[i].children.length > 0) {
changeTabs(tabs[i].children); await changeTabs(tabs[i].children);
} }
} }
}; };
changeTabs(tstTabs); await changeTabs(tstTabs);
}); });
@@ -116,12 +138,24 @@ browser.runtime.onMessageExternal.addListener((aMessage, aSender) => {
}); });
//when something happens with a tab //when something happens with a tab
let tabEvents = ['onUpdated', 'onAttached', 'onDetached', 'onMoved', 'onRemoved'] let tabEvents = ['onAttached', 'onDetached', 'onMoved', 'onRemoved']
tabEvents.forEach((ev) => { tabEvents.forEach((ev) => {
browser.tabs[ev].addListener(async (tabId, changeInfo, tab) => { browser.tabs[ev].addListener((tabId, changeInfo, tab) => {
updateAllColorsOnAllTabs(); updateAllColorsOnAllTabs();
}); });
}); });
//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

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.2", "version": "0.0.5",
"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,9 +14,15 @@
} }
}, },
"background": { "background": {
"scripts": ["bg.js"] "scripts": ["bg.js", "utils.js"]
}, },
"permissions": [ "permissions": [
"storage",
"webNavigation",
"<all_urls>" "<all_urls>"
] ],
"options_ui": {
"browser_style": true,
"page": "options/options.html"
}
} }

37
src/options/options.html Normal file
View File

@@ -0,0 +1,37 @@
<!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>
</section>
<script src="../utils.js"></script>
<script src="options.js"></script>
</body>
</html>

26
src/options/options.js Normal file
View File

@@ -0,0 +1,26 @@
function persistOptions() {
var globals = {}; //global addon options
globals = {
width: document.querySelector('#indicator-width').value,
orientation: document.querySelector('#indicator-orientation').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');
for (var i = 0; i < list.length; i++) {
list[i].addEventListener('change', (ev) => {
persistOptions();
});
}

BIN
src/screenshots/firefox.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

8
src/utils.js Normal file
View File

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