diff --git a/..TODO/TODO.txt b/..TODO/TODO.txt
index 209d79e..3d7ee25 100644
--- a/..TODO/TODO.txt
+++ b/..TODO/TODO.txt
@@ -1,33 +1,58 @@
+CHANGES:
+1. shortcut to open TreeTabs Sidebar is now F1
+2. log does not preserve any personal data (urls) for GDPR law
+
+NEW:
+1. you can now drag&drop entire group to another window
+2. tree structure is tracked in background (excluded closing tabs)
+3. added alt+w shortcut to close a tree of tabs
+4. creating folder will now prompt for a new name
+5. search for *audible, *muted, *unloaded, *loaded tabs! Just write *audible in search box!
+
+
FIXES:
-deny Drag&drop tab to root of folders
-"Never show close button" option was breaking theme preview/editor
-closing pinned tabs did not resize area of pinned tabs, leaving empty space below
-added "bookmark" menu for single tab
-clone pinned tab was added as not pinned (only in Firefox)
-Shortcut changed to Ctrl+F2
-export session file has now date as a name
+1. import window was not showing up
+2. export group and export session had file extension in name
+3. pin tree had bug in setting class
+FEATURES TO DO
+
+opt.promote_children_in_first_child true, to work from background! also for message.command == "tab_detached"
+
+manager: add save/import/export window
+
+discard on import group and import session
+
+Shift + mouse scroll to switch between groups
+
+unread tabs
-instruction to add popup
line for children hierarchy (like at the beggining)
"undo close" as a possible action with middle click on empty space
+return to the first tab with mousewheel when we are at the bottom list (loop) - "mousewheel scroll on the last tab allow to return to the first one"
+
+mute icon config option (disable animation)
+
+FIREFOX CONTAINERS
-DRAG&DROP TO ANOTHER WINDOW OF THE ENTIRE GROUP
undo close to restore trees (will work ONLY in firefox)
Close tab on Middle mouse click and not On Middle mouse down
Split Pin size in theme
+unread state?
+Unread Tabs Color/Style
+automatic different color for each tree
+
add groups scrolling arrows
add textbox for ungrouped name in options
option for scrollbar on the left
-unread state?
menu: copy urls of the selected tabs
menu: bookmark selected tabs/tree
@@ -44,16 +69,14 @@ maybe filter tabs on search
font size
-hibernate group
double click on tab actions selection like double click to be able to expand child tab.
- I want you to be able to display the tab number count on the right end
+I want you to be able to display the tab number count on the right end
customizable menu
import session to unload tabs immediately
bind groups to FF containers
-Unread Tabs Color/Style
Give back group color (like it was before)
@@ -64,8 +87,6 @@ folders collapsed by default or make this optional
when actived tab located in folder, all tabs operation related with creating new tab (such as clone of tab in folder, new tab) must work only in current folder.
-New tab in selected folder!
-
separate option for close folder (close or promote children)
menu: unload tabs in folders
@@ -81,7 +102,7 @@ Accept BCH (BitcoinCash) donations as the FEES make it FAR more palatable to don
- Like many other commenters suggested, it would be wonderful to see some indication of the container a tab was opened in, if any. Getting an option to directly be able to chose to open a new tab in a container would also be very useful.
-I don't understand those from comments
+I DON'T UNDERSTAND THOSE FROM COMMENTS
- add possibility open all tabs in folder in new left tab group with deleting this folder;
- for economy memory your tabs must to makings (html code) during activating left tab group or during unfold folders/trees;
- real FF tabs must creating and linking only after activate your tabs;
\ No newline at end of file
diff --git a/..files_ForTesting/background.html b/..files_ForTesting/background.html
deleted file mode 100644
index 0816c92..0000000
--- a/..files_ForTesting/background.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/..files_ForTesting/init.js b/..files_ForTesting/init.js
deleted file mode 100644
index af2398d..0000000
--- a/..files_ForTesting/init.js
+++ /dev/null
@@ -1,16 +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/
-
-document.addEventListener("DOMContentLoaded", Init(), false);
-
-function Init() {
- if (browserId == "F") {
- FirefoxMessageListeners();
- FirefoxStart(0);
- } else {
- // ConvertLegacyStorage();
- ChromeMessageListeners();
- ChromeLoadTabs(0);
- }
-}
diff --git a/..files_ForTesting/manifest.json b/..files_ForTesting/manifest.json
index 76dcbba..0e7a66c 100644
--- a/..files_ForTesting/manifest.json
+++ b/..files_ForTesting/manifest.json
@@ -2,7 +2,7 @@
"manifest_version": 2,
"default_locale": "en",
"background": {
- "page": "background.html",
+ "scripts": [ "listeners_bg.js", "scripts/common.js", "background.js" ],
"persistent": true
},
"name": "Tree Tabs",
@@ -14,7 +14,7 @@
"19": "icons/16.png",
"16": "icons/16.png"
},
- "permissions": [ "tabs", "sessions", "", "storage", "unlimitedStorage", "bookmarks", "tabHide" ],
+ "permissions": [ "", "tabs", "sessions", "storage", "unlimitedStorage", "bookmarks", "tabHide" ],
"sidebar_action": {
"default_icon": {
@@ -39,5 +39,11 @@
"page": "options.html",
"open_in_tab": true
},
+ "commands": {
+ "close_tree": {
+ "suggested_key": { "default": "Alt+W" },
+ "description": "close tree"
+ }
+ },
"version": "100"
}
\ No newline at end of file
diff --git a/..files_firefox/background.html b/..files_firefox/background.html
deleted file mode 100644
index c7bbc40..0000000
--- a/..files_firefox/background.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/..files_firefox/init.js b/..files_firefox/init.js
deleted file mode 100644
index 326732f..0000000
--- a/..files_firefox/init.js
+++ /dev/null
@@ -1,12 +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/
-
-document.addEventListener("DOMContentLoaded", Init(), false);
-
-function Init() {
- setTimeout(function() {
- FirefoxMessageListeners();
- FirefoxStart(0);
- }, 500);
-}
\ No newline at end of file
diff --git a/..files_firefox/manifest.json b/..files_firefox/manifest.json
index 4ac47a9..661cf39 100644
--- a/..files_firefox/manifest.json
+++ b/..files_firefox/manifest.json
@@ -2,7 +2,7 @@
"manifest_version": 2,
"default_locale": "en",
"background": {
- "page": "background.html",
+ "scripts": [ "listeners_bg.js", "scripts/common.js", "background.js" ],
"persistent": true
},
"name": "Tree Tabs",
@@ -14,7 +14,7 @@
"19": "icons/16.png",
"16": "icons/16.png"
},
- "permissions": [ "tabs", "sessions", "", "storage", "unlimitedStorage", "bookmarks", "tabHide" ],
+ "permissions": [ "tabs", "sessions", "storage", "unlimitedStorage", "bookmarks", "tabHide" ],
"sidebar_action": {
"default_icon": {
"16": "icons/16.png",
@@ -30,8 +30,12 @@
},
"commands": {
"_execute_browser_action": {
- "suggested_key": { "default": "Ctrl+F2" },
+ "suggested_key": { "default": "F1" },
"description": "toggle Tree Tabs"
+ },
+ "close_tree": {
+ "suggested_key": { "default": "Alt+W" },
+ "description": "close tree"
}
},
"applications": {
@@ -44,5 +48,5 @@
"page": "options.html",
"open_in_tab": true
},
- "version": "1.6.0"
+ "version": "1.7.0"
}
\ No newline at end of file
diff --git a/..files_opera/background.html b/..files_opera/background.html
deleted file mode 100644
index 1d3aa75..0000000
--- a/..files_opera/background.html
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/..files_opera/init.js b/..files_opera/init.js
deleted file mode 100644
index 27fe083..0000000
--- a/..files_opera/init.js
+++ /dev/null
@@ -1,11 +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/
-
-document.addEventListener("DOMContentLoaded", Init(), false);
-
-function Init() {
- ConvertLegacyStorage();
- ChromeMessageListeners();
- ChromeLoadTabs(0);
-}
diff --git a/..files_opera/manifest.json b/..files_opera/manifest.json
index 4de32b3..c7c72df 100644
--- a/..files_opera/manifest.json
+++ b/..files_opera/manifest.json
@@ -3,7 +3,7 @@
"minimum_opera_version": "42",
"default_locale": "en",
"background": {
- "page": "background.html",
+ "scripts": [ "listeners_bg.js", "scripts/common.js", "background.js" ],
"persistent": true
},
"name": "Tree Tabs",
@@ -25,5 +25,11 @@
"default_title": "Tree Tabs"
},
"options_page": "options.html",
- "version": "1.6.0"
+ "commands": {
+ "close_tree": {
+ "suggested_key": { "default": "Alt+W" },
+ "description": "close tree"
+ }
+ },
+ "version": "1.6.1"
}
diff --git a/..files_vivaldi/background.html b/..files_vivaldi/background.html
deleted file mode 100644
index 1215d3f..0000000
--- a/..files_vivaldi/background.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/..files_vivaldi/init.js b/..files_vivaldi/init.js
deleted file mode 100644
index afe0210..0000000
--- a/..files_vivaldi/init.js
+++ /dev/null
@@ -1,10 +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/
-
-document.addEventListener("DOMContentLoaded", Init(), false);
-
-function Init() {
- ChromeMessageListeners();
- ChromeLoadTabs(0);
-}
diff --git a/..files_vivaldi/manifest.json b/..files_vivaldi/manifest.json
index 883d3b5..1220c67 100644
--- a/..files_vivaldi/manifest.json
+++ b/..files_vivaldi/manifest.json
@@ -2,7 +2,7 @@
"manifest_version": 2,
"default_locale": "en",
"background": {
- "page": "background.html",
+ "scripts": [ "listeners_bg.js", "scripts/common.js", "background.js" ],
"persistent": true
},
"name": "Tree Tabs",
@@ -19,5 +19,11 @@
"page": "options.html",
"open_in_tab": false
},
- "version": "1.6.0"
+ "commands": {
+ "close_tree": {
+ "suggested_key": { "default": "Alt+W" },
+ "description": "close tree"
+ }
+ },
+ "version": "1.7.0"
}
diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index 34bc0d0..34e47b8 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -251,8 +251,7 @@
-
-
+
"options_vivaldi": {
"message": " Vivaldi "
},
@@ -297,16 +296,16 @@
"message": "never"
},
"options_move_on_url_change_from_empty": {
- "message": "when URL changes in Home tab (only Home tab created externally, for example, ctrl+t shortcut)"
+ "message": "when URL changes in Home tab (only Home tabs created by ctrl+t shortcut)"
},
"options_move_on_url_change_from_empty_b": {
- "message": "when URL changes in Home tab"
+ "message": "when URL changes in any Home tab"
},
"options_move_on_url_change_all_new": {
"message": "when tab is created with a matching URL"
},
"options_move_on_url_change_always": {
- "message": "always when URL changes to a matching pattern"
+ "message": "whenever URL changes to a matching pattern"
},
"options_always_show_close": {
@@ -392,16 +391,16 @@
"options_append_child_tab": {
- "message": "Append children tabs at the"
+ "message": "Place children tabs"
},
"options_append_child_tab_top": {
- "message": "top (reverse hierarchy)"
+ "message": "at the top (reverse hierarchy)"
},
"options_append_child_tab_bottom": {
- "message": "bottom"
+ "message": " at the bottom"
},
- "options_append_child_tab_after_active": {
- "message": "after active"
+ "options_append_child_tab_after": {
+ "message": "after parent (no automatic tree)"
},
"options_append_orphan_tab": {
@@ -440,7 +439,7 @@
},
"options_append_child_tab_after_limit": {
- "message": "Once reached tree depth, place tab on the same level, but"
+ "message": "Once reached maximum tree depth, place tab on the same level, but"
},
"options_append_child_tab_after_limit_top": {
"message": "at the top"
@@ -1125,8 +1124,276 @@
"manager_window_load_icon": {
"message": "Load"
+ },
+
+ "options_Remove_button": {
+ "message": "Remove"
+ },
+
+ "add_tab_group_regex": {
+ "message": "Add"
+ },
+
+
+ "tab_title_font_color": {
+ "message": ""
+ },
+ "tab_background": {
+ "message": ""
+ },
+ "tab_border": {
+ "message": ""
+ },
+ "tab_hover_title_font_color": {
+ "message": ""
+ },
+ "tab_hover_background": {
+ "message": ""
+ },
+ "tab_hover_border": {
+ "message": ""
+ },
+ "tab_selected_title_font_color": {
+ "message": ""
+ },
+ "tab_selected_background": {
+ "message": ""
+ },
+ "tab_selected_border": {
+ "message": ""
+ },
+ "tab_selected_hover_title_font_color": {
+ "message": ""
+ },
+ "tab_selected_hover_background": {
+ "message": ""
+ },
+ "tab_selected_hover_border": {
+ "message": ""
+ },
+ "tab_active_title_font_color": {
+ "message": ""
+ },
+ "tab_active_background": {
+ "message": ""
+ },
+ "tab_active_border": {
+ "message": ""
+ },
+ "tab_active_hover_title_font_color": {
+ "message": ""
+ },
+ "tab_active_hover_background": {
+ "message": ""
+ },
+ "tab_active_hover_border": {
+ "message": ""
+ },
+ "tab_active_selected_title_font_color": {
+ "message": ""
+ },
+ "tab_active_selected_background": {
+ "message": ""
+ },
+ "tab_active_selected_border": {
+ "message": ""
+ },
+ "tab_selected_active_hover_title_font_color": {
+ "message": ""
+ },
+ "tab_selected_active_hover_background": {
+ "message": ""
+ },
+ "tab_selected_active_hover_border": {
+ "message": ""
+ },
+ "tab_discarded_title_font_color": {
+ "message": ""
+ },
+ "tab_discarded_background": {
+ "message": ""
+ },
+ "tab_discarded_border": {
+ "message": ""
+ },
+ "tab_discarded_hover_title_font_color": {
+ "message": ""
+ },
+ "tab_discarded_hover_background": {
+ "message": ""
+ },
+ "tab_discarded_hover_border": {
+ "message": ""
+ },
+ "tab_selected_discarded_title_font_color": {
+ "message": ""
+ },
+ "tab_selected_discarded_background": {
+ "message": ""
+ },
+ "tab_selected_discarded_border": {
+ "message": ""
+ },
+ "tab_selected_discarded_hover_title_font_color": {
+ "message": ""
+ },
+ "tab_selected_discarded_hover_background": {
+ "message": ""
+ },
+ "tab_selected_discarded_hover_border": {
+ "message": ""
+ },
+ "tab_filtered_title_font_color": {
+ "message": ""
+ },
+ "tab_filtered_background": {
+ "message": ""
+ },
+ "tab_filtered_border": {
+ "message": ""
+ },
+ "tab_filtered_hover_title_font_color": {
+ "message": ""
+ },
+ "tab_filtered_hover_background": {
+ "message": ""
+ },
+ "tab_filtered_hover_border": {
+ "message": ""
+ },
+ "tab_filtered_active_title_font_color": {
+ "message": ""
+ },
+ "tab_filtered_active_background": {
+ "message": ""
+ },
+ "tab_filtered_active_border": {
+ "message": ""
+ },
+ "tab_filtered_active_hover_title_font_color": {
+ "message": ""
+ },
+ "tab_filtered_active_hover_background": {
+ "message": ""
+ },
+ "tab_filtered_active_hover_border": {
+ "message": ""
+ },
+ "tab_filtered_selected_title_font_color": {
+ "message": ""
+ },
+ "tab_filtered_selected_background": {
+ "message": ""
+ },
+ "tab_filtered_selected_border": {
+ "message": ""
+ },
+ "tab_filtered_selected_hover_title_font_color": {
+ "message": ""
+ },
+ "tab_filtered_selected_hover_background": {
+ "message": ""
+ },
+ "tab_filtered_selected_hover_border": {
+ "message": ""
+ },
+ "tab_filtered_selected_active_title_font_color": {
+ "message": ""
+ },
+ "tab_filtered_selected_active_background": {
+ "message": ""
+ },
+ "tab_filtered_selected_active_border": {
+ "message": ""
+ },
+ "tab_filtered_selected_active_hover_title_font_color": {
+ "message": ""
+ },
+ "tab_filtered_selected_active_hover_background": {
+ "message": ""
+ },
+ "tab_filtered_selected_active_hover_border": {
+ "message": ""
+ },
+ "tab_filtered_highlighted_search_title_font_color": {
+ "message": ""
+ },
+ "tab_filtered_highlighted_search_background": {
+ "message": ""
+ },
+ "tab_filtered_highlighted_search_border": {
+ "message": ""
+ },
+ "tab_filtered_highlighted_search_hover_title_font_color": {
+ "message": ""
+ },
+ "tab_filtered_highlighted_search_hover_background": {
+ "message": ""
+ },
+ "tab_filtered_highlighted_search_hover_border": {
+ "message": ""
+ },
+ "tab_filtered_active_highlighted_search_title_font_color": {
+ "message": ""
+ },
+ "tab_filtered_active_highlighted_search_background": {
+ "message": ""
+ },
+ "tab_filtered_active_highlighted_search_border": {
+ "message": ""
+ },
+ "tab_filtered_active_highlighted_search_hover_title_font_color": {
+ "message": ""
+ },
+ "tab_filtered_active_highlighted_search_hover_background": {
+ "message": ""
+ },
+ "tab_filtered_active_highlighted_search_hover_border": {
+ "message": ""
+ },
+ "tab_filtered_selected_highlighted_search_title_font_color": {
+ "message": ""
+ },
+ "tab_filtered_selected_highlighted_search_background": {
+ "message": ""
+ },
+ "tab_filtered_selected_highlighted_search_border": {
+ "message": ""
+ },
+ "tab_filtered_selected_highlighted_search_hover_title_font_color": {
+ "message": ""
+ },
+ "tab_filtered_selected_highlighted_search_hover_background": {
+ "message": ""
+ },
+ "tab_filtered_selected_highlighted_search_hover_border": {
+ "message": ""
+ },
+ "tab_filtered_selected_active_highlighted_search_title_font_color": {
+ "message": ""
+ },
+ "tab_filtered_selected_active_highlighted_search_background": {
+ "message": ""
+ },
+ "tab_filtered_selected_active_highlighted_search_border": {
+ "message": ""
+ },
+ "tab_filtered_selected_active_highlighted_search_hover_title_font_color": {
+ "message": ""
+ },
+ "tab_filtered_selected_active_highlighted_search_hover_background": {
+ "message": ""
+ },
+ "tab_filtered_selected_active_highlighted_search_hover_border": {
+ "message": ""
}
+
+
+
+
+
+
diff --git a/background.html b/background.html
deleted file mode 100644
index 0816c92..0000000
--- a/background.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/background.js b/background.js
new file mode 100644
index 0000000..eee9d98
--- /dev/null
+++ b/background.js
@@ -0,0 +1,614 @@
+// 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/
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////// START BACKGROUND SCRIPT /////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////
+
+
+document.addEventListener("DOMContentLoaded", function() {
+ if (browserId == "F") {
+ setTimeout(function() {
+ StartBackgroundListeners();
+ QuantumStart(0);
+ }, 500);
+ } else {
+ StartBackgroundListeners();
+ ChromiumLoadTabs(0);
+ }
+});
+
+////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////// BACKGROUND FUNCTIONS /////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////
+
+
+function pushlog(log) {
+ b.debug.push(log);
+ if (b.debug.length > 100) {
+ b.debug.splice(0, 1);
+ }
+ console.log(log);
+ b.schedule_save++;
+}
+
+
+function ReplaceParents(oldTabId, newTabId) {
+ for (let tabId in b.tabs) {
+ if (b.tabs[tabId].parent == oldTabId) {
+ b.tabs[tabId].parent = newTabId;
+ }
+ }
+}
+
+async function DiscardTab(tabId) {
+ let DiscardTimeout = 0;
+ let Discard = setInterval(function() {
+ chrome.tabs.get(tabId, function(tab) {
+ if ((tab.favIconUrl != undefined && tab.favIconUrl != "" && tab.title != undefined && tab.title != "") || tab.status == "complete" || tab.audible) {
+ chrome.tabs.discard(tab.id);
+ clearInterval(Discard);
+ }
+ if (DiscardTimeout > 300) {
+ clearInterval(Discard);
+ }
+ });
+ DiscardTimeout++;
+ }, 2000);
+}
+
+async function DiscardWindow(windowId) {
+ let DiscardTimeout = 0;
+ let DiscardedTabs = 0;
+ let Discard = setInterval(function() {
+ chrome.windows.get(windowId, {populate: true}, function(w) {
+ for (let i = 0; i < w.tabs.length; i++) {
+ if (w.tabs[i].discarded == false && w.tabs[i].active == false) {
+ if ((w.tabs[i].favIconUrl != undefined && w.tabs[i].favIconUrl != "" && w.tabs[i].title != undefined && w.tabs[i].title != "") || w.tabs[i].status == "complete" || tab.audible) {
+ chrome.tabs.discard(w.tabs[i].id);
+ DiscardedTabs++;
+ }
+ }
+ }
+ if (DiscardedTabs == w.tabs.length) {
+ clearInterval(Discard);
+ }
+ });
+ if (DiscardTimeout > 300) {
+ clearInterval(Discard);
+ }
+ DiscardTimeout++;
+ }, 5000);
+}
+
+function GetTabGroupId(tabId, windowId) {
+ let groupId = "tab_list";
+ if (tabId == undefined || windowId == undefined || b.windows[windowId] == undefined || b.tabs[tabId] == undefined) {
+ return groupId;
+ }
+ let parent = b.tabs[tabId].parent;
+ while (parent) {
+ if (isNaN(parent) == false && b.tabs[parent]) {
+ parent = b.tabs[parent].parent;
+ } else {
+ if (parent.match("tab_list|g_|f_") == null && b.tabs[parent]) {
+ parent = b.tabs[parent].parent;
+ } else {
+ if (parent.match("f_") != null && b.windows[windowId].folders[parent]) {
+ parent = b.windows[windowId].folders[parent].parent;
+ } else {
+ if (parent.match("pin_list|tab_list|g_") != null) {
+ groupId = parent;
+ parent = false;
+ } else {
+ parent = false;
+ }
+ }
+ }
+ }
+ }
+ return groupId;
+}
+
+function GetTabParents(tabId) {
+ let Parents = [];
+ if (tabId == undefined) {
+ return Parents;
+ }
+ if (b.tabs[tabId] == undefined) {
+ return Parents;
+ }
+ while (b.tabs[tabId].parent != "" && b.tabs[b.tabs[tabId].parent] != undefined) {
+ if (b.tabs[b.tabs[tabId].parent]) {
+ Parents.push(b.tabs[tabId].parent);
+ }
+ tabId = b.tabs[tabId].parent;
+ }
+ return Parents;
+}
+
+function GetChildren(parentId) {
+ let Children = [];
+ for (let tId in b.tabs) {
+ if (b.tabs[tId].parent == parentId) {
+ Children.push(parseInt(tId));
+ }
+ }
+ for (let i = 0; i < Children.length-1; i++) {
+ for (let j = i+1; j < Children.length; j++) {
+ if (b.tabs[Children[i]].index > b.tabs[Children[j]].index) {
+ let swap = Children[i];
+ Children[i] = Children[j];
+ Children[j] = swap;
+ }
+ }
+ }
+ return Children;
+}
+
+
+function AppendTabToGroupOnRegexMatch(tabId, windowId, url) {
+ let TabGroupId = GetTabGroupId(tabId, windowId);
+ for (let i = 0; i < opt.tab_group_regexes.length; i++) {
+ let regexPair = opt.tab_group_regexes[i];
+ if (url.match(regexPair[0])) {
+ let groupId = FindGroupIdByName(regexPair[1], b.windows[windowId].groups);
+ let groupName = regexPair[1];
+ if (groupId === null) { // no group
+ let newGroupID = "";
+ while (newGroupID == "") {
+ newGroupID = "g_"+GenerateRandomID();
+ for (let wId in b.windows) {
+ for (let gId in b.windows[wId].groups) {
+ console.log("check if group id exists");
+ if (gId == newGroupID) {
+ newGroupID = "";
+ console.log("yup, redo");
+ }
+ }
+ }
+ }
+ groupId = newGroupID;
+ b.windows[windowId].groups[groupId] = {id: groupId, index: 999, active_tab: 0, prev_active_tab: 0, active_tab_ttid: "", name: groupName, font: ""};
+ chrome.runtime.sendMessage({command: "append_group", groupId: groupId, group_name: groupName, font_color: "", windowId: windowId});
+ }
+ if (TabGroupId != groupId && groupId != null) {
+ b.tabs[tabId].parent = groupId;
+ setTimeout(function() {
+ chrome.runtime.sendMessage({command: "append_tab_to_group", tabId: tabId, groupId: groupId, windowId: windowId});
+ }, 100);
+ }
+ break;
+ }
+ }
+ return b.tabs[tabId].parent;
+}
+
+function FindGroupIdByName(name, groups) {
+ for (let groupId in groups) {
+ if (!groups.hasOwnProperty(groupId)) {
+ continue;
+ }
+ if (groups[groupId].name === name) {
+ return groupId;
+ }
+ }
+ return null;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////// QUANTUM //////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////
+
+
+function QuantumStart(retry) {
+ chrome.windows.getAll({windowTypes: ["normal"], populate: true}, function(w) {
+ if (w[0].tabs.length == 1 && (w[0].tabs[0].url == "about:blank" || w[0].tabs[0].url == "about:sessionrestore")) {
+ setTimeout(function() {
+ QuantumStart(retry+1);
+ }, 2000);
+ } else {
+ QuantumLoadTabs(0);
+ if (retry > 0) {
+ chrome.runtime.sendMessage({command: "reload_sidebar"});
+ }
+ setTimeout(function() {
+ b.schedule_save = 0;
+ }, 2000);
+ }
+ });
+}
+
+function QuantumLoadTabs(retry) {
+ chrome.windows.getAll({windowTypes: ["normal"], populate: true}, function(w) {
+ chrome.storage.local.get(null, function(storage) {
+ // LOAD PREFERENCES
+ GetCurrentPreferences(storage);
+
+ // CACHED COUNTS AND STUFF
+ // let b.tt_ids = {};
+ let tabs_matched = 0;
+ let tabs_count = 0;
+ for (let wIndex = 0; wIndex < w.length; wIndex++) {
+ tabs_count += w[wIndex].tabs.length;
+ }
+ let lastWinId = w[w.length-1].id;
+ let lastTabId = w[w.length-1].tabs[w[w.length-1].tabs.length-1].id;
+ let WinCount = w.length;
+
+ if (opt.debug == true) {
+ if (storage.debug_log != undefined) {
+ b.debug = storage.debug_log;
+ }
+ if (retry == 0) {
+ pushlog("TreeTabs background start");
+ }
+ }
+
+ for (let wIndex = 0; wIndex < WinCount; wIndex++) {
+ let winIndex = wIndex;
+ let winId = w[winIndex].id;
+ let tabsCount = w[winIndex].tabs.length;
+
+ // LOAD TTID FROM FIREFOX GET WINDOW VALUE
+ let win = Promise.resolve(browser.sessions.getWindowValue(winId, "TTdata")).then(function(WindowData) {
+ if (opt.skip_load == false && WindowData != undefined) {
+ b.windows[winId] = Object.assign({}, WindowData);
+ } else {
+ QuantumAppendWinTTId(winId);
+ }
+ for (let tIndex = 0; tIndex < tabsCount; tIndex++) {
+ let tab = w[winIndex].tabs[tIndex];
+ let tabIndex = tIndex;
+ let tabId = w[winIndex].tabs[tabIndex].id;
+ let tabPinned = w[winIndex].tabs[tabIndex].pinned;
+
+ if (tab.active) {
+ b.windows[winId].activeTabId[0] = tabId;
+ b.windows[winId].activeTabId[1] = tabId;
+ }
+
+ // LOAD TTID FROM FIREFOX GET TAB VALUE
+ let tt_tab = Promise.resolve(browser.sessions.getTabValue(tabId, "TTdata")).then(function(TabData) {
+ if (opt.skip_load == false && TabData != undefined) {
+ b.tabs[tabId] = Object.assign({}, TabData);
+ b.tt_ids[b.tabs[tabId].ttid] = tabId;
+ tabs_matched++;
+ } else {
+ QuantumAppendTabTTId(tab);
+ }
+ // IF ON LAST TAB AND LAST WINDOW, START MATCHING LOADED DATA
+ if (tabId == lastTabId && winId == lastWinId) {
+
+ // OK, DONE, NOW REPLACE OLD PARENTS IDS WITH THIS SESSION IDS
+ for (let ThisSessonTabId in b.tabs) {
+ if (b.tabs[ThisSessonTabId].parent_ttid != "" && b.tt_ids[b.tabs[ThisSessonTabId].parent_ttid] != undefined) {
+ b.tabs[ThisSessonTabId].parent = b.tt_ids[b.tabs[ThisSessonTabId].parent_ttid];
+ }
+ }
+
+ // OK, SAME THING FOR ACTIVE TABS IN GROUPS
+ for (let ThisSessonWinId in b.windows) {
+ for (let group in b.windows[ThisSessonWinId].groups) {
+ if (b.tt_ids[b.windows[ThisSessonWinId].groups[group].active_tab_ttid] != undefined) {
+ b.windows[ThisSessonWinId].groups[group].active_tab = b.tt_ids[b.windows[ThisSessonWinId].groups[group].active_tab_ttid];
+ }
+ if (b.tt_ids[b.windows[ThisSessonWinId].groups[group].prev_active_tab_ttid] != undefined) {
+ b.windows[ThisSessonWinId].groups[group].prev_active_tab = b.tt_ids[b.windows[ThisSessonWinId].groups[group].prev_active_tab_ttid];
+ }
+ }
+ }
+
+ if (opt.debug){ pushlog("QuantumLoadTabs, retry: "+retry); pushlog("Current windows count is: "+w.length); pushlog("Current tabs count is: "+tabs_count); pushlog("Matching tabs: "+tabs_matched); pushlog("Current windows:"); pushlog(w); }
+
+ // will try to find tabs for 3 times
+ if (opt.skip_load == true || retry > 2 || (tabs_matched > tabs_count*0.5)) {
+ b.running = true;
+ QuantumAutoSaveData();
+ QuantumStartListeners();
+ delete DefaultToolbar; delete DefaultTheme; delete DefaultPreferences;
+ } else {
+ if (opt.debug){
+ pushlog("Attempt "+retry+" failed, matched tabs was below 50%");
+ }
+ setTimeout(function() {
+ QuantumLoadTabs(retry+1);
+ }, 2000);
+ }
+ }
+ });
+ }
+ });
+ }
+ });
+ });
+}
+
+// save every second if there is anything to save obviously
+async function QuantumAutoSaveData() {
+ setInterval(function() {
+ if (b.schedule_save > 1) {
+ b.schedule_save = 1;
+ }
+ if (b.running && b.schedule_save > 0 && Object.keys(b.tabs).length > 1) {
+ chrome.windows.getAll({windowTypes: ['normal'], populate: true}, function(w) {
+ let WinCount = w.length;
+ for (let wIndex = 0; wIndex < WinCount; wIndex++) {
+ let winId = w[wIndex].id;
+ if (b.windows[winId] != undefined && b.windows[winId].ttid != undefined && b.windows[winId].group_bar != undefined && b.windows[winId].search_filter != undefined && b.windows[winId].active_shelf != undefined && b.windows[winId].active_group != undefined && b.windows[winId].groups != undefined && b.windows[winId].folders != undefined) {
+ browser.sessions.setWindowValue(winId, "TTdata", b.windows[winId] );
+ }
+ let TabsCount = w[wIndex].tabs.length;
+ for (let tabIndex = 0; tabIndex < TabsCount; tabIndex++) {
+ let tabId = w[wIndex].tabs[tabIndex].id;
+ if (b.tabs[tabId] != undefined && b.tabs[tabId].ttid != undefined && b.tabs[tabId].parent != undefined && b.tabs[tabId].index != undefined && b.tabs[tabId].expand != undefined) {
+ browser.sessions.setTabValue( tabId, "TTdata", b.tabs[tabId] );
+ }
+ }
+ }
+ b.schedule_save--;
+ });
+ }
+ if (opt.debug == true) { chrome.storage.local.set({debug_log: b.debug}); }
+ }, 1000);
+}
+
+function QuantumGenerateNewWindowID() {
+ let newID = "";
+ while (newID == "") {
+ newID = "w_"+GenerateRandomID();
+ for (let wId in b.windows) {
+ if (wId == newID) {
+ newID = "";
+ }
+ }
+ }
+ return newID;
+}
+
+function QuantumGenerateNewTabID() {
+ let newID = "";
+ while (newID == "") {
+ newID = "t_"+GenerateRandomID();
+ for (let tId in b.tabs) {
+ if (tId == newID) {
+ newID = "";
+ }
+ }
+ }
+ return newID;
+}
+
+function QuantumAppendTabTTId(tab) {
+ let NewTTTabId = QuantumGenerateNewTabID();
+ if (b.tabs[tab.id] != undefined) {
+ b.tabs[tab.id].ttid = NewTTTabId;
+ } else {
+ b.tabs[tab.id] = {ttid: NewTTTabId, parent: (b.windows[tab.windowId] ? b.windows[tab.windowId].active_group : "tab_list"), parent_ttid: "", index: tab.index, expand: ""};
+ }
+ b.tt_ids[NewTTTabId] = tab.id;
+ return NewTTTabId;
+ // if (b.schedule_save > 0) browser.sessions.setTabValue( tab.id, "TTdata", b.tabs[tab.id] );
+}
+
+function QuantumAppendWinTTId(windowId) {
+ let NewTTWindowId = QuantumGenerateNewWindowID();
+ 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: {}};
+ }
+ // if (b.schedule_save > 0) browser.sessions.setWindowValue( windowId, "TTdata", b.windows[windowId] );
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////// CHROMIUM /////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////
+
+function ChromiumLoadTabs(retry) {
+ chrome.windows.getAll({windowTypes: ['normal'], populate: true}, function(w) {
+ chrome.storage.local.get(null, function(storage) {
+ // LOAD PREFERENCES
+ GetCurrentPreferences(storage);
+
+ // load tabs and windows from storage
+ let refTabs = {};
+ let tabs_matched = 0;
+ let w_count = storage.w_count ? storage.w_count : 0;
+ let t_count = storage.t_count ? storage.t_count : 0;
+ let LoadedWindows = storage.windows ? storage.windows : [];
+ let LoadedTabs = storage.tabs ? storage.tabs : [];
+ let CurrentTabsCount = 0;
+ for (let wIndex = 0; wIndex < w.length; wIndex++) {
+ CurrentTabsCount += w[wIndex].tabs.length;
+ }
+
+ let bak = (1 + retry) <= 3 ? (1 + retry) : 3;
+
+ if (opt.skip_load == false) {
+ // if loaded tabs mismatch by 50%, then try to load back
+ if (LoadedTabs.length < t_count*0.5) {
+ LoadedTabs = storage["tabs_BAK"+bak] ? storage["tabs_BAK"+bak] : [];
+ }
+ // if loaded windows mismatch, then try to load back
+ if (LoadedWindows.length < w_count) {
+ LoadedWindows = storage["windows_BAK"+bak] ? storage["windows_BAK"+bak] : [];
+ }
+ } else {
+ tabs_matched = CurrentTabsCount;
+ }
+
+ if (opt.debug == true) {
+ if (storage.debug_log != undefined) {
+ b.debug = storage.debug_log;
+ }
+ if (retry == 0) {
+ pushlog("TreeTabs background start");
+ }
+ }
+
+ // CACHED COUNTS
+ let WinCount = w.length;
+ let LoadedWinCount = LoadedWindows.length;
+ let LoadedTabsCount = LoadedTabs.length;
+
+ for (let wIndex = 0; wIndex < WinCount; wIndex++) {
+ if (w[wIndex].tabs[0].url != "chrome://videopopout/") { // this is for opera for their extra video popup, which is weirdly queried as a "normal" window
+ let winId = w[wIndex].id;
+ let url1 = w[wIndex].tabs[0].url;
+ let url2 = w[wIndex].tabs[w[wIndex].tabs.length-1].url;
+ ChromiumAddWindowData(winId);
+
+ if (opt.skip_load == false) {
+ for (let LwIndex = 0; LwIndex < LoadedWinCount; LwIndex++) {
+ if (LoadedWindows[LwIndex].url1 == url1 || LoadedWindows[LwIndex].url2 == url2) {
+ if (LoadedWindows[LwIndex].group_bar) { b.windows[winId].group_bar = LoadedWindows[LwIndex].group_bar; }
+ if (LoadedWindows[LwIndex].search_filter) { b.windows[winId].search_filter = LoadedWindows[LwIndex].search_filter; }
+ if (LoadedWindows[LwIndex].active_shelf) { b.windows[winId].active_shelf = LoadedWindows[LwIndex].active_shelf; }
+ if (LoadedWindows[LwIndex].active_group) { b.windows[winId].active_group = LoadedWindows[LwIndex].active_group; }
+ if (Object.keys(LoadedWindows[LwIndex].groups).length > 0) { b.windows[winId].groups = Object.assign({}, LoadedWindows[LwIndex].groups); }
+ if (Object.keys(LoadedWindows[LwIndex].folders).length > 0) { b.windows[winId].folders = Object.assign({}, LoadedWindows[LwIndex].folders); }
+ LoadedWindows[LwIndex].url1 = "";
+ LoadedWindows[LwIndex].url2 = "";
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // add new hashes for current tabs
+ for (let wIndex = 0; wIndex < WinCount; wIndex++) {
+ let TabsCount = w[wIndex].tabs.length;
+ for (let tabIndex = 0; tabIndex < TabsCount; tabIndex++) {
+ 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;
+ }
+
+ }
+ }
+
+ // compare saved tabs from storage to current session tabs, but can be skipped if set in options
+ if (opt.skip_load == false && LoadedTabs.length > 0) {
+ for (let wIndex = 0; wIndex < WinCount; wIndex++) {
+ let TabsCount = w[wIndex].tabs.length;
+ for (let tabIndex = 0; tabIndex < TabsCount; tabIndex++) {
+ for (let LtabIndex = 0; LtabIndex < LoadedTabsCount; LtabIndex++) {
+ let tabId = w[wIndex].tabs[tabIndex].id;
+ if (LoadedTabs[LtabIndex].hash == b.tabs[tabId].hash && refTabs[LoadedTabs[LtabIndex].id] == undefined) {
+ refTabs[LoadedTabs[LtabIndex].id] = tabId;
+ if (LoadedTabs[LtabIndex].parent) { b.tabs[tabId].parent = LoadedTabs[LtabIndex].parent; }
+ if (LoadedTabs[LtabIndex].index) { b.tabs[tabId].index = LoadedTabs[LtabIndex].index; }
+ if (LoadedTabs[LtabIndex].expand) { b.tabs[tabId].expand = LoadedTabs[LtabIndex].expand; }
+ LoadedTabs[LtabIndex].hash = undefined;
+ tabs_matched++;
+ break;
+ }
+ }
+ }
+ }
+ // replace parents tabIds for new ones, for that purpose refTabs was made before
+ for (let tabId in b.tabs) {
+ if (refTabs[b.tabs[tabId].parent] != undefined) {
+ b.tabs[tabId].parent = refTabs[b.tabs[tabId].parent];
+ }
+ }
+ // replace active tab ids for each group using refTabs
+ for (let windowId in b.windows) {
+ for (let group in b.windows[windowId].groups) {
+ if (refTabs[b.windows[windowId].groups[group].active_tab]) {
+ b.windows[windowId].groups[group].active_tab = refTabs[b.windows[windowId].groups[group].active_tab];
+ }
+ if (refTabs[b.windows[windowId].groups[group].prev_active_tab]) {
+ b.windows[windowId].groups[group].prev_active_tab = refTabs[b.windows[windowId].groups[group].prev_active_tab];
+ }
+ }
+ }
+ }
+
+ if (opt.debug){
+ pushlog("ChromiumLoadTabs, retry: "+retry); pushlog("Current windows count is: "+w.length); pushlog("Saved windows count is: "+LoadedWindows.length); pushlog("Current tabs count is: "+CurrentTabsCount);
+ pushlog("Loaded tabs count is: "+LoadedTabsCount); pushlog("Matching tabs: "+tabs_matched); pushlog("Current windows:"); pushlog(w);
+ }
+
+ // will loop trying to find tabs
+ if (opt.skip_load || retry >= 5 || (tabs_matched > t_count*0.5)) {
+ b.running = true;
+ ChromiumAutoSaveData(0, 1000); ChromiumAutoSaveData(1, 300000); ChromiumAutoSaveData(2, 600000); ChromiumAutoSaveData(3, 1800000);
+ ChromiumStartListeners();
+ delete DefaultToolbar; delete DefaultTheme; delete DefaultPreferences;
+ b.schedule_save = -1; // 2 operations must be made to start saving data
+ } else {
+ if (opt.debug){
+ pushlog("Attempt "+retry+" failed, matched tabs was below 50%");
+ }
+ setTimeout(function() {
+ ChromiumLoadTabs(retry+1);
+ }, 5000);
+ }
+ });
+ });
+}
+
+async function ChromiumAutoSaveData(BAK, LoopTimer) {
+ setInterval(function() {
+ if (b.schedule_save > 1 || BAK > 0) {
+ b.schedule_save = 1;
+ }
+ if (b.running && b.schedule_save > 0 && Object.keys(b.tabs).length > 1) {
+ chrome.windows.getAll({windowTypes: ['normal'], populate: true}, function(w) {
+ let WinCount = w.length;
+ let t_count = 0;
+ let counter = 0;
+ let Windows = [];
+ let Tabs = [];
+ for (let wIndex = 0; wIndex < WinCount; wIndex++) {
+ t_count += w[wIndex].tabs.length;
+ }
+ for (let wIndex = 0; wIndex < WinCount; wIndex++) {
+ let winId = w[wIndex].id;
+ if (b.windows[winId] != undefined && b.windows[winId].group_bar != undefined && b.windows[winId].search_filter != undefined && b.windows[winId].active_shelf != undefined && b.windows[winId].active_group != undefined && b.windows[winId].groups != undefined && b.windows[winId].folders != undefined) {
+ Windows.push({ url1: w[wIndex].tabs[0].url, url2: w[wIndex].tabs[w[wIndex].tabs.length-1].url, group_bar: b.windows[winId].group_bar, search_filter: b.windows[winId].search_filter, active_shelf: b.windows[winId].active_shelf, active_group: b.windows[winId].active_group, groups: b.windows[winId].groups, folders: b.windows[winId].folders });
+ }
+ let TabsCount = w[wIndex].tabs.length;
+ for (let tabIndex = 0; tabIndex < TabsCount; tabIndex++) {
+ let tabId = w[wIndex].tabs[tabIndex].id;
+ if (b.tabs[tabId] != undefined && b.tabs[tabId].hash != undefined && b.tabs[tabId].parent != undefined && b.tabs[tabId].index != undefined && b.tabs[tabId].expand != undefined) {
+ Tabs.push({ id: tabId, hash: b.tabs[tabId].hash, parent: b.tabs[tabId].parent, index: b.tabs[tabId].index, expand: b.tabs[tabId].expand });
+ counter++;
+ }
+ }
+ if (counter == t_count) {
+ chrome.storage.local.set({t_count: t_count});
+ chrome.storage.local.set({w_count: WinCount});
+ if (BAK == 0) { chrome.storage.local.set({windows: Windows}); chrome.storage.local.set({tabs: Tabs}); }
+ if (BAK == 1) { chrome.storage.local.set({windows_BAK1: Windows}); chrome.storage.local.set({tabs_BAK1: Tabs}); chrome.runtime.sendMessage({command: "backup_available", bak: 1}); }
+ if (BAK == 2) { chrome.storage.local.set({windows_BAK2: Windows}); chrome.storage.local.set({tabs_BAK2: Tabs}); chrome.runtime.sendMessage({command: "backup_available", bak: 2}); }
+ if (BAK == 3) { chrome.storage.local.set({windows_BAK3: Windows}); chrome.storage.local.set({tabs_BAK3: Tabs}); chrome.runtime.sendMessage({command: "backup_available", bak: 3}); }
+ }
+ }
+ b.schedule_save--;
+ });
+ }
+ if (opt.debug == true) { chrome.storage.local.set({debug_log: b.debug}); }
+ }, 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: {}};
+}
+
+function ChromiumHashURL(tab) {
+ if (b.tabs[tab.id] == undefined) { b.tabs[tab.id] = {hash: 0, parent: tab.pinned ? "pin_list" : (b.windows[tab.windowId] ? b.windows[tab.windowId].active_group : "tab_list"), index: (Object.keys(b.tabs).length + 1), expand: "n"}; }
+ let hash = 0;
+ for (let charIndex = 0; charIndex < tab.url.length; charIndex++) {
+ hash += tab.url.charCodeAt(charIndex);
+ }
+ b.tabs[tab.id].hash = hash;
+}
diff --git a/bg_ch.js b/bg_ch.js
deleted file mode 100644
index 754fe19..0000000
--- a/bg_ch.js
+++ /dev/null
@@ -1,460 +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/
-
-
-function ChromeLoadTabs(retry) {
- chrome.windows.getAll({windowTypes: ['normal'], populate: true}, function(w) {
- chrome.storage.local.get(null, function(storage) {
- // LOAD PREFERENCES
- GetCurrentPreferences(storage);
-
- // load tabs and windows from storage
- let refTabs = {};
- let tabs_matched = 0;
- let w_count = storage.w_count ? storage.w_count : 0;
- let t_count = storage.t_count ? storage.t_count : 0;
- let LoadedWindows = storage.windows ? storage.windows : [];
- let LoadedTabs = storage.tabs ? storage.tabs : [];
-
- let bak = (1 + retry) <= 3 ? (1 + retry) : 3;
-
- // if loaded tabs mismatch by 50%, then try to load back
- if (LoadedTabs.length < t_count*0.5) {
- LoadedTabs = storage["tabs_BAK"+bak] ? storage["tabs_BAK"+bak] : [];
- }
- // if loaded windows mismatch, then try to load back
- if (LoadedWindows.length < w_count) {
- LoadedWindows = storage["windows_BAK"+bak] ? storage["windows_BAK"+bak] : [];
- }
-
- if (opt.debug == true) {
- if (storage.debug_log != undefined) {
- debug = storage.debug_log;
- }
- if (retry == 0) {
- pushlog("TreeTabs background start");
- }
- }
-
- // CACHED COUNTS
- let WinCount = w.length;
- let LoadedWinCount = LoadedWindows.length;
- let LoadedTabsCount = LoadedTabs.length;
-
- let CurrentTabsCount = 0;
- for (let wIndex = 0; wIndex < w.length; wIndex++) {
- CurrentTabsCount += w[wIndex].tabs.length;
- }
-
- for (let wIndex = 0; wIndex < WinCount; wIndex++) {
- if (w[wIndex].tabs[0].url != "chrome://videopopout/") { // this is for opera for their extra video popup, which is weirdly queried as a "normal" window
- let winId = w[wIndex].id;
- let url1 = w[wIndex].tabs[0].url;
- let url2 = w[wIndex].tabs[w[wIndex].tabs.length-1].url;
- windows[winId] = {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: caption_ungrouped_group, font: ""}}, folders: {}};
- for (let LwIndex = 0; LwIndex < LoadedWinCount; LwIndex++) {
- if (LoadedWindows[LwIndex].url1 == url1 || LoadedWindows[LwIndex].url2 == url2) {
- if (LoadedWindows[LwIndex].group_bar) { windows[winId].group_bar = LoadedWindows[LwIndex].group_bar; }
- if (LoadedWindows[LwIndex].search_filter) { windows[winId].search_filter = LoadedWindows[LwIndex].search_filter; }
- if (LoadedWindows[LwIndex].active_shelf) { windows[winId].active_shelf = LoadedWindows[LwIndex].active_shelf; }
- if (LoadedWindows[LwIndex].active_group) { windows[winId].active_group = LoadedWindows[LwIndex].active_group; }
- if (Object.keys(LoadedWindows[LwIndex].groups).length > 0) { windows[winId].groups = Object.assign({}, LoadedWindows[LwIndex].groups); }
- if (Object.keys(LoadedWindows[LwIndex].folders).length > 0) { windows[winId].folders = Object.assign({}, LoadedWindows[LwIndex].folders); }
- LoadedWindows[LwIndex].url1 = "";
- LoadedWindows[LwIndex].url2 = "";
- break;
- }
- }
- }
- }
- for (let wIndex = 0; wIndex < WinCount; wIndex++) {
- let TabsCount = w[wIndex].tabs.length;
- for (let tabIndex = 0; tabIndex < TabsCount; tabIndex++) {
- ChromeHashURL(w[wIndex].tabs[tabIndex]);
- }
- }
-
- if (opt.skip_load == false && LoadedTabs.length > 0) { // compare saved tabs from storage to current session tabs, but can be skipped if set in options
- for (let wIndex = 0; wIndex < WinCount; wIndex++) { // match loaded tabs
- let TabsCount = w[wIndex].tabs.length;
- for (let tabIndex = 0; tabIndex < TabsCount; tabIndex++) {
- for (let LtabIndex = 0; LtabIndex < LoadedTabsCount; LtabIndex++) {
- let tabId = w[wIndex].tabs[tabIndex].id;
- if (LoadedTabs[LtabIndex].hash == tabs[tabId].hash && refTabs[LoadedTabs[LtabIndex].id] == undefined) {
- refTabs[LoadedTabs[LtabIndex].id] = tabId;
- if (LoadedTabs[LtabIndex].parent) { tabs[tabId].parent = LoadedTabs[LtabIndex].parent; }
- if (LoadedTabs[LtabIndex].index) { tabs[tabId].index = LoadedTabs[LtabIndex].index; }
- if (LoadedTabs[LtabIndex].expand) { tabs[tabId].expand = LoadedTabs[LtabIndex].expand; }
- LoadedTabs[LtabIndex].hash = undefined;
- tabs_matched++;
- break;
- }
- }
- }
- }
- // replace parents tabIds for new ones, for that purpose refTabs was made before
- for (let tabId in tabs) {
- if (refTabs[tabs[tabId].parent] != undefined) {
- tabs[tabId].parent = refTabs[tabs[tabId].parent];
- }
- }
- }
- // replace active tab ids for each group using refTabs
- for (let windowId in windows) {
- for (let group in windows[windowId].groups) {
- if (refTabs[windows[windowId].groups[group].active_tab]) {
- windows[windowId].groups[group].active_tab = refTabs[windows[windowId].groups[group].active_tab];
- }
- if (refTabs[windows[windowId].groups[group].prev_active_tab]) {
- windows[windowId].groups[group].prev_active_tab = refTabs[windows[windowId].groups[group].prev_active_tab];
- }
- }
- }
-
- if (opt.debug){
- pushlog("ChromeLoadTabs, retry: "+retry);
- pushlog("Current windows count is: "+w.length);
- pushlog("Saved windows count is: "+LoadedWindows.length);
- pushlog("Current tabs count is: "+CurrentTabsCount);
- pushlog("Loaded tabs count is: "+LoadedTabsCount);
- pushlog("Matching tabs: "+tabs_matched);
- pushlog("Current windows:");
- pushlog(w);
- }
-
- // will loop trying to find tabs
- if (opt.skip_load == true || retry >= 5 || (tabs_matched > t_count*0.5)) {
- running = true;
- ChromeAutoSaveData(0, 1000);
- ChromeAutoSaveData(1, 300000);
- ChromeAutoSaveData(2, 600000);
- ChromeAutoSaveData(3, 1800000);
- ChromeListeners();
-
- delete schedule_update_data;
- delete schedule_rearrange_tabs;
- delete DragNodeClass;
- delete DragOverTimer;
- delete DragTreeDepth;
- delete menuItemNode;
- delete CurrentWindowId;
- delete SearchIndex;
- delete active_group;
- delete browserId;
- delete bggroups;
- delete bgfolders;
- delete caption_clear_filter;
- delete caption_loading;
- delete caption_searchbox;
- delete DefaultToolbar;
- delete DefaultTheme;
- delete DefaultPreferences;
-
- delete newTabUrl;
- delete EmptyTabs;
-
- delete tt_ids;
-
- schedule_save = -1; // 2 operations must be made to start saving data
- } else {
- if (opt.debug){
- pushlog("Attempt "+retry+" failed, matched tabs was below 50%");
- }
- setTimeout(function() {
- ChromeLoadTabs(retry+1);
- }, 5000);
- }
- });
- });
-}
-// You maybe are asking yourself why I save tabs in array? It's because, instead of, keeping 2 index numbers (one for browser tabs on top and one for my index in tree), it's easier to just arrange them in order and save it in localstorage.
-// Another reason is that Object does not preserve order in chrome, I've been told that in Firefox it is. But I can't trust that.
-async function ChromeAutoSaveData(BAK, LoopTimer) {
- setInterval(function() {
- if (schedule_save > 1 || BAK > 0) {
- schedule_save = 1;
- }
- if (running && schedule_save > 0 && Object.keys(tabs).length > 1) {
- chrome.windows.getAll({windowTypes: ['normal'], populate: true}, function(w) {
- let WinCount = w.length;
- let t_count = 0;
- let counter = 0;
- let Windows = [];
- let Tabs = [];
- for (let wIndex = 0; wIndex < WinCount; wIndex++) {
- t_count += w[wIndex].tabs.length;
- }
- for (let wIndex = 0; wIndex < WinCount; wIndex++) {
- let winId = w[wIndex].id;
- if (windows[winId] != undefined && windows[winId].group_bar != undefined && windows[winId].search_filter != undefined && windows[winId].active_shelf != undefined && windows[winId].active_group != undefined && windows[winId].groups != undefined && windows[winId].folders != undefined) {
- Windows.push({url1: w[wIndex].tabs[0].url, url2: w[wIndex].tabs[w[wIndex].tabs.length-1].url, group_bar: windows[winId].group_bar, search_filter: windows[winId].search_filter, active_shelf: windows[winId].active_shelf, active_group: windows[winId].active_group, groups: windows[winId].groups, folders: windows[winId].folders});
- }
- let TabsCount = w[wIndex].tabs.length;
- for (let tabIndex = 0; tabIndex < TabsCount; tabIndex++) {
- let tabId = w[wIndex].tabs[tabIndex].id;
- if (tabs[tabId] != undefined && tabs[tabId].hash != undefined && tabs[tabId].parent != undefined && tabs[tabId].index != undefined && tabs[tabId].expand != undefined) {
- Tabs.push({id: tabId, hash: tabs[tabId].hash, parent: tabs[tabId].parent, index: tabs[tabId].index, expand: tabs[tabId].expand});
- counter++;
- }
- }
- if (counter == t_count) {
- chrome.storage.local.set({t_count: t_count});
- chrome.storage.local.set({w_count: WinCount});
-
- if (BAK == 0) {
- chrome.storage.local.set({windows: Windows});
- chrome.storage.local.set({tabs: Tabs});
- }
- if (BAK == 1) {
- chrome.storage.local.set({windows_BAK1: Windows});
- chrome.storage.local.set({tabs_BAK1: Tabs});
- chrome.runtime.sendMessage({command: "backup_available", bak: 1});
- }
- if (BAK == 2) {
- chrome.storage.local.set({windows_BAK2: Windows});
- chrome.storage.local.set({tabs_BAK2: Tabs});
- chrome.runtime.sendMessage({command: "backup_available", bak: 2});
- }
- if (BAK == 3) {
- chrome.storage.local.set({windows_BAK3: Windows});
- chrome.storage.local.set({tabs_BAK3: Tabs});
- chrome.runtime.sendMessage({command: "backup_available", bak: 3});
- }
- }
- }
- schedule_save--;
- });
- }
-
- if (opt.debug == true) {
- chrome.storage.local.set({debug_log: debug});
- }
-
- }, LoopTimer);
-}
-function ChromeHashURL(tab) {
- if (tabs[tab.id] == undefined) {
- tabs[tab.id] = {hash: 0, parent: tab.pinned ? "pin_list" : (windows[tab.windowId] ? windows[tab.windowId].active_group : "tab_list"), index: tab.index, expand: "n"};
- }
- let hash = 0;
- for (let charIndex = 0; charIndex < tab.url.length; charIndex++) {
- hash += tab.url.charCodeAt(charIndex);
- }
- tabs[tab.id].hash = hash;
-}
-function ReplaceParents(oldTabId, newTabId) {
- for (let tabId in tabs) {
- if (tabs[tabId].parent == oldTabId) {
- tabs[tabId].parent = newTabId;
- }
- }
-}
-function ChromeListeners() { // start all listeners
- chrome.tabs.onCreated.addListener(function(tab) {
- ChromeHashURL(tab);
- chrome.runtime.sendMessage({command: "tab_created", windowId: tab.windowId, tabId: tab.id});
- schedule_save++;
- });
- chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) {
- setTimeout(function() { chrome.runtime.sendMessage({command: "tab_removed", windowId: removeInfo.windowId, tabId: tabId}); },5);
- delete tabs[tabId];
- schedule_save++;
- });
- chrome.tabs.onAttached.addListener(function(tabId, attachInfo) {
- chrome.tabs.get(tabId, function(tab) {
- chrome.runtime.sendMessage({command: "tab_attached", windowId: attachInfo.newWindowId, tab: tab, tabId: tabId, ParentId: tabs[tabId].parent});
- });
- schedule_save++;
- });
- chrome.tabs.onDetached.addListener(function(tabId, detachInfo) {
- chrome.runtime.sendMessage({command: "tab_detached", windowId: detachInfo.oldWindowId, tabId: tabId});
- schedule_save++;
- });
- chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
- if (tabs[tabId] == undefined || changeInfo.url != undefined) {
- ChromeHashURL(tab);
- }
- if (changeInfo.pinned != undefined) {
- schedule_save++;
- }
- if (changeInfo.pinned == true) {
- tabs[tabId].parent = "pin_list";
- }
- if (changeInfo.title != undefined && !tab.active) {
- chrome.runtime.sendMessage({command: "tab_attention", windowId: tab.windowId, tabId: tabId});
- }
- chrome.runtime.sendMessage({command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tabId, changeInfo: changeInfo});
- });
- chrome.tabs.onMoved.addListener(function(tabId, moveInfo) {
- schedule_save++;
- });
- chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId) {
- chrome.tabs.get(addedTabId, function(tab) {
- if (addedTabId == removedTabId) {
- chrome.runtime.sendMessage({command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tab.id, changeInfo: {status: tab.status, url: tab.url, title: tab.title, audible: tab.audible, mutedInfo: tab.mutedInfo}});
- } else {
- ReplaceParents(tabId, tab.id);
- if (tabs[removedTabId]) {
- tabs[addedTabId] = tabs[removedTabId];
- } else {
- ChromeHashURL(tab);
- }
- chrome.runtime.sendMessage({command: "tab_removed", windowId: tab.windowId, tabId: removedTabId});
- chrome.runtime.sendMessage({command: "tab_attached", windowId: tab.windowId, tab: tab, tabId: addedTabId});
- delete tabs[removedTabId];
- }
- schedule_save++;
- });
- });
- chrome.tabs.onActivated.addListener(function(activeInfo) {
- chrome.runtime.sendMessage({command: "tab_activated", windowId: activeInfo.windowId, tabId: activeInfo.tabId});
- });
- chrome.windows.onCreated.addListener(function(window) {
- windows[window.id] = {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: caption_ungrouped_group, font: ""}}, folders: {}};
- schedule_save++;
- });
- chrome.windows.onRemoved.addListener(function(windowId) {
- delete windows[windowId];
- schedule_save++;
- });
- chrome.runtime.onSuspend.addListener(function() {
- running = false;
- });
-}
-function ChromeMessageListeners() {
- chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
-
- if (message.command == "reload") {
- window.location.reload();
- return;
- }
- if (message.command == "get_windows") {
- sendResponse(windows);
- return;
- }
- if (message.command == "get_folders") {
- if (windows[message.windowId]) {
- sendResponse(windows[message.windowId].folders);
- }
- return;
- }
- if (message.command == "save_folders") {
- if (windows[message.windowId]) {
- windows[message.windowId].folders = Object.assign({}, message.folders);
- schedule_save++;
- }
- return;
- }
- if (message.command == "get_groups") {
- if (windows[message.windowId]) {
- sendResponse(windows[message.windowId].groups);
- }
- return;
- }
- if (message.command == "save_groups") {
- if (windows[message.windowId]) {
- windows[message.windowId].groups = Object.assign({}, message.groups);
- schedule_save++;
- }
- return;
- }
- if (message.command == "set_active_group") {
- if (windows[message.windowId]) {
- windows[message.windowId].active_group = message.active_group;
- schedule_save++;
- }
- return;
- }
- if (message.command == "get_active_group") {
- if (windows[message.windowId]) {
- sendResponse(windows[message.windowId].active_group);
- }
- return;
- }
- if (message.command == "set_search_filter") {
- if (windows[message.windowId]) {
- windows[message.windowId].search_filter = message.search_filter;
- schedule_save++;
- }
- return;
- }
- if (message.command == "get_search_filter") {
- if (windows[message.windowId]) {
- sendResponse(windows[message.windowId].search_filter);
- }
- return;
- }
- if (message.command == "set_active_shelf") {
- if (windows[message.windowId]) {
- windows[message.windowId].active_shelf = message.active_shelf;
- schedule_save++;
- }
- return;
- }
- if (message.command == "get_active_shelf") {
- if (windows[message.windowId]) {
- sendResponse(windows[message.windowId].active_shelf);
- }
- return;
- }
- if (message.command == "set_group_bar") {
- if (windows[message.windowId]) {
- windows[message.windowId].group_bar = message.group_bar;
- schedule_save++;
- }
- return;
- }
- if (message.command == "get_group_bar") {
- if (windows[message.windowId]) {
- sendResponse(windows[message.windowId].group_bar);
- }
- return;
- }
- if (message.command == "get_browser_tabs") {
- sendResponse(tabs);
- return;
- }
- if (message.command == "is_bg_ready") {
- sendResponse(running);
- return;
- }
- if (message.command == "update_tab") {
- if (tabs[message.tabId]) {
- if (message.tab.index) {
- tabs[message.tabId].index = message.tab.index;
- }
- if (message.tab.expand) {
- tabs[message.tabId].expand = message.tab.expand;
- }
- if (message.tab.parent) {
- tabs[message.tabId].parent = message.tab.parent;
- }
- schedule_save++;
- }
- return;
- }
- if (message.command == "update_all_tabs") {
- for (let i = 0; i < message.pins.length; i++) {
- if (tabs[message.pins[i].id]) {
- tabs[message.pins[i].id].parent = "pin_list";
- tabs[message.pins[i].id].expand = "";
- tabs[message.pins[i].id].index = message.pins[i].index;
- }
- }
- for (let j = 0; j < message.tabs.length; j++) {
- if (tabs[message.tabs[j].id]) {
- tabs[message.tabs[j].id].parent = message.tabs[j].parent;
- tabs[message.tabs[j].id].expand = message.tabs[j].expand;
- tabs[message.tabs[j].id].index = message.tabs[j].index;
- }
- }
- schedule_save++;
- return;
- }
- if (message.command == "debug") {
- pushlog(message.log);
- return;
- }
- });
-}
\ No newline at end of file
diff --git a/bg_ff.js b/bg_ff.js
deleted file mode 100644
index 43c44ba..0000000
--- a/bg_ff.js
+++ /dev/null
@@ -1,525 +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/
-
-function FirefoxStart(retry) {
- chrome.windows.getAll({windowTypes: ["normal"], populate: true}, function(w) {
- if (w[0].tabs.length == 1 && (w[0].tabs[0].url == "about:blank" || w[0].tabs[0].url == "about:sessionrestore")) {
- setTimeout(function() {
- FirefoxStart(retry+1);
- }, 2000);
- } else {
- FirefoxLoadTabs(0);
- if (retry > 0) {
- chrome.runtime.sendMessage({command: "reload_sidebar"});
- }
- setTimeout(function() {
- schedule_save = 0;
- }, 2000);
- }
- });
-}
-function FirefoxLoadTabs(retry) {
- chrome.windows.getAll({windowTypes: ["normal"], populate: true}, function(w) {
- chrome.storage.local.get(null, function(storage) {
- // LOAD PREFERENCES
- GetCurrentPreferences(storage);
-
- // CACHED COUNTS AND STUFF
- // let tt_ids = {};
- let tabs_matched = 0;
- let tabs_count = 0;
- for (let wIndex = 0; wIndex < w.length; wIndex++) {
- tabs_count += w[wIndex].tabs.length;
- }
- let lastWinId = w[w.length-1].id;
- let lastTabId = w[w.length-1].tabs[w[w.length-1].tabs.length-1].id;
- let WinCount = w.length;
-
- if (opt.debug == true) {
- if (storage.debug_log != undefined) {
- debug = storage.debug_log;
- }
- if (retry == 0) {
- pushlog("TreeTabs background start");
- }
- }
-
- for (let wIndex = 0; wIndex < WinCount; wIndex++) {
- let winIndex = wIndex;
- let winId = w[winIndex].id;
- let tabsCount = w[winIndex].tabs.length;
-
- // LOAD TTID FROM FIREFOX GET WINDOW VALUE
- let win = Promise.resolve(browser.sessions.getWindowValue(winId, "TTdata")).then(function(WindowData) {
- if (opt.skip_load == false && WindowData != undefined) {
- windows[winId] = Object.assign({}, WindowData);
- } else {
- windows[winId] = {ttid: "", 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: caption_ungrouped_group, font: ""}}, folders: {}};
- }
- for (let tIndex = 0; tIndex < tabsCount; tIndex++) {
- let tabIndex = tIndex;
- let tabId = w[winIndex].tabs[tabIndex].id;
- let tabPinned = w[winIndex].tabs[tabIndex].pinned;
- // LOAD TTID FROM FIREFOX GET TAB VALUE
- let tab = Promise.resolve(browser.sessions.getTabValue(tabId, "TTdata")).then(function(TabData) {
- if (opt.skip_load == false && TabData != undefined) {
- tabs[tabId] = Object.assign({}, TabData);
- tt_ids[tabs[tabId].ttid] = tabId;
- tabs_matched++;
- } else {
- tabs[tabId] = {ttid: "", parent_ttid: "", parent: tabPinned ? "pin_list" : "tab_list", index: tabIndex, expand: ""};
- }
- // IF ON LAST TAB AND LAST WINDOW, START MATCHING LOADED DATA
- if (tabId == lastTabId && winId == lastWinId) {
- for (let ThisSessonWinId in windows) {
- if (windows[ThisSessonWinId].ttid == "") {
- AppendWinTTId(parseInt(ThisSessonWinId));
- }
- }
- // OK, DONE WITH WINDOWS, START TABS LOOP
- for (let ThisSessonTabId in tabs) {
- if (tabs[ThisSessonTabId].ttid == "") {
- AppendTabTTId(parseInt(ThisSessonTabId));
- }
- }
- // OK, DONE, NOW REPLACE OLD PARENTS IDS WITH THIS SESSION IDS
- for (let ThisSessonTabId in tabs) {
- if (tt_ids[tabs[ThisSessonTabId].parent_ttid] != undefined) {
- tabs[ThisSessonTabId].parent = tt_ids[tabs[ThisSessonTabId].parent_ttid];
- }
- }
- // OK, SAME THING FOR ACTIVE TABS IN GROUPS
- for (let ThisSessonWinId in windows) {
- for (let group in windows[ThisSessonWinId].groups) {
- if (tt_ids[windows[ThisSessonWinId].groups[group].active_tab_ttid] != undefined) {
- windows[ThisSessonWinId].groups[group].active_tab = tt_ids[windows[ThisSessonWinId].groups[group].active_tab_ttid];
- }
- if (tt_ids[windows[ThisSessonWinId].groups[group].prev_active_tab_ttid] != undefined) {
- windows[ThisSessonWinId].groups[group].prev_active_tab = tt_ids[windows[ThisSessonWinId].groups[group].prev_active_tab_ttid];
- }
- }
- }
-
- if (opt.debug){
- pushlog("FirefoxLoadTabs, retry: "+retry);
- pushlog("Current windows count is: "+w.length);
- pushlog("Current tabs count is: "+tabs_count);
- pushlog("Matching tabs: "+tabs_matched);
- pushlog("Current windows:");
- pushlog(w);
- }
-
-
- // will try to find tabs for 3 times
- if (opt.skip_load == true || retry > 2 || (tabs_matched > tabs_count*0.5)) {
- running = true;
- FirefoxAutoSaveData();
- FirefoxListeners();
-
- delete schedule_update_data;
- delete schedule_rearrange_tabs;
- delete DragNodeClass;
- delete DragOverTimer;
- delete DragTreeDepth;
- delete menuItemNode;
- delete CurrentWindowId;
- delete SearchIndex;
- delete active_group;
- delete browserId;
- delete bggroups;
- delete bgfolders;
- delete caption_clear_filter;
- delete caption_loading;
- delete caption_searchbox;
- delete DefaultToolbar;
- delete DefaultTheme;
- delete DefaultPreferences;
-
- delete newTabUrl;
- delete EmptyTabs;
- } else {
- if (opt.debug){
- pushlog("Attempt "+retry+" failed, matched tabs was below 50%");
- }
- setTimeout(function() {
- FirefoxLoadTabs(retry+1);
- }, 2000);
- }
- }
- });
- }
- });
- }
- });
- });
-}
-// save every second if there is anything to save obviously
-async function FirefoxAutoSaveData() {
- setInterval(function() {
- if (schedule_save > 1) {
- schedule_save = 1;
- }
- if (running && schedule_save > 0 && Object.keys(tabs).length > 1) {
- chrome.windows.getAll({windowTypes: ['normal'], populate: true}, function(w) {
- let WinCount = w.length;
- for (let wIndex = 0; wIndex < WinCount; wIndex++) {
- let winId = w[wIndex].id;
- if (windows[winId] != undefined && windows[winId].ttid != undefined && windows[winId].group_bar != undefined && windows[winId].search_filter != undefined && windows[winId].active_shelf != undefined && windows[winId].active_group != undefined && windows[winId].groups != undefined && windows[winId].folders != undefined) {
- browser.sessions.setWindowValue(winId, "TTdata", windows[winId] );
- }
- let TabsCount = w[wIndex].tabs.length;
- for (let tabIndex = 0; tabIndex < TabsCount; tabIndex++) {
- let tabId = w[wIndex].tabs[tabIndex].id;
- if (tabs[tabId] != undefined && tabs[tabId].ttid != undefined && tabs[tabId].parent != undefined && tabs[tabId].index != undefined && tabs[tabId].expand != undefined) {
- browser.sessions.setTabValue( tabId, "TTdata", tabs[tabId] );
- }
- }
- }
- schedule_save--;
- });
- }
- if (opt.debug == true) {
- chrome.storage.local.set({debug_log: debug});
- }
- }, 1000);
-}
-function GenerateNewWindowID() {
- let newID = "w_"+GenerateRandomID();
- let newIdAvailable = true;
- for (let windowId in windows) {
- if (windows[windowId].ttid == newID) {
- newIdAvailable = false;
- }
- }
- if (newIdAvailable) {
- return newID;
- } else {
- GenerateNewWindowID();
- }
-}
-function GenerateNewTabID() {
- let newID = "t_"+GenerateRandomID();
- let newIdAvailable = true;
- // for (let tabId in tabs) {
- // if (tabs[tabId].ttid == newID) {
- // newIdAvailable = false;
- // }
- // }
- if (tt_ids[newID] != undefined) {
- newIdAvailable = false;
- }
- if (newIdAvailable) {
- return newID;
- } else {
- GenerateNewTabID();
- }
-}
-function AppendTabTTId(tabId) {
- let NewTTTabId = GenerateNewTabID();
- if (tabs[tabId] != undefined) {
- tabs[tabId].ttid = NewTTTabId;
- } else {
- tabs[tabId] = {ttid: NewTTTabId, parent: "tab_list", parent_ttid: "", index: 0, expand: ""};
- }
- tt_ids[NewTTTabId] = tabId;
- return NewTTTabId;
- // if (schedule_save > 0) browser.sessions.setTabValue( tabId, "TTdata", tabs[tabId] );
-}
-
-function AppendWinTTId(windowId) {
- let NewTTWindowId = GenerateNewWindowID();
- if (windows[windowId] != undefined) {
- windows[windowId].ttid = NewTTWindowId;
- } else {
- windows[windowId] = {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: caption_ungrouped_group, font: ""}}, folders: {}};
- }
- // if (schedule_save > 0) browser.sessions.setWindowValue( windowId, "TTdata", windows[windowId] );
-}
-function ReplaceParents(oldTabId, newTabId) {
- for (let tabId in tabs) {
- if (tabs[tabId].parent == oldTabId) {
- tabs[tabId].parent = newTabId;
- }
- }
-}
-let DETACHED_TABS___Bug1398272___WTF_ARE_YOU_DOING_MOZILLA = {}; // MOZILLA BUG 1398272
-// start all listeners
-function FirefoxListeners() {
- browser.browserAction.onClicked.addListener(function() {
- browser.sidebarAction.setPanel({panel: (browser.extension.getURL("/sidebar.html")) });
- browser.sidebarAction.open();
- });
- chrome.tabs.onCreated.addListener(function(tab) {
- let t = Promise.resolve(browser.sessions.getTabValue(tab.id, "TTdata")).then(function(TabData) {
- if (TabData != undefined) {
- tabs[tab.id] = Object.assign({}, TabData);
- let originalParent = TabData.parent_ttid == "" ? undefined : (tt_ids[TabData.parent_ttid] ? tt_ids[TabData.parent_ttid] : TabData.parent_ttid);
- chrome.runtime.sendMessage({command: "tab_created", windowId: tab.windowId, tabId: tab.id, parentTabId: originalParent, index: TabData.index});
- } else {
- AppendTabTTId(tab.id);
- chrome.runtime.sendMessage({command: "tab_created", windowId: tab.windowId, tabId: tab.id});
- }
- schedule_save++;
- });
- });
- chrome.tabs.onAttached.addListener(function(tabId, attachInfo) {
- let oldId = tabId;
- chrome.tabs.get(oldId, function(tab) {
- ReplaceParents(oldId, tab.id);
- tt_ids[tabs[oldId].ttid] = tab.id; // MOZILLA BUG 1398272
- tabs[tab.id] = tabs[oldId]; // MOZILLA BUG 1398272
- DETACHED_TABS___Bug1398272___WTF_ARE_YOU_DOING_MOZILLA[oldId] = tab.id; // MOZILLA BUG 1398272
- DETACHED_TABS___Bug1398272___WTF_ARE_YOU_DOING_MOZILLA[tab.id] = oldId; // MOZILLA BUG 1398272
- browser.sessions.setTabValue( tab.id, "TTdata", tabs[oldId] ); // MOZILLA BUG 1398272
- chrome.runtime.sendMessage({command: "tab_attached", windowId: attachInfo.newWindowId, tab: tab, tabId: tab.id, ParentId: tabs[tab.id].parent});
- schedule_save++;
- });
- });
-
- chrome.tabs.onDetached.addListener(function(tabId, detachInfo) {
- chrome.runtime.sendMessage({command: "tab_detached", windowId: detachInfo.oldWindowId, tabId: tabId});
- let detachTabId = tabId;
- if (DETACHED_TABS___Bug1398272___WTF_ARE_YOU_DOING_MOZILLA[tabId] != undefined) { // MOZILLA BUG 1398272
- detachTabId = DETACHED_TABS___Bug1398272___WTF_ARE_YOU_DOING_MOZILLA[tabId]; // MOZILLA BUG 1398272
- chrome.runtime.sendMessage({command: "tab_detached", windowId: detachInfo.oldWindowId, tabId: DETACHED_TABS___Bug1398272___WTF_ARE_YOU_DOING_MOZILLA[tabId]}); // MOZILLA BUG 1398272
- } // MOZILLA BUG 1398272
- });
-
- chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) {
- setTimeout(function() {
- if (DETACHED_TABS___Bug1398272___WTF_ARE_YOU_DOING_MOZILLA[tabId] != undefined) { // MOZILLA BUG 1398272
- chrome.runtime.sendMessage({command: "tab_removed", windowId: removeInfo.windowId, tabId: DETACHED_TABS___Bug1398272___WTF_ARE_YOU_DOING_MOZILLA[tabId]}); // MOZILLA BUG 1398272
- } // MOZILLA BUG 1398272
- chrome.runtime.sendMessage({command: "tab_removed", windowId: removeInfo.windowId, tabId: tabId});
- }, 5);
- // setTimeout(function() {
- // delete tabs[tabId];
- // },60000);
- schedule_save++;
- });
- chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
- if (changeInfo.pinned == true && tabs[tabId]) {
- tabs[tabId].parent = "pin_list";
- tabs[tabId].parent_ttid = "";
- schedule_save++;
- } else {
- AppendTabTTId(tabId);
- }
- if (changeInfo.title != undefined && !tab.active) {
- chrome.runtime.sendMessage({command: "tab_attention", windowId: tab.windowId, tabId: tabId});
- }
- chrome.runtime.sendMessage({command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tabId, changeInfo: changeInfo});
- });
- chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId) {
- chrome.tabs.get(addedTabId, function(tab) {
- if (addedTabId == removedTabId) {
- chrome.runtime.sendMessage({command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tab.id, changeInfo: {status: tab.status, url: tab.url, title: tab.title, audible: tab.audible, mutedInfo: tab.mutedInfo}});
- } else {
- if (tabs[removedTabId]) {
- tabs[addedTabId] = tabs[removedTabId];
- }
- ReplaceParents(tabId, tab.id);
- chrome.runtime.sendMessage({command: "tab_removed", windowId: tab.windowId, tabId: removedTabId});
- chrome.runtime.sendMessage({command: "tab_attached", windowId: tab.windowId, tab: tab, tabId: addedTabId, ParentId: tabs[addedTabId].parent});
- // delete ttid[tabs[removedTabId].ttid];
- // delete tabs[removedTabId];
- }
- setTimeout(function() {
- AppendTabTTId(addedTabId);
- schedule_save++;
- }, 100);
-
- });
- });
- chrome.tabs.onActivated.addListener(function(activeInfo) {
- chrome.runtime.sendMessage({command: "tab_activated", windowId: activeInfo.windowId, tabId: activeInfo.tabId});
- });
- chrome.windows.onCreated.addListener(function(window) {
- let win = Promise.resolve(browser.sessions.getWindowValue(window.id, "TTdata")).then(function(WindowData) {
- if (WindowData != undefined) {
- windows[window.id] = Object.assign({}, WindowData);
- } else {
- AppendWinTTId(window.id);
- }
- schedule_save++;
- });
- });
- chrome.windows.onRemoved.addListener(function(windowId) {
- // delete windows[windowId];
- schedule_save++;
- });
- chrome.sessions.onChanged.addListener(function(session) {
- chrome.windows.getAll({windowTypes: ['normal'], populate: false}, function(w) {
- chrome.tabs.query({}, function(t) {
- for (let wiInd = 0; wiInd < w.length; wiInd++) {
- if (windows[w[wiInd].id] == undefined) {
- chrome.runtime.sendMessage({command: "reload_sidebar"});
- window.location.reload();
- }
- }
- for (let tbInd = 0; tbInd < t.length; tbInd++) {
- if (tabs[t[tbInd].id] == undefined) {
- chrome.runtime.sendMessage({command: "reload_sidebar"});
- window.location.reload();
- }
- }
- });
- });
- });
-}
-function FirefoxMessageListeners() {
- chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
-
- if (message.command == "reload") {
- window.location.reload();
- return;
- }
- if (message.command == "get_windows") {
- sendResponse(windows);
- return;
- }
- if (message.command == "get_folders") {
- if (windows[message.windowId]) {
- sendResponse(windows[message.windowId].folders);
- }
- return;
- }
- if (message.command == "save_folders") {
- if (windows[message.windowId]) {
- windows[message.windowId].folders = Object.assign({}, message.folders);
- schedule_save++;
- }
- return;
- }
- if (message.command == "get_groups") {
- if (windows[message.windowId]) {
- sendResponse(windows[message.windowId].groups);
- }
- return;
- }
- if (message.command == "save_groups") {
- if (windows[message.windowId]) {
- windows[message.windowId].groups = Object.assign({}, message.groups);
- for (let group in windows[message.windowId].groups) {
- if (tabs[windows[message.windowId].groups[group].active_tab]) {
- windows[message.windowId].groups[group].active_tab_ttid = tabs[windows[message.windowId].groups[group].active_tab].ttid;
- }
- if (tabs[windows[message.windowId].groups[group].prev_active_tab]) {
- windows[message.windowId].groups[group].prev_active_tab_ttid = tabs[windows[message.windowId].groups[group].prev_active_tab].ttid;
- }
- }
- schedule_save++;
- }
- return;
- }
- if (message.command == "set_active_group") {
- if (windows[message.windowId]) {
- windows[message.windowId].active_group = message.active_group;
- schedule_save++;
- }
- return;
- }
- if (message.command == "get_active_group") {
- if (windows[message.windowId]) {
- sendResponse(windows[message.windowId].active_group);
- }
- return;
- }
- if (message.command == "set_search_filter") {
- if (windows[message.windowId]) {
- windows[message.windowId].search_filter = message.search_filter;
- schedule_save++;
- }
- return;
- }
- if (message.command == "get_search_filter") {
- if (windows[message.windowId]) {
- sendResponse(windows[message.windowId].search_filter);
- }
- return;
- }
- if (message.command == "set_active_shelf") {
- if (windows[message.windowId]) {
- windows[message.windowId].active_shelf = message.active_shelf;
- schedule_save++;
- }
- return;
- }
- if (message.command == "get_active_shelf") {
- if (windows[message.windowId]) {
- sendResponse(windows[message.windowId].active_shelf);
- }
- return;
- }
- if (message.command == "set_group_bar") {
- if (windows[message.windowId]) {
- windows[message.windowId].group_bar = message.group_bar;
- schedule_save++;
- }
- return;
- }
- if (message.command == "get_group_bar") {
- if (windows[message.windowId]) {
- sendResponse(windows[message.windowId].group_bar);
- }
- return;
- }
- if (message.command == "get_browser_tabs") {
- sendResponse(tabs);
- return;
- }
- if (message.command == "is_bg_ready") {
- sendResponse(running);
- return;
- }
- if (message.command == "update_tab") {
- if (tabs[message.tabId]) {
- if (message.tab.index) {
- tabs[message.tabId].index = message.tab.index;
- }
- if (message.tab.expand) {
- tabs[message.tabId].expand = message.tab.expand;
- }
- if (message.tab.parent) {
- tabs[message.tabId].parent = message.tab.parent;
- if (tabs[message.tab.parent]) {
- tabs[message.tabId].parent_ttid = tabs[message.tab.parent].ttid;
- } else {
- tabs[message.tabId].parent_ttid = "";
- }
- }
- schedule_save++;
- }
- return;
- }
- if (message.command == "update_all_tabs") {
- for (let i = 0; i < message.pins.length; i++) {
- if (tabs[message.pins[i].id]) {
- tabs[message.pins[i].id].parent = "pin_list";
- tabs[message.pins[i].id].parent_ttid = "";
- tabs[message.pins[i].id].expand = "";
- tabs[message.pins[i].id].index = message.pins[i].index;
- }
- }
- for (let j = 0; j < message.tabs.length; j++) {
- if (tabs[message.tabs[j].id]) {
- tabs[message.tabs[j].id].parent = message.tabs[j].parent;
- tabs[message.tabs[j].id].expand = message.tabs[j].expand;
- tabs[message.tabs[j].id].index = message.tabs[j].index;
- if (tabs[message.tabs[j].parent]) {
- tabs[message.tabs[j].id].parent_ttid = tabs[message.tabs[j].parent].ttid;
- } else {
- tabs[message.tabs[j].id].parent_ttid = "";
- }
- }
- }
- schedule_save++;
- return;
- }
- if (message.command == "debug") {
- pushlog(message.log);
- return;
- }
- });
-}
\ No newline at end of file
diff --git a/init.js b/init.js
deleted file mode 100644
index af2398d..0000000
--- a/init.js
+++ /dev/null
@@ -1,16 +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/
-
-document.addEventListener("DOMContentLoaded", Init(), false);
-
-function Init() {
- if (browserId == "F") {
- FirefoxMessageListeners();
- FirefoxStart(0);
- } else {
- // ConvertLegacyStorage();
- ChromeMessageListeners();
- ChromeLoadTabs(0);
- }
-}
diff --git a/legacy.js b/legacy.js
deleted file mode 100644
index 93a1aed..0000000
--- a/legacy.js
+++ /dev/null
@@ -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;
- }
-}
diff --git a/listeners_bg.js b/listeners_bg.js
new file mode 100644
index 0000000..840e57f
--- /dev/null
+++ b/listeners_bg.js
@@ -0,0 +1,703 @@
+// 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/
+
+function StartBackgroundListeners() {
+ chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
+ if (message.command == "reload") {
+ window.location.reload();
+ return;
+ }
+ if (message.command == "reload_options") {
+ opt = Object.assign({}, message.opt);
+ return;
+ }
+ if (message.command == "get_windows") {
+ sendResponse(b.windows);
+ return;
+ }
+ if (message.command == "get_folders") {
+ if (b.windows[message.windowId]) {
+ sendResponse(b.windows[message.windowId].folders);
+ }
+ return;
+ }
+ if (message.command == "save_folders") {
+ if (b.windows[message.windowId]) {
+ b.windows[message.windowId].folders = Object.assign({}, message.folders);
+ b.schedule_save++;
+ }
+ return;
+ }
+ if (message.command == "get_groups") {
+ if (b.windows[message.windowId]) {
+ sendResponse(b.windows[message.windowId].groups);
+ }
+ return;
+ }
+ if (message.command == "save_groups" && browserId == "F") {
+ if (b.windows[message.windowId]) {
+ b.windows[message.windowId].groups = Object.assign({}, message.groups);
+ for (let group in b.windows[message.windowId].groups) {
+ if (b.tabs[b.windows[message.windowId].groups[group].active_tab]) {
+ b.windows[message.windowId].groups[group].active_tab_ttid = b.tabs[b.windows[message.windowId].groups[group].active_tab].ttid;
+ }
+ if (b.tabs[b.windows[message.windowId].groups[group].prev_active_tab]) {
+ b.windows[message.windowId].groups[group].prev_active_tab_ttid = b.tabs[b.windows[message.windowId].groups[group].prev_active_tab].ttid;
+ }
+ }
+ b.schedule_save++;
+ }
+ return;
+ }
+ if (message.command == "save_groups" && browserId != "F") {
+ if (b.windows[message.windowId]) {
+ b.windows[message.windowId].groups = Object.assign({}, message.groups);
+ b.schedule_save++;
+ }
+ return;
+ }
+ if (message.command == "set_active_group") {
+ if (b.windows[message.windowId]) {
+ b.windows[message.windowId].active_group = message.active_group;
+ b.schedule_save++;
+ }
+ return;
+ }
+ if (message.command == "get_active_group") {
+ if (b.windows[message.windowId]) {
+ sendResponse(b.windows[message.windowId].active_group);
+ }
+ return;
+ }
+ if (message.command == "set_search_filter") {
+ if (b.windows[message.windowId]) {
+ b.windows[message.windowId].search_filter = message.search_filter;
+ b.schedule_save++;
+ }
+ return;
+ }
+ if (message.command == "get_search_filter") {
+ if (b.windows[message.windowId]) {
+ sendResponse(b.windows[message.windowId].search_filter);
+ }
+ return;
+ }
+ if (message.command == "set_active_shelf") {
+ if (b.windows[message.windowId]) {
+ b.windows[message.windowId].active_shelf = message.active_shelf;
+ b.schedule_save++;
+ }
+ return;
+ }
+ if (message.command == "get_active_shelf") {
+ if (b.windows[message.windowId]) {
+ sendResponse(b.windows[message.windowId].active_shelf);
+ }
+ return;
+ }
+ if (message.command == "set_group_bar") {
+ if (b.windows[message.windowId]) {
+ b.windows[message.windowId].group_bar = message.group_bar;
+ b.schedule_save++;
+ }
+ return;
+ }
+ if (message.command == "get_group_bar") {
+ if (b.windows[message.windowId]) {
+ sendResponse(b.windows[message.windowId].group_bar);
+ }
+ return;
+ }
+ if (message.command == "get_browser_tabs") {
+ sendResponse(b.tabs);
+ return;
+ }
+ if (message.command == "is_bg_ready") {
+ sendResponse(b.running);
+ return;
+ }
+ if (message.command == "update_tab" && browserId == "F") {
+ if (b.tabs[message.tabId]) {
+ if (message.tab.index) {
+ b.tabs[message.tabId].index = message.tab.index;
+ }
+ if (message.tab.expand) {
+ b.tabs[message.tabId].expand = message.tab.expand;
+ }
+ if (message.tab.parent) {
+ b.tabs[message.tabId].parent = message.tab.parent;
+ if (b.tabs[message.tab.parent]) {
+ b.tabs[message.tabId].parent_ttid = b.tabs[message.tab.parent].ttid;
+ } else {
+ b.tabs[message.tabId].parent_ttid = "";
+ }
+ }
+ b.schedule_save++;
+ } else {
+ b.tabs[tabId] = {ttid: "", parent: message.tab.parent, parent_ttid: "", index: message.tab.index, expand: message.tab.expand};
+ b.schedule_save++;
+ }
+ return;
+ }
+ if (message.command == "update_tab" && browserId != "F") {
+ if (b.tabs[message.tabId]) {
+ if (message.tab.index) {
+ b.tabs[message.tabId].index = message.tab.index;
+ }
+ if (message.tab.expand) {
+ b.tabs[message.tabId].expand = message.tab.expand;
+ }
+ if (message.tab.parent) {
+ b.tabs[message.tabId].parent = message.tab.parent;
+ }
+ b.schedule_save++;
+ } else {
+ b.tabs[tabId] = {hash: 0, parent: message.tab.parent, index: message.tab.index, expand: message.tab.expand};
+ b.schedule_save++;
+ }
+ return;
+ }
+ if (message.command == "update_all_tabs" && browserId == "F") {
+ for (let i = 0; i < message.pins.length; i++) {
+ if (b.tabs[message.pins[i].id]) {
+ b.tabs[message.pins[i].id].parent = "pin_list";
+ b.tabs[message.pins[i].id].parent_ttid = "";
+ b.tabs[message.pins[i].id].expand = "";
+ b.tabs[message.pins[i].id].index = message.pins[i].index;
+ }
+ }
+ for (let j = 0; j < message.tabs.length; j++) {
+ if (b.tabs[message.tabs[j].id]) {
+ b.tabs[message.tabs[j].id].parent = message.tabs[j].parent;
+ b.tabs[message.tabs[j].id].expand = message.tabs[j].expand;
+ b.tabs[message.tabs[j].id].index = message.tabs[j].index;
+ if (b.tabs[message.tabs[j].parent]) {
+ b.tabs[message.tabs[j].id].parent_ttid = b.tabs[message.tabs[j].parent].ttid;
+ } else {
+ b.tabs[message.tabs[j].id].parent_ttid = "";
+ }
+ }
+ }
+ b.schedule_save++;
+ return;
+ }
+ if (message.command == "update_all_tabs" && browserId != "F") {
+ for (let i = 0; i < message.pins.length; i++) {
+ if (b.tabs[message.pins[i].id]) {
+ b.tabs[message.pins[i].id].parent = "pin_list";
+ b.tabs[message.pins[i].id].expand = "";
+ b.tabs[message.pins[i].id].index = message.pins[i].index;
+ }
+ }
+ for (let j = 0; j < message.tabs.length; j++) {
+ if (b.tabs[message.tabs[j].id]) {
+ b.tabs[message.tabs[j].id].parent = message.tabs[j].parent;
+ b.tabs[message.tabs[j].id].expand = message.tabs[j].expand;
+ b.tabs[message.tabs[j].id].index = message.tabs[j].index;
+ }
+ }
+ b.schedule_save++;
+ return;
+ }
+ if (message.command == "discard_tab") {
+ DiscardTab(message.tabId);
+ return;
+ }
+ if (message.command == "discard_window") {
+ DiscardWindow(message.windowId);
+ return;
+ }
+ if (message.command == "remove_tab_from_empty_tabs") {
+ setTimeout(function() {
+ if (b.EmptyTabs.indexOf(message.tabId) != -1) {
+ b.EmptyTabs.splice(b.EmptyTabs.indexOf(message.tabId), 1);
+ }
+ }, 100);
+ return;
+ }
+ if (message.command == "debug") {
+ pushlog(message.log);
+ return;
+ }
+ });
+}
+
+function QuantumStartListeners() {
+ browser.browserAction.onClicked.addListener(function() {
+ browser.sidebarAction.setPanel({panel: (browser.extension.getURL("/sidebar.html")) });
+ browser.sidebarAction.open();
+ });
+ chrome.tabs.onCreated.addListener(function(tab) {
+ let t = Promise.resolve(browser.sessions.getTabValue(tab.id, "TTdata")).then(function(TabData) {
+ if (TabData != undefined) {
+ b.tabs[tab.id] = Object.assign({}, TabData);
+ let originalParent = TabData.parent_ttid == "" ? undefined : (b.tt_ids[TabData.parent_ttid] ? b.tt_ids[TabData.parent_ttid] : TabData.parent_ttid);
+ 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);
+ }
+ });
+ });
+ chrome.tabs.onAttached.addListener(function(tabId, attachInfo) {
+ let oldId = tabId;
+ chrome.tabs.get(oldId, function(tab) {
+ ReplaceParents(oldId, tab.id);
+ chrome.runtime.sendMessage({command: "tab_attached", windowId: attachInfo.newWindowId, tab: tab, tabId: tab.id, ParentId: b.tabs[tab.id].parent});
+ b.schedule_save++;
+ });
+ });
+
+ chrome.tabs.onDetached.addListener(function(tabId, detachInfo) {
+ chrome.runtime.sendMessage({command: "tab_detached", windowId: detachInfo.oldWindowId, tabId: tabId});
+ });
+
+ chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) {
+ if (b.EmptyTabs.indexOf(tabId) != -1) {
+ b.EmptyTabs.splice(b.EmptyTabs.indexOf(tabId), 1);
+ }
+ setTimeout(function() {
+ chrome.runtime.sendMessage({command: "tab_removed", windowId: removeInfo.windowId, tabId: tabId});
+ }, 5);
+ // setTimeout(function() {
+ // delete b.tabs[tabId];
+ // },60000);
+ b.schedule_save++;
+ });
+ chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
+ if (changeInfo.pinned == true) {
+ if (b.tabs[tabId]) {
+ b.tabs[tabId].parent = "pin_list";
+ b.tabs[tabId].parent_ttid = "";
+ b.schedule_save++;
+ }
+ }
+ if (changeInfo.pinned == false) {
+ if (b.tabs[tabId]) {
+ b.tabs[tabId].parent = "tab_list";
+ b.tabs[tabId].parent_ttid = "";
+ b.schedule_save++;
+ }
+ }
+ if (changeInfo.url != undefined) { // if set to append when url changes and matches pre-set group
+ if (opt.move_tabs_on_url_change == "always" || ((opt.move_tabs_on_url_change == "from_empty" || opt.move_tabs_on_url_change == "from_empty_b") && b.EmptyTabs.indexOf(tabId) != -1)) {
+ AppendTabToGroupOnRegexMatch(tabId, tab.windowId, changeInfo.url);
+ }
+ if (changeInfo.url != b.newTabUrl && b.EmptyTabs.indexOf(tabId) != -1) {
+ b.EmptyTabs.splice(b.EmptyTabs.indexOf(tabId), 1);
+ }
+ }
+ if (changeInfo.title != undefined && !tab.active) {
+ chrome.runtime.sendMessage({command: "tab_attention", windowId: tab.windowId, tabId: tabId});
+ }
+ chrome.runtime.sendMessage({command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tabId, changeInfo: changeInfo});
+ });
+
+ chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId) {
+ chrome.tabs.get(addedTabId, function(tab) {
+ if (addedTabId == removedTabId) {
+ chrome.runtime.sendMessage({command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tab.id, changeInfo: {status: tab.status, url: tab.url, title: tab.title, audible: tab.audible, mutedInfo: tab.mutedInfo}});
+ } else {
+ if (b.tabs[removedTabId]) {
+ b.tabs[addedTabId] = b.tabs[removedTabId];
+ }
+ ReplaceParents(tabId, tab.id);
+ chrome.runtime.sendMessage({command: "tab_removed", windowId: tab.windowId, tabId: removedTabId});
+ chrome.runtime.sendMessage({command: "tab_attached", windowId: tab.windowId, tab: tab, tabId: addedTabId, ParentId: b.tabs[addedTabId].parent});
+ // delete ttid[b.tabs[removedTabId].ttid];
+ // delete b.tabs[removedTabId];
+ }
+ setTimeout(function() {
+ QuantumAppendTabTTId(tab);
+ b.schedule_save++;
+ }, 100);
+
+ });
+ });
+ 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;
+ }
+ }
+ chrome.runtime.sendMessage({command: "tab_activated", windowId: activeInfo.windowId, tabId: activeInfo.tabId});
+ b.schedule_save++;
+ });
+ chrome.windows.onCreated.addListener(function(window) {
+ let win = Promise.resolve(browser.sessions.getWindowValue(window.id, "TTdata")).then(function(WindowData) {
+ if (WindowData != undefined) {
+ b.windows[window.id] = Object.assign({}, WindowData);
+ } else {
+ QuantumAppendWinTTId(window.id);
+ }
+ b.schedule_save++;
+ });
+ });
+ chrome.windows.onRemoved.addListener(function(windowId) {
+ // delete b.windows[windowId];
+ b.schedule_save++;
+ });
+ // chrome.sessions.onChanged.addListener(function(session) {
+ // chrome.windows.getAll({windowTypes: ['normal'], populate: false}, function(w) {
+ // chrome.tabs.query({}, function(t) {
+ // for (let wiInd = 0; wiInd < w.length; wiInd++) {
+ // if (b.windows[w[wiInd].id] == undefined) {
+ // chrome.runtime.sendMessage({command: "reload_sidebar"});
+ // window.location.reload();
+ // }
+ // }
+ // for (let tbInd = 0; tbInd < t.length; tbInd++) {
+ // if (b.tabs[t[tbInd].id] == undefined) {
+ // chrome.runtime.sendMessage({command: "reload_sidebar"});
+ // window.location.reload();
+ // }
+ // }
+ // });
+ // });
+ // });
+}
+
+
+function ChromiumStartListeners() { // start all listeners
+ chrome.tabs.onCreated.addListener(function(tab) {
+ ChromiumHashURL(tab);
+ OnMessageTabCreated(tab.id);
+ });
+ chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) {
+ if (b.EmptyTabs.indexOf(tabId) != -1) {
+ b.EmptyTabs.splice(b.EmptyTabs.indexOf(tabId), 1);
+ }
+ setTimeout(function() { chrome.runtime.sendMessage({command: "tab_removed", windowId: removeInfo.windowId, tabId: tabId}); },5);
+ delete b.tabs[tabId];
+ b.schedule_save++;
+ });
+ chrome.tabs.onAttached.addListener(function(tabId, attachInfo) {
+ chrome.tabs.get(tabId, function(tab) {
+ chrome.runtime.sendMessage({command: "tab_attached", windowId: attachInfo.newWindowId, tab: tab, tabId: tabId, ParentId: b.tabs[tabId].parent});
+ });
+ b.schedule_save++;
+ });
+ chrome.tabs.onDetached.addListener(function(tabId, detachInfo) {
+ chrome.runtime.sendMessage({command: "tab_detached", windowId: detachInfo.oldWindowId, tabId: tabId});
+ b.schedule_save++;
+ });
+ chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
+ if (b.tabs[tabId] == undefined || changeInfo.url != undefined) {
+ ChromiumHashURL(tab);
+ }
+ if (changeInfo.pinned != undefined) {
+ if (changeInfo.pinned == true) {
+ b.tabs[tabId].parent = "pin_list";
+ }
+ if (changeInfo.pinned == false) {
+ b.tabs[tabId].parent = "tab_list";
+ }
+ b.schedule_save++;
+ }
+ if (changeInfo.url != undefined) { // if set to append when url changes and matches pre-set group
+ if (opt.move_tabs_on_url_change == "always" || ((opt.move_tabs_on_url_change == "from_empty" || opt.move_tabs_on_url_change == "from_empty_b") && b.EmptyTabs.indexOf(tabId) != -1)) {
+ AppendTabToGroupOnRegexMatch(tabId, tab.windowId, changeInfo.url);
+ }
+ if (changeInfo.url != b.newTabUrl && b.EmptyTabs.indexOf(tabId) != -1) {
+ b.EmptyTabs.splice(b.EmptyTabs.indexOf(tabId), 1);
+ }
+ }
+ if (changeInfo.title != undefined && !tab.active) {
+ chrome.runtime.sendMessage({command: "tab_attention", windowId: tab.windowId, tabId: tabId});
+ }
+ chrome.runtime.sendMessage({command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tabId, changeInfo: changeInfo});
+ });
+ chrome.tabs.onMoved.addListener(function(tabId, moveInfo) {
+ b.schedule_save++;
+ });
+ chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId) {
+ chrome.tabs.get(addedTabId, function(tab) {
+ if (addedTabId == removedTabId) {
+ chrome.runtime.sendMessage({command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tab.id, changeInfo: {status: tab.status, url: tab.url, title: tab.title, audible: tab.audible, mutedInfo: tab.mutedInfo}});
+ } else {
+ ReplaceParents(tabId, tab.id);
+ if (b.tabs[removedTabId]) {
+ b.tabs[addedTabId] = b.tabs[removedTabId];
+ } else {
+ ChromiumHashURL(tab);
+ }
+ chrome.runtime.sendMessage({command: "tab_removed", windowId: tab.windowId, tabId: removedTabId});
+ chrome.runtime.sendMessage({command: "tab_attached", windowId: tab.windowId, tab: tab, tabId: addedTabId});
+ delete b.tabs[removedTabId];
+ }
+ b.schedule_save++;
+ });
+ });
+ 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;
+ }
+ }
+ chrome.runtime.sendMessage({command: "tab_activated", windowId: activeInfo.windowId, tabId: activeInfo.tabId});
+ b.schedule_save++;
+ });
+ chrome.windows.onCreated.addListener(function(window) {
+ ChromiumAddWindowData(window.id);
+ // b.windows[window.id] = {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.schedule_save++;
+ });
+ chrome.windows.onRemoved.addListener(function(windowId) {
+ delete b.windows[windowId];
+ b.schedule_save++;
+ });
+ chrome.runtime.onSuspend.addListener(function() {
+ b.running = false;
+ });
+}
+
+
+
+
+function OnMessageTabCreated(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;
+ let AfterId;
+ let append;
+
+ if (b.windows[NewTab.windowId] && NewTab.active) {
+ b.windows[NewTab.windowId].groups[b.windows[NewTab.windowId].active_group].active_tab = NewTab.id;
+ }
+
+ if (NewTab.url == b.newTabUrl) {
+ 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;
+ }
+
+ } 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];
+ }
+
+ if (NewTab.openerTabId) { // child case
+
+ let OpenerSiblings = GetChildren(b.tabs[NewTab.openerTabId].parent);
+
+ if (opt.append_child_tab == "after") { // place tabs flat
+ b.tabs[NewTab.id].parent = b.tabs[NewTab.openerTabId].parent;
+ 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;
+ }
+ AfterId = NewTab.openerTabId;
+
+ } else {
+
+ if (opt.max_tree_depth == 0) { // place tabs flat if limit is set to 0
+
+ b.tabs[NewTab.id].parent = b.tabs[NewTab.openerTabId].parent;
+ if (browserId == "F"){
+ b.tabs[NewTab.id].parent_ttid = b.tabs[NewTab.openerTabId].parent_ttid;
+ }
+
+ 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;
+ }
+ 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;
+ }
+ ParentId = b.tabs[NewTab.id].parent;
+ }
+
+ if (opt.append_child_tab_after_limit == "bottom" && opt.append_child_tab != "after") { // max tree depth, place tab on bottom (below parent)
+ if (OpenerSiblings.length > 0) {
+ b.tabs[NewTab.id].index = b.tabs[OpenerSiblings[OpenerSiblings.length-1]].index+1;
+ } else {
+ b.tabs[NewTab.id].index = 1;
+ }
+ ParentId = b.tabs[NewTab.id].parent;
+ append = true;
+ }
+
+ } else {
+
+ let Parents = GetTabParents(NewTab.openerTabId);
+ let OpenerChildren = GetChildren(NewTab.openerTabId);
+
+ if (opt.max_tree_depth < 0 || (opt.max_tree_depth > 0 && Parents.length < opt.max_tree_depth)) { // append to tree on top and bottom
+
+ b.tabs[NewTab.id].parent = NewTab.openerTabId;
+ if (browserId == "F"){
+ b.tabs[NewTab.id].parent_ttid = b.tabs[NewTab.openerTabId].ttid;
+ }
+
+ 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;
+ }
+ ParentId = b.tabs[NewTab.id].parent;
+ }
+
+ if (opt.append_child_tab == "bottom") { // place child tab at the bottom
+ if (OpenerChildren.length > 0) {
+ b.tabs[NewTab.id].index = b.tabs[OpenerChildren[OpenerChildren.length-1]].index+1;
+ } else {
+ b.tabs[NewTab.id].index = 0;
+ }
+ ParentId = b.tabs[NewTab.id].parent;
+ append = true;
+ }
+
+ } else {
+
+ if (opt.max_tree_depth > 0 && Parents.length >= opt.max_tree_depth) { // if reached depth limit of the tree
+
+ b.tabs[NewTab.id].parent = b.tabs[NewTab.openerTabId].parent;
+ if (browserId == "F"){
+ b.tabs[NewTab.id].parent_ttid = b.tabs[NewTab.openerTabId].parent_ttid;
+ }
+
+ 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;
+ }
+ 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;
+ }
+ ParentId = b.tabs[NewTab.id].parent;
+ }
+
+ if (opt.append_child_tab_after_limit == "bottom") { // tab will append on bottom
+ if (OpenerSiblings.length > 0) {
+ b.tabs[NewTab.id].index = b.tabs[OpenerSiblings[OpenerSiblings.length-1]].index+1;
+ } else {
+ b.tabs[NewTab.id].index = 1;
+ }
+ ParentId = b.tabs[NewTab.id].parent;
+ append = true;
+ }
+
+ }
+ }
+ }
+ }
+ } else { // orphan tab
+
+ if (opt.orphaned_tabs_to_ungrouped == true) { // if set to append orphan tabs to ungrouped group
+ let TabListTabs = GetChildren("tab_list");
+ 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") {
+
+ 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 );
+ }
+ 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;
+ if (browserId == "F"){
+ b.tabs[NewTab.id].parent_ttid = "";
+ }
+ if (GroupTabs.length > 0) {
+ b.tabs[NewTab.id].index = b.tabs[GroupTabs[GroupTabs.length-1]].index+1;
+ } else {
+ b.tabs[NewTab.id].index = 0;
+ }
+ ParentId = b.windows[NewTab.windowId].active_group;
+ }
+ // console.log(b.tabs[NewTab.id].index);
+ }
+
+ if (opt.append_orphan_tab == "top") {
+ let GroupTabs = GetChildren(b.windows[NewTab.windowId].active_group);
+ b.tabs[NewTab.id].parent = b.windows[NewTab.windowId].active_group;
+ 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;
+ }
+ ParentId = b.windows[NewTab.windowId].active_group;
+ }
+
+ if (opt.append_orphan_tab == "bottom") {
+ let GroupTabs = GetChildren(b.windows[NewTab.windowId].active_group);
+ b.tabs[NewTab.id].parent = b.windows[NewTab.windowId].active_group;
+ if (browserId == "F"){
+ b.tabs[NewTab.id].parent_ttid = "";
+ }
+ if (GroupTabs.length > 0) {
+ b.tabs[NewTab.id].index = b.tabs[GroupTabs[GroupTabs.length-1]].index+1;
+ } else {
+ b.tabs[NewTab.id].index = 0;
+ }
+ ParentId = b.windows[NewTab.windowId].active_group;
+ append = true;
+ }
+
+ }
+
+ }
+
+ if (opt.move_tabs_on_url_change === "all_new") {
+ setTimeout(function() {
+ chrome.tabs.get(NewTab.id, function(CheckTabsUrl) {
+ AppendTabToGroupOnRegexMatch(CheckTabsUrl.id, CheckTabsUrl.windowId, CheckTabsUrl.url);
+ });
+ }, 100);
+ }
+ }
+ 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});
+ });
+}
\ No newline at end of file
diff --git a/manifest.json b/manifest.json
index 76dcbba..661cf39 100644
--- a/manifest.json
+++ b/manifest.json
@@ -2,7 +2,7 @@
"manifest_version": 2,
"default_locale": "en",
"background": {
- "page": "background.html",
+ "scripts": [ "listeners_bg.js", "scripts/common.js", "background.js" ],
"persistent": true
},
"name": "Tree Tabs",
@@ -14,8 +14,7 @@
"19": "icons/16.png",
"16": "icons/16.png"
},
- "permissions": [ "tabs", "sessions", "", "storage", "unlimitedStorage", "bookmarks", "tabHide" ],
-
+ "permissions": [ "tabs", "sessions", "storage", "unlimitedStorage", "bookmarks", "tabHide" ],
"sidebar_action": {
"default_icon": {
"16": "icons/16.png",
@@ -29,6 +28,16 @@
"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",
@@ -39,5 +48,5 @@
"page": "options.html",
"open_in_tab": true
},
- "version": "100"
+ "version": "1.7.0"
}
\ No newline at end of file
diff --git a/options.html b/options.html
index 0352545..5eee67b 100644
--- a/options.html
+++ b/options.html
@@ -3,41 +3,41 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
-
-
+
+
-
+
-
+
-
+