diff --git a/js/lib/libghettoui/BaseUi.js b/js/lib/libghettoui/BaseUi.js index 9550f65..ef9cc05 100644 --- a/js/lib/libghettoui/BaseUi.js +++ b/js/lib/libghettoui/BaseUi.js @@ -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); } diff --git a/js/lib/libghettoui/popup/MenuItem.js b/js/lib/libghettoui/popup/MenuItem.js index c0b4e99..0595355 100644 --- a/js/lib/libghettoui/popup/MenuItem.js +++ b/js/lib/libghettoui/popup/MenuItem.js @@ -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(); + } + } \ No newline at end of file diff --git a/js/lib/libghettoui/popup/TabItem.js b/js/lib/libghettoui/popup/TabItem.js index a0569d5..8406217 100644 --- a/js/lib/libghettoui/popup/TabItem.js +++ b/js/lib/libghettoui/popup/TabItem.js @@ -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'); } } diff --git a/js/uw-bg.js b/js/uw-bg.js index 8208aa1..6cff81b 100644 --- a/js/uw-bg.js +++ b/js/uw-bg.js @@ -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); diff --git a/res/popup/css/popup.css b/res/popup/css/popup.css index 3eb1b2d..03bc329 100644 --- a/res/popup/css/popup.css +++ b/res/popup/css/popup.css @@ -75,3 +75,8 @@ html, body { content: "⦿"; padding-right: 0.5em; } + +.tabitem-iframe::after { + content: ">"; + padding-left: 0.33em; +} \ No newline at end of file diff --git a/res/popup/js/popup.js b/res/popup/js/popup.js index a709f0a..17f8b94 100644 --- a/res/popup/js/popup.js +++ b/res/popup/js/popup.js @@ -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")){ diff --git a/res/popup/popup.html b/res/popup/popup.html index cb771df..37d65d4 100644 --- a/res/popup/popup.html +++ b/res/popup/popup.html @@ -16,32 +16,12 @@ -