Create tabs and stuff with javascript for more readability. 'unregisterVideo' doesn't get fired, so manual cleanup of the videoTab object was implemented in background script

This commit is contained in:
Tamius Han 2018-11-11 22:35:08 +01:00
parent ccafcd5285
commit 3f14785c29
7 changed files with 226 additions and 125 deletions

View File

@ -23,6 +23,12 @@ class BaseUi {
show() {
this.element.classList.remove('hidden');
}
select() {
this.element.classList.add('selected');
}
unselect() {
this.element.classList.remove('selected');
}
appendTo(element) {
element.appendChild(this.element);
}

View File

@ -7,24 +7,56 @@ class MenuItem extends BaseUi {
additionalClasses
);
this.element.classList.add('menu-item');
this.element.subitemList = document.createElement('div');
this.subitemListElement = document.createElement('div');
this.element.appendChild(this.subitemListElement);
this.subitemList = [];
}
insertSubitem(subitemElement) {
this.element.subitemList.appendChild(subitemElement);
insertSubitem(subitem) {
this.subitemList.push(subitem);
this.subitemListElement.appendChild(subitem.element);
}
removeSubitems() {
while (this.element.subitemList.firstChild) {
this.element.subitemList.removeChild(this.element.subitemList.firstChild);
while (this.subitemListElement.lastChild) {
this.subitemListElement.removeChild(this.subitemListElement.lastChild);
}
this.subitemList = [];
}
selectSubitem(subitemName) {
for(let item of this.subitemList) {
if (item.name === subitemName) {
item.select();
} else {
item.unselect();
}
}
}
selectFirstSubitem() {
for(let item of this.subitemList) {
item.unselect();
}
this.subitemList[0].select();
}
showSubitems() {
this.element.subitemList.classList.remove('hidden');
this.subitemListElement.classList.remove('hidden');
}
hideSubitems() {
this.element.subitemList.classList.add('hidden');
this.subitemListElement.classList.add('hidden');
}
select() {
super.select();
this.showSubitems();
}
unselect() {
super.unselect();
this.hideSubitems();
}
}

View File

@ -1,14 +1,20 @@
class TabItem {
static create(id, text, isIframe, onClick) {
var tabitem = document.createElement('div');
tabitem.classList.add('tabitem');
if (isIframe) {
tabitem.classList.add('tabitem-iframe');
}
tabitem.setAttribute('id', id);
tabitem.textContent = text;
tabitem.addEventListener('click', onClick);
class TabItem extends BaseUi {
return tabitem;
constructor (id, name, label, isIframe, onClick, additionalClasses) {
super(id, label, onClick, additionalClasses);
this.element.classList.add('tabitem');
if (isIframe) {
this.element.classList.add('tabitem-iframe');
}
this.name = name;
}
select() {
super.select();
this.element.classList.add('tabitem-selected');
}
unselect() {
super.unselect();
this.element.classList.remove('tabitem-selected');
}
}

View File

@ -15,6 +15,7 @@ class UWServer {
this.videoTabs = {};
this.currentTabId = 0;
this._gctimeout = undefined;
}
async setup() {
@ -29,6 +30,9 @@ class UWServer {
} else if (BrowserDetect.chrome) {
chrome.tabs.onActivated.addListener(function(m) {ths.onTabSwitched(m)});
}
console.log("will schedule gcframe")
this.scheduleGc();
}
async _promisifyTabsGet(browserObj, tabId){
@ -37,6 +41,25 @@ class UWServer {
});
}
scheduleGc(timeout) {
console.log("scheduling gcframe")
if (this._gctimeout) {
return;
}
if (!timeout) {
timeout = 0;
}
const ths = this;
setTimeout( () => {
clearTimeout(ths._gctimeout);
ths.gcFrames();
ths._gctimeoutgcTimeout = ths.scheduleGc(5000);
}, timeout);
}
extractHostname(url){
var hostname;
@ -81,6 +104,25 @@ class UWServer {
//TODO: change extension icon based on whether there's any videos on current page
}
async gcFrames() {
// does "garbage collection" on frames
let frames;
if (BrowserDetect.firefox) {
frames = await browser.webNavigation.getAllFrames({tabId: this.currentTabId});
} else if (BrowserDetect.chrome) {
frames = await new Promise( (resolve, reject) => {
chrome.webNavigation.getAllFrames({tabId: this.currentTabId}, (data) => resolve(data) );
});
}
for (let key in this.videoTabs[this.currentTabId].frames) {
if (! frames.find(x => x.frameId == key)) {
delete this.videoTabs[this.currentTabId].frames[key];
}
}
}
registerVideo(sender) {
if (Debug.debug && Debug.comms) {
console.log("[UWServer::registerVideo] registering video.\nsender:", sender);

View File

@ -75,3 +75,8 @@ html, body {
content: "⦿";
padding-right: 0.5em;
}
.tabitem-iframe::after {
content: "</>";
padding-left: 0.33em;
}

View File

@ -5,6 +5,11 @@ document.getElementById("uw-version").textContent = browser.runtime.getManifest(
var selectedMenu = "";
var selectedSubitem = {
'siteSettings': undefined,
'videoSettings': undefined,
}
var hasVideos = false;
var zoom_videoScale = 1;
@ -22,6 +27,58 @@ port.onMessage.addListener( (m,p) => processReceivedMessage(m,p));
var _video_settings_tab_items = [];
//#region build ui
var tablist = {
'extensionSettings': new MenuItem('_menu_item_settings_ext', 'Extension settings', '', () => showMenu('extensionSettings')),
'siteSettings': new MenuItem('_menu_item_settings_site', 'Site settings', 'Settings for current site', () => showMenu('siteSettings')),
'videoSettings': new MenuItem('_menu_item_settings_video', 'Video settings', 'Crop & stretch options for videos on current page', () => showMenu('videoSettings')),
'about': new MenuItem('_menu_item_about', 'About Ultrawidify', '', () => showMenu('about'))
};
for (let t in tablist) {
tablist[t].appendTo(document.getElementById('tablist'));
}
function loadFrames(videoTab) {
tablist['siteSettings'].removeSubitems();
tablist['videoSettings'].removeSubitems();
for (var frame in videoTab.frames) {
const nid = `_vsi_${videoTab.id}-${videoTab.frames[frame].id}`;
var newItem = new TabItem(
undefined,
nid,
videoTab.frames[frame].host,
videoTab.frames[frame].url != videoTab.url,
(click) => {
tablist[selectedMenu].selectSubitem(nid);
selectedSubitem[selectedMenu] = nid;
// todo: set selected subitem
}
)
tablist['siteSettings'].insertSubitem(newItem);
tablist['videoSettings'].insertSubitem(newItem);
}
if (! selectedSubitem.siteSettings) {
tablist['siteSettings'].selectFirstSubitem();
} else {
tablist['siteSettings'].selectSubitem(selectedSubitem.siteSettings)
}
if (! selectedSubitem.videoSettings) {
tablist['videoSettings'].selectFirstSubitem();
} else {
tablist['videoSettings'].selectSubitem(selectedSubitem.videoSettings);
}
}
//#endregion
async function processReceivedMessage(message, port){
if (Debug.debug) {
console.log("[popup.js] received message", message)
@ -68,7 +125,7 @@ async function setCurrentZoom(scale) {
}
function hideWarning(warn){
document.getElementById(warn).classList.add("hidden");
// document.getElementById(warn).classList.add("hidden");
}
function stringToKeyCombo(key_in){
@ -90,59 +147,30 @@ function stringToKeyCombo(key_in){
}
function configurePopupTabs(site) {
// todo: this can potentially be removed
// Determine which tabs can we touch.
// If extension is disabled, we can't touch 'site settings' and 'video settings'
// If extension is enabled, but site is disabled, we can't touch 'video settings'
var extensionEnabled = settings.extensionEnabled();
var extensionEnabledForSite = settings.extensionEnabledForSite(site);
MenuTab.siteSettings.classList.add('disabled');
if (extensionEnabledForSite) {
MenuTab.videoSettings.classList.remove('disabled');
}
if (extensionEnabled) {
MenuTab.videoSettings.classList.remove('disabled');
}
// we assume that these two can be shown. If extension or site are disabled, we'll
// add 'disabled' class later down the line:
document.getElementById("_site_only_when_site_enabled").classList.remove("disabled");
document.getElementById("_ext_only_when_ext_enabled").classList.remove("disabled");
if (! extensionEnabledForSite) {
MenuTab.videoSettings.classList.add('disabled');
// also disable extra settings for site
document.getElementById("_site_only_when_site_enabled").classList.add("disabled");
if (! extensionEnabled) {
MenuTab.siteSettings.classList.add('disabled');
// also disable extra settings for extension
document.getElementById("_ext_only_when_ext_enabled").classList.add("disabled");
if (!selectedMenu) {
openMenu('extensionSettings');
}
} else {
MenuTab.siteSettings.classList.remove('disabled');
if (!selectedMenu) {
openMenu('siteSettings');
}
}
if (extensionEnabledForSite || extensionEnabled) {
tablist['videoSettings'].enable();
} else {
MenuTab.videoSettings.classList.remove('disabled');
MenuTab.siteSettings.classList.remove('disabled');
tablist['videoSettings'].disable();
}
// if popup isn't being opened for the first time, there's no reason to switch
// we're already in this tab
if (!selectedMenu) {
openMenu('videoSettings');
}
// if popup isn't being opened for the first time, there's no reason to switch
// we're already in this tab
if (!selectedMenu) {
showMenu('videoSettings');
}
}
function configureGlobalTab() {
return; // todo: revisit
if (Debug.debug) {
console.log("[popup.js] Configuring global tab (ExtPanel).",
"\nextension mode: ", settings.active.extensionMode,
@ -173,6 +201,7 @@ function configureGlobalTab() {
}
function configureSitesTab(site) {
return; // todo: revisit
if (Debug.debug) {
console.log("[popup.js] Configuring sites tab (SitePanel).",
"\nsite: ", site,
@ -307,9 +336,6 @@ async function loadConfig(site){
console.log("\n\n-------------------------------------\n[popup.js::loadConfig] loading config. conf object:", settings.active);
}
document.getElementById("_menu_tab_settings_site_site_label").textContent = site;
configurePopupTabs(site);
configureGlobalTab();
configureSitesTab(site);
@ -335,35 +361,18 @@ function unselect(itemArray, extraClasses) {
}
}
function loadFrames(videoTab) {
console.log("LOADING FRAMES:", videoTab)
removeAll(_video_settings_tab_items);
_video_settings_tab_items = [];
for (var frame in videoTab.frames) {
var newItem = TabItem.create(
`_vsi_${videoTab.id}-${videoTab.frames[frame].id}`,
videoTab.frames[frame].host,
videoTab.frames[frame].url != videoTab.url,
(click) => {
unselect(_video_settings_tab_items, 'tabitem-selected');
click.target.classList.add('selected');
click.target.classList.add('tabitem-selected');
loadConfig(videoTab.frames[frame].host);
click.stopPropagation();
}
);
MenuTab.videoSettings_items.appendChild(newItem);
_video_settings_tab_items.push(newItem);
}
}
async function getSite(){
if (Debug.debug) {
console.log("[popup.js] requesting current site");
}
port.postMessage({cmd: 'get-current-site'});
try {
port.postMessage({cmd: 'get-current-site'});
} catch (e) {
console.log("[popup::getSite] sending get-current-site failed for some reason. Reason:", e)
}
}
function openMenu(menu){
@ -387,6 +396,23 @@ function openMenu(menu){
}
function showMenu(tab) {
if (!tablist) {
// todo: fix & remove this
return;
}
for (const i in tablist) {
tablist[i].unselect();
tablist[i].hideSubitems();
}
tablist[tab].select();
tablist[tab].showSubitems();
// todo: display the correct tab
selectedMenu = tab;
}
function getCustomAspectRatio() {
var textBox_value = document.getElementById("_input_custom_ar").value.trim();
@ -455,25 +481,25 @@ document.addEventListener("click", (e) => {
if(e.target.classList.contains("disabled"))
return;
if(e.target.classList.contains("menu-item")){
// if(e.target.classList.contains("menu-item")){
if(Debug.debug) {
console.log("[popup.js::eventListener] clicked on a tab. Class list:", e.target.classList);
}
// if(Debug.debug) {
// console.log("[popup.js::eventListener] clicked on a tab. Class list:", e.target.classList);
// }
if(e.target.classList.contains("_menu_tab_settings_ext")){
openMenu("extensionSettings");
} else if(e.target.classList.contains("_menu_tab_settings_site")){
openMenu("siteSettings");
} else if(e.target.classList.contains("_menu_tab_settings_video")){
openMenu("videoSettings");
} else if(e.target.classList.contains("_menu_tab_about")){
openMenu("about");
}
// if(e.target.classList.contains("_menu_tab_settings_ext")){
// openMenu("extensionSettings");
// } else if(e.target.classList.contains("_menu_tab_settings_site")){
// openMenu("siteSettings");
// } else if(e.target.classList.contains("_menu_tab_settings_video")){
// openMenu("videoSettings");
// } else if(e.target.classList.contains("_menu_tab_about")){
// openMenu("about");
// }
// don't send commands
return;
}
// // don't send commands
// return;
// }
if(e.target.classList.contains("_ext")) {
var command = {};
if(e.target.classList.contains("_ext_global_options")){

View File

@ -16,32 +16,12 @@
<!-- TABS/SIDEBAR -->
<div class="left-side">
<div id="_menu_tab_settings_ext" class="menu-item _menu_tab_settings_ext">
Extension settings
</div>
<div id="_menu_tab_settings_site" class="menu-item _menu_tab_settings_site">
Site settings
<span class="menu-item-inline-desc"><br/>Settings for <span id="_menu_tab_settings_site_site_label"></span></span>
</div>
<div id="_menu_tab_settings_video" class="menu-item _menu_tab_settings_video">
Video settings
<span class="menu-item-inline-desc"><br/>Crop & stretch options for current video</span>
<div id="_menu_tab_settings_video_items" class="tabitem-container">
</div>
</div>
<div id="_menu_tab_about" class="menu-item _menu_tab_about">
About Ultrawidify<span class="menu-item-inline-desc"><br/>See for bug reports</span>
</div>
<div id="tablist" class="left-side">
</div>
<!-- PANELS/CONTENT -->
<div class="right-side">
<div id="script-not-running-warning" class="warning">If you see this line, then your browser didn't start the popup script yet. This is a problem caused by the browser. Please wait a few seconds.</div>
<div id="tab-content" class="right-side">
<!-- <div id="script-not-running-warning" class="warning">If you see this line, then your browser didn't start the popup script yet. This is a problem caused by the browser. Please wait a few seconds.</div> -->
<!-- EXTENSION SETTINGS -->
<div id="_menu_settings_ext" class="suboption hidden">
@ -239,7 +219,7 @@
</div>
<!-- ABOUTR -->
<!-- ABOUT -->
<div id="_menu_about" class="suboption hidden">
<div class="row">
<span class="label">Ultrawidify version:</span><br/> <span id="uw-version"></span>
@ -264,8 +244,12 @@
<script src="../../js/lib/Settings.js"></script>
<!-- ui libs -->
<script src="../../js/lib/libghettoui/BaseUi.js"></script>
<script src="../../js/lib/libghettoui/popup/MenuItem.js"></script>
<script src="../../js/lib/libghettoui/popup/TabItem.js"></script>
<script src="./js/popupvars.js"></script>
<script src="./js/popup.js"></script>
</body>