1.7.2 - 1. Added one option for new tabs from toolbar 2. Added hints in options page 3. New tabs in background are added in queue, so order is always correct 4. Changed visual style for tab counters

This commit is contained in:
karol@jagiello.it 2018-07-09 00:16:44 +02:00
parent ef57faa773
commit 6211e85683
28 changed files with 519 additions and 503 deletions

File diff suppressed because one or more lines are too long

View File

@ -48,5 +48,5 @@
"page": "options.html",
"open_in_tab": true
},
"version": "1.7.1"
"version": "1.7.2"
}

View File

@ -31,5 +31,5 @@
"description": "close tree"
}
},
"version": "1.6.1"
"version": "1.7.2"
}

View File

@ -25,5 +25,5 @@
"description": "close tree"
}
},
"version": "1.7.0"
"version": "1.7.2"
}

View File

@ -1,201 +0,0 @@
// Copyright (c) 2017 kroppy. All rights reserved.
// Use of this source code is governed by a Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0) license
// that can be found at https://creativecommons.org/licenses/by-nc-nd/4.0/
if (localStorage.getItem("t0") != null){
LoadV015(0);
}
function OldHashTab(tab){
if (tabs[tab.id] == undefined){
tabs[tab.id] = {ttid: "", hash: 0, h: 0, parent: tab.pinned ? "pin_list" : "tab_list", index: tab.index, expand: ""};
}
var hash = 0;
if (tab.url.length === 0){
return 0;
}
for (var i = 0; i < tab.url.length; i++){
hash = (hash << 5)-hash;
hash = hash+tab.url.charCodeAt(i);
hash |= 0;
}
tabs[tab.id].h = hash;
}
function LoadV015(retry){
var loaded_options = {};
for (var parameter in DefaultPreferences) {
opt[parameter] = DefaultPreferences[parameter];
}
// set loaded options
if (localStorage.getItem("current_options") !== null){
loaded_options = JSON.parse(localStorage["current_options"]);
}
for (var parameter in opt) {
if (loaded_options[parameter] != undefined && opt[parameter] != undefined){
opt[parameter] = loaded_options[parameter];
}
}
SavePreferences();
if (localStorage.getItem("current_options") !== null){
localStorage.removeItem("current_options");
}
chrome.tabs.query({windowType: "normal"}, function(qtabs){
// create current tabs object
qtabs.forEach(function(Tab){
OldHashTab(Tab);
});
var reference_tabs = {};
var tabs_to_save = [];
var tabs_matched = 0;
// compare saved tabs from storage to current session tabs, but can be skipped if set in options
qtabs.forEach(function(Tab){
for (var t = 0; t < 9999; t++){
if (localStorage.getItem("t"+t) !== null){
var LoadedTab = JSON.parse(localStorage["t"+t]);
if (LoadedTab[1] === tabs[Tab.id].h && reference_tabs[LoadedTab[0]] == undefined){
reference_tabs[LoadedTab[0]] = Tab.id;
tabs[Tab.id].parent = LoadedTab[2];
tabs[Tab.id].index = LoadedTab[3];
tabs[Tab.id].expand = LoadedTab[4];
tabs_matched++;
break;
}
} else {
break;
}
}
});
// replace parents tabIds to new ones, for that purpose reference_tabs was made before
for (var tabId in tabs){
if (reference_tabs[tabs[tabId].parent] != undefined){
tabs[tabId].parent = reference_tabs[tabs[tabId].parent];
}
}
// create new hashes
qtabs.forEach(function(Tab){
ChromeHashURL(Tab);
});
qtabs.forEach(function(Tab){
tabs_to_save.push({id: Tab.id, hash: tabs[Tab.id].hash, parent: tabs[Tab.id].parent, index: tabs[Tab.id].index, expand: tabs[Tab.id].expand});
});
localStorage["t_count"] = JSON.stringify(qtabs.length);
localStorage["tabs"] = JSON.stringify(tabs_to_save);
for (var t = 0; t < 9999; t++){
if (localStorage.getItem("t"+t) !== null){
localStorage.removeItem("t"+t);
}
}
ConvertLegacyStorage();
});
}
function ConvertLegacyStorage() {
if (localStorage.getItem("current_theme") != null || localStorage.getItem("preferences") != null || localStorage.getItem("tabs") != null || localStorage.getItem("windows") != null) {
let current_theme = "";
if (localStorage.getItem("current_theme") != null) {
current_theme = localStorage["current_theme"];
}
let LSthemes = [];
if (localStorage.getItem("themes") != null) {
LSthemes = LoadData("themes", []);
}
SLThemes = {};
LSthemes.forEach(function(themeName) {
let them = LoadData("theme"+themeName, {"TabsSizeSetNumber": 2, "ToolbarShow": true, "toolbar": DefaultToolbar});
SLThemes[themeName] = them;
});
let LSpreferences = Object.assign({}, DefaultPreferences);
if (localStorage.getItem("preferences") != null) {
LSpreferences = LoadData("preferences", {});
}
let LStabs = {};
if (localStorage.getItem("tabs") != null) {
LStabs = LoadData("tabs", {});
}
let LSwindows = {};
if (localStorage.getItem("windows") != null) {
LSwindows = LoadData("windows", {});
}
let LStabs_BAK1 = {};
if (localStorage.getItem("tabs_BAK1") != null) {
LStabs_BAK1 = LoadData("tabs_BAK1", {});
}
let LStabs_BAK2 = {};
if (localStorage.getItem("tabs_BAK2") != null) {
LStabs_BAK2 = LoadData("tabs_BAK2", {});
}
let LStabs_BAK3 = {};
if (localStorage.getItem("tabs_BAK3") != null) {
LStabs_BAK3 = LoadData("tabs_BAK3", {});
}
let LSwindows_BAK1 = {};
if (localStorage.getItem("windows_BAK1") != null) {
LSwindows_BAK1 = LoadData("windows_BAK1", {});
}
let LSwindows_BAK2 = {};
if (localStorage.getItem("windows_BAK2") != null) {
LSwindows_BAK2 = LoadData("windows_BAK2", {});
}
let LSwindows_BAK3 = {};
if (localStorage.getItem("windows_BAK3") != null) {
LSwindows_BAK3 = LoadData("windows_BAK3", {});
}
let LSt_count = 0;
if (localStorage.getItem("t_count") != null) {
LSt_count = LoadData("t_count", {});
}
let LSw_count = 0;
if (localStorage.getItem("w_count") != null) {
LSw_count = LoadData("w_count", {});
}
chrome.storage.local.set({tabs: LStabs});
chrome.storage.local.set({windows: LSwindows});
chrome.storage.local.set({tabs_BAK1: LStabs_BAK1});
chrome.storage.local.set({tabs_BAK2: LStabs_BAK2});
chrome.storage.local.set({tabs_BAK3: LStabs_BAK3});
chrome.storage.local.set({windows_BAK1: LSwindows_BAK1});
chrome.storage.local.set({windows_BAK2: LSwindows_BAK2});
chrome.storage.local.set({windows_BAK3: LSwindows_BAK3});
chrome.storage.local.set({t_count: LSt_count});
chrome.storage.local.set({w_count: LSw_count});
chrome.storage.local.set({preferences: LSpreferences});
chrome.storage.local.set({current_theme: current_theme});
chrome.storage.local.set({themes: SLThemes});
localStorage.clear();
window.location.reload();
}
}
function LoadData(KeyName, ExpectReturnDefaultType) {
var data = ExpectReturnDefaultType;
try {
data = JSON.parse(localStorage[KeyName]);
return data;
} catch(e) {
return ExpectReturnDefaultType;
}
}

View File

@ -245,6 +245,9 @@
"menu_groups_hibernate": {
"message": "Hibernate"
},
"menu_group_tabs_close": {
"message": "Close tabs"
},
@ -400,25 +403,37 @@
"message": " at the bottom"
},
"options_append_child_tab_after": {
"message": "after parent (no automatic tree)"
"message": "after parent tab (no automatic tree)"
},
"options_append_orphan_tab": {
"message": "Append orphan tabs (new tabs, tabs opened from shortcuts or from bookmarks)"
"message": "Append orphan tabs"
},
"options_append_orphan_tab_top": {
"message": "at the top"
"message": "at the top of the group"
},
"options_append_orphan_tab_after_active": {
"message": "after active"
"message": "after active tab"
},
"options_append_orphan_tab_bottom": {
"message": "at the bottom"
"message": "at the bottom of the group"
},
"options_append_orphan_tab_as_child": {
"message": "treat as active's tab child"
},
"options_toolbar_new_tab": {
"message": "Toolbar + (new tab button) should append tab"
},
"options_toolbar_new_tab_as_regular_orphan": {
"message": "as a regular orphan tab (option above)"
},
"options_toolbar_new_tab_root_of_group": {
"message": "at the bottom of the group"
},
"options_after_closing_active_tab": {
"message": "After closing active tab,"
},
@ -590,15 +605,37 @@
},
"options_toolbar_look": {
"message": " Toolbar's look "
},
"hint_orphan_tab": {
"message": "Orphan tab is a tab opened from an external source, which can be:"
},
"hint_ctrl_t": {
"message": "ctrl+t shortcut"
},
"hint_from_pin": {
"message": "link that opens new tab from pinned tab"
},
"hint_from_bookmark": {
"message": "bookmark"
},
"hint_from_external_link": {
"message": "external link"
},
"hint_from_popup": {
"message": "popup opened as a tab (settings in browser, popup blocker or similar)"
},
"hint_explained_new_tab_settings": {
"message": "+ button in Tree Tabs toolbar, places new tabs in the root of the active group, unless set differently."
},
"hint_explained_orphan_after_active_settings": {
"message": "If 'Append orphan tabs' is set to 'after active' and active tab is not in active group, tab will append to the root of the active group instead. But only if sidebar is open."
},
"button_background": {
"message": "Toolbar buttons background"

View File

@ -260,9 +260,7 @@ function QuantumLoadTabs(retry) {
QuantumAppendWinTTId(winId);
}
if (b.windows[winId].activeTabId == undefined) { // legacy
b.windows[winId].activeTabId = [0,0]; // legacy
} // legacy
b.windows[winId].activeTabId = 0; // legacy
for (let tIndex = 0; tIndex < tabsCount; tIndex++) {
@ -272,8 +270,7 @@ function QuantumLoadTabs(retry) {
let tabPinned = w[winIndex].tabs[tabIndex].pinned;
if (tab.active) {
b.windows[winId].activeTabId[0] = tabId;
b.windows[winId].activeTabId[1] = tabId;
b.windows[winId].activeTabId = tabId;
}
// LOAD TTID FROM FIREFOX GET TAB VALUE
@ -404,7 +401,7 @@ function QuantumAppendWinTTId(windowId) {
if (b.windows[windowId] != undefined) {
b.windows[windowId].ttid = NewTTWindowId;
} else {
b.windows[windowId] = {activeTabId: [0,0], ttid: NewTTWindowId, group_bar: opt.groups_toolbar_default, search_filter: "url", active_shelf: "", active_group: "tab_list", groups: {tab_list: {id: "tab_list", index: 0, active_tab: 0, active_tab_ttid: "", prev_active_tab: 0, prev_active_tab_ttid: "", name: labels.ungrouped_group, font: ""}}, folders: {}};
b.windows[windowId] = {activeTabId: 0, ttid: NewTTWindowId, group_bar: opt.groups_toolbar_default, search_filter: "url", active_shelf: "", active_group: "tab_list", groups: {tab_list: {id: "tab_list", index: 0, active_tab: 0, active_tab_ttid: "", prev_active_tab: 0, prev_active_tab_ttid: "", name: labels.ungrouped_group, font: ""}}, folders: {}};
}
// if (b.schedule_save > 0) browser.sessions.setWindowValue( windowId, "TTdata", b.windows[windowId] );
}
@ -493,8 +490,7 @@ function ChromiumLoadTabs(retry) {
ChromiumHashURL(w[wIndex].tabs[tabIndex]);
if (w[wIndex].tabs[tabIndex].active) {
b.windows[w[wIndex].id].activeTabId[0] = w[wIndex].tabs[tabIndex].id;
b.windows[w[wIndex].id].activeTabId[1] = w[wIndex].tabs[tabIndex].id;
b.windows[w[wIndex].id].activeTabId = w[wIndex].tabs[tabIndex].id;
}
}
@ -607,7 +603,7 @@ async function ChromiumAutoSaveData(BAK, LoopTimer) {
}
function ChromiumAddWindowData(winId) {
b.windows[winId] = {activeTabId: [0,0], group_bar: opt.groups_toolbar_default, search_filter: "url", active_shelf: "", active_group: "tab_list", groups: {tab_list: {id: "tab_list", index: 0, active_tab: 0, prev_active_tab: 0, name: labels.ungrouped_group, font: ""}}, folders: {}};
b.windows[winId] = {activeTabId: 0, group_bar: opt.groups_toolbar_default, search_filter: "url", active_shelf: "", active_group: "tab_list", groups: {tab_list: {id: "tab_list", index: 0, active_tab: 0, prev_active_tab: 0, name: labels.ungrouped_group, font: ""}}, folders: {}};
}
function ChromiumHashURL(tab) {

View File

@ -229,6 +229,8 @@ function QuantumStartListeners() {
browser.sidebarAction.open();
});
chrome.tabs.onCreated.addListener(function(tab) {
let prevActiveTabId = b.windows[tab.windowId].activeTabId;
b.NewTabsQueue.push(tab.id);
let t = Promise.resolve(browser.sessions.getTabValue(tab.id, "TTdata")).then(function(TabData) {
if (TabData != undefined) {
b.tabs[tab.id] = Object.assign({}, TabData);
@ -236,7 +238,7 @@ function QuantumStartListeners() {
chrome.runtime.sendMessage({command: "tab_created", windowId: tab.windowId, tabId: tab.id, tab: tab, ParentId: originalParent, InsertAfterId: undefined, Append: undefined});
} else {
QuantumAppendTabTTId(tab);
OnMessageTabCreated(tab.id);
OnMessageTabCreated(tab.id, prevActiveTabId);
}
});
});
@ -317,10 +319,7 @@ function QuantumStartListeners() {
});
chrome.tabs.onActivated.addListener(function(activeInfo) {
if (b.windows[activeInfo.windowId]) {
if (b.windows[activeInfo.windowId].activeTabId[1] != activeInfo.tabId) {
b.windows[activeInfo.windowId].activeTabId[0] = b.windows[activeInfo.windowId].activeTabId[1];
b.windows[activeInfo.windowId].activeTabId[1] = activeInfo.tabId;
}
b.windows[activeInfo.windowId].activeTabId = activeInfo.tabId;
}
chrome.runtime.sendMessage({command: "tab_activated", windowId: activeInfo.windowId, tabId: activeInfo.tabId});
b.schedule_save++;
@ -362,8 +361,9 @@ function QuantumStartListeners() {
function ChromiumStartListeners() { // start all listeners
chrome.tabs.onCreated.addListener(function(tab) {
b.NewTabsQueue.push(tab.id);
ChromiumHashURL(tab);
OnMessageTabCreated(tab.id);
OnMessageTabCreated(tab.id, b.windows[tab.windowId].activeTabId);
});
chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) {
if (b.EmptyTabs.indexOf(tabId) != -1) {
@ -432,10 +432,7 @@ function ChromiumStartListeners() { // start all listeners
});
chrome.tabs.onActivated.addListener(function(activeInfo) {
if (b.windows[activeInfo.windowId]) {
if (b.windows[activeInfo.windowId].activeTabId[1] != activeInfo.tabId) {
b.windows[activeInfo.windowId].activeTabId[0] = b.windows[activeInfo.windowId].activeTabId[1];
b.windows[activeInfo.windowId].activeTabId[1] = activeInfo.tabId;
}
b.windows[activeInfo.windowId].activeTabId = activeInfo.tabId;
}
chrome.runtime.sendMessage({command: "tab_activated", windowId: activeInfo.windowId, tabId: activeInfo.tabId});
b.schedule_save++;
@ -457,7 +454,8 @@ function ChromiumStartListeners() { // start all listeners
function OnMessageTabCreated(tabId) {
function OnMessageTabCreated(tabId, activeTabId) {
if (b.NewTabsQueue.length > 0 && b.NewTabsQueue[0] == tabId) {
chrome.tabs.get(tabId, function(NewTab) { // get tab again as reported tab's url is empty! Also for some reason firefox sends tab with "active == false" even if tab is active (THIS IS POSSIBLY A NEW BUG IN FF 60!)
let ParentId;
@ -472,25 +470,21 @@ function OnMessageTabCreated(tabId) {
b.EmptyTabs.push(tabId);
}
if (NewTab.pinned) {
let PinTabs = GetChildren("pin_list");
b.tabs[NewTab.id].parent = "pin_list";
b.tabs[NewTab.id].index = NewTab.index;
if (browserId == "F") {
b.tabs[NewTab.id].parent_ttid = "";
}
for (let i = PinTabs.indexOf(NewTab.openerTabId)+1; i < PinTabs.length; i++) { // shift next siblings indexes
b.tabs[PinTabs[i]].index += 1;
}
b.tabs[NewTab.id].index = NewTab.index;
} else {
if (opt.append_orphan_tab == "as_child" && opt.orphaned_tabs_to_ungrouped == false) {
// let atb = NewTab.active ? 0 : 1;
NewTab.openerTabId = b.windows[NewTab.windowId].activeTabId[NewTab.active ? 0 : 1];
NewTab.openerTabId = activeTabId;
}
if (NewTab.openerTabId) { // child case
@ -502,10 +496,10 @@ function OnMessageTabCreated(tabId) {
if (browserId == "F") {
b.tabs[NewTab.id].parent_ttid = b.tabs[NewTab.openerTabId].parent_ttid;
}
b.tabs[NewTab.id].index = b.tabs[NewTab.openerTabId].index+1;
for (let i = OpenerSiblings.indexOf(NewTab.openerTabId)+1; i < OpenerSiblings.length; i++) { // shift next siblings indexes
b.tabs[OpenerSiblings[i]].index += 1;
}
b.tabs[NewTab.id].index = b.tabs[NewTab.openerTabId].index+1;
AfterId = NewTab.openerTabId;
} else {
@ -518,18 +512,18 @@ function OnMessageTabCreated(tabId) {
}
if (opt.append_child_tab_after_limit == "after") { // max tree depth, place tab after parent
b.tabs[NewTab.id].index = b.tabs[NewTab.openerTabId].index+1;
for (let i = OpenerSiblings.indexOf(NewTab.openerTabId)+1; i < OpenerSiblings.length; i++) { // shift next siblings indexes
b.tabs[OpenerSiblings[i]].index += 1;
}
b.tabs[NewTab.id].index = b.tabs[NewTab.openerTabId].index+1;
AfterId = NewTab.openerTabId;
}
if (opt.append_child_tab_after_limit == "top" && opt.append_child_tab != "after") { // max tree depth, place tab on top (above parent)
b.tabs[NewTab.id].index = 0;
for (let i = 0; i < OpenerSiblings.length; i++) { // shift all siblings indexes
b.tabs[OpenerSiblings[i]].index += 1;
}
b.tabs[NewTab.id].index = 0;
ParentId = b.tabs[NewTab.id].parent;
}
@ -556,10 +550,10 @@ function OnMessageTabCreated(tabId) {
}
if (opt.append_child_tab == "top") { // place child tab at the top (reverse hierarchy)
b.tabs[NewTab.id].index = 0;
for (let i = 0; i < OpenerChildren.length; i++) { // shift all siblings indexes
b.tabs[OpenerChildren[i]].index += 1;
}
b.tabs[NewTab.id].index = 0;
ParentId = b.tabs[NewTab.id].parent;
}
@ -583,18 +577,18 @@ function OnMessageTabCreated(tabId) {
}
if (opt.append_child_tab_after_limit == "after") { // tab will append after opener
b.tabs[NewTab.id].index = b.tabs[NewTab.openerTabId].index+1;
for (let i = OpenerSiblings.indexOf(NewTab.openerTabId)+1; i < OpenerSiblings.length; i++) { // shift next siblings indexes
b.tabs[OpenerSiblings[i]].index += 1;
}
b.tabs[NewTab.id].index = b.tabs[NewTab.openerTabId].index+1;
AfterId = NewTab.openerTabId;
}
if (opt.append_child_tab_after_limit == "top") { // tab will append on top
b.tabs[NewTab.id].index = 0;
for (let i = 0; i < OpenerChildren.length; i++) { // shift all siblings indexes
b.tabs[OpenerChildren[i]].index += 1;
}
b.tabs[NewTab.id].index = 0;
ParentId = b.tabs[NewTab.id].parent;
}
@ -612,6 +606,7 @@ function OnMessageTabCreated(tabId) {
}
}
}
} else { // orphan tab
if (opt.orphaned_tabs_to_ungrouped == true) { // if set to append orphan tabs to ungrouped group
@ -619,28 +614,25 @@ function OnMessageTabCreated(tabId) {
b.tabs[NewTab.id].index = b.tabs[TabListTabs[TabListTabs.length-1]].index+1;
ParentId = "tab_list";
append = true;
// chrome.runtime.sendMessage({command: "set_active_group", windowId: NewTab.windowId, groupId: "tab_list"});
} else {
if (opt.append_orphan_tab == "after_active") {
if (b.windows[NewTab.windowId] && b.windows[NewTab.windowId].activeTabId) {
let activeTabId = b.windows[NewTab.windowId].activeTabId[1] != NewTab.id ? b.windows[NewTab.windowId].activeTabId[1] : b.windows[NewTab.windowId].activeTabId[0];
// console.log(b.tabs[activeTabId].index);
if (b.tabs[activeTabId]) {
let ActiveSiblings = GetChildren(b.tabs[activeTabId].parent);
b.tabs[NewTab.id].parent = b.tabs[activeTabId].parent;
b.tabs[NewTab.id].index = b.tabs[activeTabId].index+1;
for (let i = ActiveSiblings.indexOf(activeTabId)+1; i < ActiveSiblings.length; i++) { // shift next siblings indexes
// let prev = b.tabs[ActiveSiblings[i]].index;
b.tabs[ActiveSiblings[i]].index += 1;
// console.log(prev + " " + b.tabs[ActiveSiblings[i]].index );
}
b.tabs[NewTab.id].index = b.tabs[activeTabId].index+1;
if (browserId == "F"){
b.tabs[NewTab.id].parent_ttid = b.tabs[activeTabId].parent_ttid;
}
AfterId = activeTabId;
} else { // FAIL, no active tab!
let GroupTabs = GetChildren(b.windows[NewTab.windowId].active_group);
b.tabs[NewTab.id].parent = b.windows[NewTab.windowId].active_group;
@ -662,7 +654,6 @@ function OnMessageTabCreated(tabId) {
b.tabs[NewTab.id].index = NewTab.index;
ParentId = "tab_list";
}
// console.log(b.tabs[NewTab.id].index);
}
if (opt.append_orphan_tab == "top") {
@ -671,10 +662,10 @@ function OnMessageTabCreated(tabId) {
if (browserId == "F"){
b.tabs[NewTab.id].parent_ttid = "";
}
b.tabs[NewTab.id].index = 0;
for (let i = 0; i < GroupTabs.length; i++) { // shift all tabs indexes in group
b.tabs[GroupTabs[i]].index += 1;
}
b.tabs[NewTab.id].index = 0;
ParentId = b.windows[NewTab.windowId].active_group;
}
@ -692,9 +683,7 @@ function OnMessageTabCreated(tabId) {
ParentId = b.windows[NewTab.windowId].active_group;
append = true;
}
}
}
if (opt.move_tabs_on_url_change === "all_new") {
@ -708,6 +697,20 @@ function OnMessageTabCreated(tabId) {
setTimeout(function() {
b.schedule_save++;
}, 500);
chrome.runtime.sendMessage({command: "tab_created", windowId: NewTab.windowId, tabId: NewTab.id, tab: NewTab, ParentId: ParentId, InsertAfterId: AfterId, Append: append});
if (b.NewTabsQueue.indexOf(NewTab.id) != -1) {
b.NewTabsQueue.splice(b.NewTabsQueue.indexOf(NewTab.id), 1);
}
});
} else {
console.log("tab_created in queue");
setTimeout(function() {
OnMessageTabCreated(tabId, activeTabId);
}, 100);
}
}

View File

@ -14,7 +14,8 @@
"19": "icons/16.png",
"16": "icons/16.png"
},
"permissions": [ "tabs", "sessions", "storage", "unlimitedStorage", "bookmarks", "tabHide" ],
"permissions": [ "<all_urls>", "tabs", "sessions", "storage", "unlimitedStorage", "bookmarks", "tabHide" ],
"sidebar_action": {
"default_icon": {
"16": "icons/16.png",
@ -28,16 +29,6 @@
"browser_action": {
"default_icon": "icons/24.png"
},
"commands": {
"_execute_browser_action": {
"suggested_key": { "default": "F1" },
"description": "toggle Tree Tabs"
},
"close_tree": {
"suggested_key": { "default": "Alt+W" },
"description": "close tree"
}
},
"applications": {
"gecko": {
"id": "TreeTabs@jagiello.it",
@ -48,5 +39,11 @@
"page": "options.html",
"open_in_tab": true
},
"version": "1.7.1"
"commands": {
"close_tree": {
"suggested_key": { "default": "Alt+W" },
"description": "close tree"
}
},
"version": "100"
}

View File

@ -221,6 +221,13 @@
<option class="bg_opt_drop_down_menu" id="options_append_orphan_tab_as_child" value="as_child"></option>
</select>
</li>
<li>
<label class="label" id="options_toolbar_new_tab"></label>
<select id="append_tab_from_toolbar">
<option class="bg_opt_drop_down_menu" id="options_toolbar_new_tab_as_regular_orphan" value="as_regular_orphan"></option>
<option class="bg_opt_drop_down_menu" id="options_toolbar_new_tab_root_of_group" value="group_root"></option>
</select>
</li>
<li>
<label class="label" id="options_after_closing_active_tab"></label>
<select id="after_closing_active_tab">
@ -270,6 +277,21 @@
</tr>
</table>
<br>
<p style="font-size:11px; color: red;" class="hint_explanation" id="hint_orphan_tab"></p>
<ul style="list-style-type:disc; font-size:11px;">
<li class="hint_explanation" id="hint_ctrl_t"></li>
<li class="hint_explanation" id="hint_from_pin"></li>
<li class="hint_explanation" id="hint_from_bookmark"></li>
<li class="hint_explanation" id="hint_from_external_link"></li>
<li class="hint_explanation" id="hint_from_popup"></li>
</ul>
<span style="display:block; font-size:11px; color: red;" class="hint_explanation" id="hint_explained_new_tab_settings"></span>
<span style="display:block; font-size:11px; color: red;" class="hint_explanation" id="hint_explained_orphan_after_active_settings"></span>
<br>
</fieldset>

View File

@ -10,7 +10,7 @@ var SelectedTheme = Object.assign({}, DefaultTheme);
var dragged_button = {id: ""};
// options for all drop down menus
let DropDownList = ["dbclick_folder", "midclick_folder", "midclick_tab", "dbclick_group", "midclick_group", "dbclick_tab", "append_child_tab", "append_child_tab_after_limit", "append_orphan_tab", "after_closing_active_tab", "move_tabs_on_url_change"];
let DropDownList = ["dbclick_folder", "midclick_folder", "midclick_tab", "dbclick_group", "midclick_group", "dbclick_tab", "append_child_tab", "append_child_tab_after_limit", "append_orphan_tab", "append_tab_from_toolbar", "after_closing_active_tab", "move_tabs_on_url_change"];
document.addEventListener("DOMContentLoaded", function() {
document.title = "Tree Tabs";
@ -102,7 +102,7 @@ function AddRegexPair() {
// document events
function GetOptions(storage) {
// get language labels
document.querySelectorAll(".label, .set_button, .bg_opt_drop_down_menu").forEach(function(s){
document.querySelectorAll(".label, .set_button, .bg_opt_drop_down_menu, .hint_explanation").forEach(function(s){
s.textContent = chrome.i18n.getMessage(s.id);
});

View File

@ -5,9 +5,9 @@
function AppendSampleTabs() {
// folders
AddNewFolder("f_folder1", "cftab_list", labels.noname_group, 0, "o", "o", false);
AddNewFolder("f_folder2", "f_folder1", labels.noname_group, 0, "c", "c", false);
AddNewFolder("f_folder3", "f_folder1", labels.noname_group, 0, "c", "c", false);
AddNewFolder({folderId: "f_folder1", ParentId: "cftab_list", Name: labels.noname_group, Index: 0, ExpandState: "o", AdditionalClass: "o"});
AddNewFolder({folderId: "f_folder2", ParentId: "f_folder1", Name: labels.noname_group, Index: 0, ExpandState: "c", AdditionalClass: "c"});
AddNewFolder({folderId: "f_folder3", ParentId: "f_folder1", Name: labels.noname_group, Index: 0, ExpandState: "c", AdditionalClass: "c"});
// pins

View File

@ -567,7 +567,7 @@ function StartAutoSaveSession() {
let newName = d.toLocaleString().replace("/", ".").replace("/", ".").replace(":", "").replace(":", "");
ExportSession(newName, false, false, true);
ShowStatusBar({show: true, spinner: false, message: "Autosave: "+newName, hideTimeout: 1000});
ShowStatusBar({show: true, spinner: false, message: "Autosave: "+newName, hideTimeout: 1500});
if (document.getElementById("manager_window").style.top != "-500px") {
chrome.storage.local.get(null, function(storage) {

View File

@ -22,6 +22,7 @@ let b = {
windows: {},
tabs: {},
tt_ids: {},
NewTabsQueue: [],
EmptyTabs: [],
newTabUrl: browserId == "F" ? "about:newtab" : "chrome://startpage/"
};
@ -57,6 +58,7 @@ const DefaultPreferences = {
append_child_tab_after_limit: "after",
append_orphan_tab: "bottom",
after_closing_active_tab: "below_seek_in_parent",
append_tab_from_toolbar: "group_root",
collapse_other_trees: false,
open_tree_on_hover: true,
promote_children: true,

View File

@ -26,12 +26,24 @@ function SetEvents() {
}
}
}
document.oncontextmenu = function(event){
document.oncontextmenu = function (event) {
if (!event.ctrlKey && event.target.classList.contains("text_input") == false) {
event.preventDefault();
event.stopPropagation();
return false;
}
};
window.addEventListener('contextmenu', function (event) {
if (!event.ctrlKey && event.target.classList.contains("text_input") == false) {
event.preventDefault();
event.stopPropagation();
return false;
}
}, false);
document.body.onresize = function(event) {
RefreshGUI();
}
@ -197,10 +209,10 @@ function SetEvents() {
}
// new folder
// if (event.which == 91 && event.which == 71) {
// let FolderId = AddNewFolder({SetEvents: true});
// ShowRenameFolderDialog(FolderId);
// }
if (event.which == 192 && event.which == 70 && event.which == 69) {
let FolderId = AddNewFolder({SetEvents: true});
ShowRenameFolderDialog(FolderId);
}
RefreshGUI();
}

View File

@ -27,6 +27,10 @@ function AppendFolder(folderId, Name, ParentId, Expand, SetEvents, AdditionalCla
let fd = document.createElement("div"); fd.className = ClassList; if (Expand) { fd.className += Expand } fd.id = folderId; // FOLDER
let fh = document.createElement("div"); fh.className = (opt.always_show_close && !opt.never_show_close) ? "folder_header close_show" : "folder_header"; fh.id = "folder_header"+folderId; if (SetEvents) {fh.draggable = true;} fd.appendChild(fh); // HEADER
let ex = document.createElement("div"); ex.className = "folder_icon"; ex.id = "fop"+folderId; fh.appendChild(ex);
let ftbc = document.createElement("div"); ftbc.className = "folder_counter"; ftbc.id = "folder_counter"+folderId; fh.appendChild(ftbc); // TABS COUNTER
let fbcn = document.createElement("div"); fbcn.className = "counter_number"; fbcn.id = "counter_number"+folderId; ftbc.appendChild(fbcn); // TABS COUNTER NUMBER
let ft = document.createElement("div"); ft.className = "folder_title"; ft.id = "folder_title"+folderId; ft.textContent = Name; fh.appendChild(ft); // TITLE
let cf = document.createElement("div"); cf.className = "children_folders"; cf.id = "cf"+folderId; fd.appendChild(cf);
let ct = document.createElement("div"); ct.className = "children_tabs"; ct.id = "ct"+folderId; fd.appendChild(ct);

View File

@ -138,6 +138,13 @@ function StartSidebarListeners() {
}
if (message.command == "tab_created") {
if (message.InsertAfterId && document.querySelectorAll("#"+tt.active_group+" .tab").length == 0) {
message.InsertAfterId = undefined;
message.ParentId = tt.active_group;
}
AppendTab({tab: message.tab, ParentId: message.ParentId, InsertAfterId: message.InsertAfterId, Append: message.Append, Scroll: true});
RefreshExpandStates();

View File

@ -108,7 +108,7 @@ function ShowFGroupMenu(GroupNode, event) {
HideMenus();
tt.menuItemNode = GroupNode;
document.querySelectorAll("#menu_new_group, #menu_rename_group, #menu_delete_group, #menu_delete_group_tabs_close, #separator_gunlo, #menu_groups_unload, #separator_gbk, #separator_tts, #menu_bookmark_group, #separator_tts, #menu_groups_hibernate, #menu_manager_window, #menu_treetabs_settings").forEach(function(s){
document.querySelectorAll("#menu_new_group, #menu_rename_group, #menu_delete_group, #separator_gtbcl, #menu_group_tabs_close, #menu_delete_group_tabs_close, #separator_gunlo, #menu_groups_unload, #separator_gbk, #separator_tts, #menu_bookmark_group, #separator_tts, #menu_groups_hibernate, #menu_manager_window, #menu_treetabs_settings").forEach(function(s){
s.style.display = "";
});
if (tt.menuItemNode.id == "tab_list") {
@ -635,6 +635,20 @@ function SetMenu() {
}
}
if (m.id == "menu_group_tabs_close") {
m.onmousedown = function(event) {
if (event.which == 1) {
event.stopPropagation();
let tabsArr = [];
document.querySelectorAll("[id='"+tt.menuItemNode.id+"'] .tab").forEach(function(s){
tabsArr.push(parseInt(s.id));
});
CloseTabs(tabsArr);
HideMenus();
}
}
}
if (m.id == "menu_manager_window") {
m.onmousedown = function(event) {
if (event.which == 1) {

View File

@ -210,13 +210,15 @@ async function GetFaviconAndTitle(tabId, addCounter) {
if (tab){
let title = tab.title ? tab.title : tab.url;
let tHeader = t.childNodes[0];
let tTitle = tHeader.childNodes[1];
let tTitle = t.childNodes[0].childNodes[2];
if (tab.status == "complete" || tab.discarded) {
t.classList.remove("loading");
tTitle.textContent = title;
tHeader.title = title;
if (opt.show_counter_tabs_hints) {
tHeader.setAttribute("tabTitle", title);
}
let Img = new Image();
@ -232,7 +234,9 @@ async function GetFaviconAndTitle(tabId, addCounter) {
t.classList.add("loading");
tHeader.style.backgroundImage = "";
tHeader.title = labels.loading;
if (opt.show_counter_tabs_hints) {
tHeader.setAttribute("tabTitle", labels.loading);
}
tTitle.textContent = labels.loading;
setTimeout(function() {
if (document.getElementById(tab.id) != null) GetFaviconAndTitle(tab.id, addCounter);
@ -272,30 +276,32 @@ async function RefreshExpandStates() {
async function RefreshCounters() {
if (opt.show_counter_tabs || opt.show_counter_tabs_hints) {
document.querySelectorAll("#"+tt.active_group+" .tab").forEach(function(s){
let title = s.childNodes[0].getAttribute("tabTitle");
if (title != null) {
s.childNodes[0].title = title;
s.childNodes[0].childNodes[1].textContent =title;
}
});
// if (opt.show_counter_tabs_hints) {
// document.querySelectorAll("#"+tt.active_group+" .tab").forEach(function(s){
// let title = s.childNodes[0].getAttribute("tabTitle");
// if (title != null) {
// s.childNodes[0].title = title;
// s.childNodes[0].childNodes[1].textContent = title;
// }
// });
// }
document.querySelectorAll("#"+tt.active_group+" .o.tab, #"+tt.active_group+" .c.tab").forEach(function(s){
let title = s.childNodes[0].getAttribute("tabTitle");
if (opt.show_counter_tabs && title != null) {
s.childNodes[0].childNodes[1].textContent = ("("+ document.querySelectorAll("[id='" + s.id + "'] .tab").length +") ") + title;
if (opt.show_counter_tabs) {
s.childNodes[0].childNodes[1].childNodes[0].textContent = document.querySelectorAll("[id='" + s.id + "'] .tab").length;
}
if (opt.show_counter_tabs_hints) {
s.childNodes[0].title = ("("+ document.querySelectorAll("[id='" + s.id + "'] .tab").length +") ") + title;
let title = s.childNodes[0].getAttribute("tabTitle");
s.childNodes[0].title = (document.querySelectorAll("[id='" + s.id + "'] .tab").length +" • ") + title;
}
});
// ·
document.querySelectorAll("#"+tt.active_group+" .folder").forEach(function(s){
if (opt.show_counter_tabs && tt.folders[s.id]) {
s.childNodes[0].childNodes[1].textContent = ("("+ document.querySelectorAll("[id='" + s.id + "'] .tab").length +") ") + tt.folders[s.id].name;
s.childNodes[0].childNodes[1].childNodes[0].textContent = document.querySelectorAll("[id='" + s.id + "'] .tab").length;
}
if (opt.show_counter_tabs_hints && tt.folders[s.id]) {
s.childNodes[0].title = ("("+ document.querySelectorAll("[id='" + s.id + "'] .tab").length +") ") + tt.folders[s.id].name;
s.childNodes[0].title = (document.querySelectorAll("[id='" + s.id + "'] .tab").length +" ") + tt.folders[s.id].name;
}
});
}
@ -308,14 +314,13 @@ async function RefreshTabCounter(tabId) {
if (t != null && title != null) {
if (t.classList.contains("o") || t.classList.contains("c")) {
if (opt.show_counter_tabs) {
t.childNodes[0].childNodes[1].textContent = ("("+ document.querySelectorAll("[id='" + t.id + "'] .tab").length +") ") + title;
t.childNodes[0].childNodes[1].childNodes[0].textContent = document.querySelectorAll("[id='" + t.id + "'] .tab").length;
}
if (opt.show_counter_tabs_hints) {
t.childNodes[0].title = ("("+ document.querySelectorAll("[id='" + t.id + "'] .tab").length +") ") + title;
t.childNodes[0].title = (document.querySelectorAll("[id='" + t.id + "'] .tab").length +" ") + title;
}
} else {
t.childNodes[0].title = title;
t.childNodes[0].childNodes[1].textContent = title;
}
}
}

View File

@ -104,13 +104,23 @@ function AppendTab(p) { // tab: chrome tab object, ParentId: int or string, Inse
let tb = document.createElement("div"); tb.className = ClassList; tb.id = p.tab.id; // TAB
let tbh = document.createElement("div"); tbh.className = (opt.always_show_close && !opt.never_show_close) ? "tab_header close_show" : "tab_header"; tbh.id = "tab_header"+p.tab.id; if (!p.SkipSetEvents) {tbh.draggable = true;} tb.appendChild(tbh); // HEADER
let tbe = document.createElement("div"); tbe.className = "expand"; tbe.id = "exp"+p.tab.id; tbh.appendChild(tbe); // EXPAND ARROW
let tbc = document.createElement("div"); tbc.className = "tab_counter"; tbc.id = "tab_counter"+p.tab.id; tbh.appendChild(tbc); // TABS COUNTER
let tbcn = document.createElement("div"); tbcn.className = "counter_number"; tbcn.id = "counter_number"+p.tab.id; tbc.appendChild(tbcn); // TABS COUNTER NUMBER
let tbt = document.createElement("div"); tbt.className = "tab_title"; tbt.id = "tab_title"+p.tab.id; tbh.appendChild(tbt); // TITLE
let cl = undefined;
if (!opt.never_show_close) {
cl = document.createElement("div"); cl.className = "close"; cl.id = "close"+p.tab.id; tbh.appendChild(cl); // CLOSE BUTTON
let ci = document.createElement("div"); ci.className = "close_img"; ci.id = "close_img"+p.tab.id; cl.appendChild(ci);
}
let mi = document.createElement("div"); mi.className = "tab_mediaicon"; mi.id = "tab_mediaicon"+p.tab.id; tbh.appendChild(mi);
let ct = document.createElement("div"); ct.className = "children_tabs"; ct.id = "ct"+p.tab.id; tb.appendChild(ct);
let di = document.createElement("div"); di.className = "drag_indicator"; di.id = "di"+p.tab.id; tb.appendChild(di); // DROP TARGET INDICATOR
@ -495,12 +505,13 @@ function CloseTabs(tabsIds) {
if (activeTab != null && tabsIds.indexOf(parseInt(activeTab.id)) != -1) {
SwitchActiveTabBeforeClose(tt.active_group);
}
setTimeout(function() {
tabsIds.forEach(function(tabId) {
let tab = document.getElementById(tabId);
if (tab.classList.contains("pin") && opt.allow_pin_close) {
tab.parentNode.removeChild(tab);
chrome.tabs.update(tabId, {pinned: false});
RefreshGUI();
// RefreshGUI();
}
if (tabId == tabsIds[tabsIds.length-1]) {
setTimeout(function() {
@ -508,6 +519,7 @@ function CloseTabs(tabsIds) {
}, 10);
}
});
}, 200);
}
function DiscardTabs(tabsIds) {
@ -532,7 +544,7 @@ function SwitchActiveTabBeforeClose(ActiveGroupId) {
}
let activeGroup = document.getElementById(ActiveGroupId);
if (document.querySelectorAll("#"+ActiveGroupId+" .tab").length <= 1 && document.querySelector(".pin.active_tab") == null) { // CHECK IF CLOSING LAST TAB IN ACTIVE GROUP
if (document.querySelectorAll("#"+ActiveGroupId+" .tab").length < 2 && document.querySelector(".pin.active_tab") == null) { // CHECK IF CLOSING LAST TAB IN ACTIVE GROUP
let pins = document.querySelectorAll(".pin");
@ -574,18 +586,18 @@ function SwitchActiveTabBeforeClose(ActiveGroupId) {
log("available tabs in current group, switching option is: "+opt.after_closing_active_tab);
}
if (opt.after_closing_active_tab == "above") {
if (opt.after_closing_active_tab == "above" || opt.after_closing_active_tab == "above_seek_in_parent") {
ActivatePrevTab(true);
}
if (opt.after_closing_active_tab == "below") {
if (opt.after_closing_active_tab == "below" || opt.after_closing_active_tab == "below_seek_in_parent") {
ActivateNextTab(true);
}
if (opt.after_closing_active_tab == "above_seek_in_parent") {
ActivatePrevTabBeforeClose();
}
if (opt.after_closing_active_tab == "below_seek_in_parent") {
ActivateNextTabBeforeClose();
}
// if (opt.after_closing_active_tab == "above_seek_in_parent") {
// ActivatePrevTabBeforeClose();
// }
// if (opt.after_closing_active_tab == "below_seek_in_parent") {
// ActivateNextTabBeforeClose();
// }
}
}

View File

@ -308,8 +308,13 @@ function SetToolbarEvents(CleanPreviousBindings, Buttons, ToolbarShelfToggle, To
if (s.id == "button_new") {
s.onclick = function(event) {
if (event.which == 1) {
if (opt.append_tab_from_toolbar == "group_root") {
OpenNewTab(false, tt.active_group);
}
if (opt.append_tab_from_toolbar == "as_regular_orphan") {
OpenNewTab(false, (document.querySelectorAll("#"+tt.active_group+" .tab").length == 0 ? tt.active_group : undefined));
}
}
}
s.onmousedown = function(event) {
// DUPLICATE TAB

View File

@ -183,6 +183,8 @@
<li class="menu_item" id="menu_groups_unload"></li>
<div class="separator" id="separator_ghiber"></div>
<li class="menu_item" id="menu_groups_hibernate"></li>
<div class="separator" id="separator_gtbcl"></div>
<li class="menu_item" id="menu_group_tabs_close"></li>
<div class="separator" id="separator_gbk"></div>
<li class="menu_item" id="menu_bookmark_group"></li>
<div class="separator" id="separator_tts"></div>

View File

@ -1410,12 +1410,79 @@ div {
.dragged_tree>.folder_header,
.dragged_tree>.tab_header {
border:1px solid var(--tab_selected_border);
background-color:var(--tab_selected_background);
border: 1px solid var(--tab_selected_border);
background-color: var(--tab_selected_background);
}
/* TITLE COUNTER */
.folder_counter,
.tab_counter {
display: none;
pointer-events: none;
width: 0px;
height: 0px;
}
.o>.folder_header>.folder_counter,
.o>.tab_header>.tab_counter,
.c>.folder_header>.folder_counter,
.c>.tab_header>.tab_counter {
opacity: 0.3;
display: block;
position: absolute;
vertical-align: bottom;
z-index: 999;
right: calc(100% - var(--counter_left));
top: var(--counter_top);
text-overflow: ellipsis;
width: auto;
height: var(--counter_height);
overflow: hidden;
border: 1px solid #e7e7e7;
border-radius: 6px;
background-color: #e7e7e7;
line-height: 10px;
}
.o>.folder_header:hover>.folder_counter,
.o>.tab_header:hover>.tab_counter,
.c>.folder_header:hover>.folder_counter,
.c>.tab_header:hover>.tab_counter {
opacity: 0.9;
height: calc(var(--counter_height) + 1px);
}
.o>.tab_header:hover>.tab_counter>.counter_number,
.c>.tab_header:hover>.tab_counter>.counter_number,
.o>.folder_header:hover>.folder_counter>.counter_number,
.c>.folder_header:hover>.folder_counter>.counter_number {
top: calc(var(--counter_number_top) + 1px);
font-size: calc(var(--counter_font_size) + 1px);
}
.folder_counter>.counter_number,
.tab_counter>.counter_number {
position: relative;
top: var(--counter_number_top);
font-family: Arial, Helvetica, "Nimbus Sans L", "Liberation Sans", FreeSans, Sans-serif;
white-space: nowrap;
font-size: var(--counter_font_size);
/* color: #303030; */
color: #000000;
padding-left: 1px;
padding-right: 1px;
}
/* MENU */
.menu {

View File

@ -7,7 +7,7 @@ body {
--pin_height: 22px;
--tab_height: 16px;
--tab_height_line: 17px;
--tab_height_line: 16px;
--title_font_size: 10.5px;
@ -35,4 +35,10 @@ body {
--tab_mediaicon_height: 8px;
--tab_mediaicon_width: 8px;
--counter_height: 5px;
--counter_left: 19px;
--counter_top: 0px;
--counter_font_size: 7px;
--counter_number_top: -3px;
}

View File

@ -7,7 +7,7 @@ body {
--pin_height: 22px;
--tab_height: 17px;
--tab_height_line: 19px;
--tab_height_line: 18px;
--title_font_size: 10.5px;
@ -35,4 +35,10 @@ body {
--tab_mediaicon_height: 9px;
--tab_mediaicon_width: 9px;
--counter_height: 6px;
--counter_left: 21px;
--counter_top: 0px;
--counter_font_size: 8px;
--counter_number_top: -2px;
}

View File

@ -35,4 +35,11 @@ body {
--tab_mediaicon_height: 10px;
--tab_mediaicon_width: 10px;
--counter_height: 6px;
--counter_left: 24px;
/* --counter_left: 1px; */
--counter_top: 1px;
--counter_font_size: 8px;
--counter_number_top: -2px;
}

View File

@ -35,4 +35,10 @@ body {
--tab_mediaicon_height: 11px;
--tab_mediaicon_width: 11px;
--counter_height: 6px;
--counter_left: 26px;
--counter_top: 1px;
--counter_font_size: 8px;
--counter_number_top: -2px;
}

View File

@ -35,4 +35,10 @@ body {
--tab_mediaicon_height: 12px;
--tab_mediaicon_width: 12px;
--counter_height: 6px;
--counter_left: 28px;
--counter_top: 1px;
--counter_font_size: 8px;
--counter_number_top: -2px;
}