Merge branch 'master' into stable
This commit is contained in:
commit
a12c43451f
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
||||
ultrawidify.zip
|
||||
ultrawidify-git.zip
|
||||
old/
|
||||
build/
|
||||
|
73
README.md
73
README.md
@ -6,15 +6,50 @@ If you own an ultrawide monitor, you have probably noticed that sometimes videos
|
||||
|
||||
![Demo](img-demo/example-httyd2.png "Should these black bars be here? No [...] But an ultrawide user never forgets.")
|
||||
|
||||
Works (tested!) on Youtube and Netflix, but you can try your luck with other sites as well. Available for [Firefox](https://addons.mozilla.org/en/firefox/addon/ultrawidify/) and [Chrome](https://chrome.google.com/webstore/detail/ultrawidify/dndehlekllfkaijdlokmmicgnlanfjbi). Should support theater mode on youtube, iframes only supported on fullscreen.
|
||||
### Limitations
|
||||
|
||||
Youtube demo of autodetection stuff can be found [here](https://www.youtube.com/watch?v=j2xn1WpbtCQ).
|
||||
* Unclear how extension handles sites with more than one video per page.
|
||||
* Autodetection is only correct 95% of the time, most of the time.
|
||||
* That new stretching mode wasn't thoroughly tested yet. Issues may be present.
|
||||
* Enabling extension everywhere (as opposed to whitelisted sites) could break some websites.
|
||||
|
||||
## Beggathon
|
||||
### Features
|
||||
|
||||
* **Can be enabled or disabled on per-site basis**
|
||||
* **Crop video to fit screen** (no stretching. Supported aspect ratios: 21/9 (1:2.39), 16:9, 16:10, _one (1) custom aspect ratio_)
|
||||
* **Automatic aspect ratio detection** (can be enabled/disabled entirely or on a per-site basis, separately of the extension. Autodetection in action: [youtube](https://www.youtube.com/watch?v=j2xn1WpbtCQ))
|
||||
* **[NEW in v3!] Stretch video to fit the screen** (4 different approaches)
|
||||
* **Supports Youtube theater mode**
|
||||
|
||||
### Officially supported sites
|
||||
|
||||
* Youtube
|
||||
* Netflix
|
||||
|
||||
### Other sites
|
||||
|
||||
I am not actively testing extension on other sites. You can try your luck and enable extension for any unsupported site you stumble across via extension popup (in the _Setting for this site_ menu), but I make no guarantees it will work everywhere.
|
||||
|
||||
### Installing this extension
|
||||
|
||||
You can download this extension from Firefox' and Chrome's extension stores:
|
||||
|
||||
* [Firefox](https://addons.mozilla.org/en/firefox/addon/ultrawidify/) (v3.0.0)
|
||||
* [Chrome](https://chrome.google.com/webstore/detail/ultrawidify/dndehlekllfkaijdlokmmicgnlanfjbi) (v2.2.5-ish)
|
||||
|
||||
### Beggathon
|
||||
|
||||
Working on this extension takes time, coffee and motivation. If you want to buy me a beer or something, you can [use this link to send me motivation](https://www.paypal.me/tamius). **Any donations are well appreciated.**
|
||||
|
||||
## The long version
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# The long version
|
||||
|
||||
The technology has been here for a while, but plenty of people don't know how to properly encode a video (despite the fact [youtube has an article that explains aspect ratios](https://support.google.com/youtube/answer/6375112)). Plenty of people surprisingly includes major Holywood studios, such as [Marvel](https://www.youtube.com/watch?v=Ke1Y3P9D0Bc), [Disney](https://www.youtube.com/watch?v=yCOPJi0Urq4), [Dreamworks](https://www.youtube.com/watch?v=oKiYuIsPxYk), [Warner Brothers](https://www.youtube.com/watch?v=VYZ3U1inHA4), [Sony](https://www.youtube.com/watch?v=7BWWWQzTpNU), et cetera. You'd think that this is the one thing Holywood studios and people who make [music videos for a living](https://www.youtube.com/watch?v=c6Mx2mxpaCY) would know how to do right, but they don't. This extension is here to fix that.
|
||||
|
||||
@ -22,15 +57,6 @@ The technology has been here for a while, but plenty of people don't know how to
|
||||
|
||||
## Features
|
||||
|
||||
(Note: this readme is being written ahead of time, so not all features described here are available in the store version of the extension. Firefox users can expect these features by, at latest, 1st of August. Chrome version may take a little longer.)
|
||||
|
||||
TL;DR:
|
||||
|
||||
* **Can be enabled or disabled on per-site basis**
|
||||
* **Crop video to fit screen** (no stretching. Supported aspect ratios: 21/9 (1:2.39), 16:9, 16:10, _one custom aspect ratio_)
|
||||
* **Automatic aspect ratio detection** (can be enabled/disabled entirely or on a per-site basis, separately of the extension)
|
||||
* **[NEW in v3!] Stretch video to fit the screen** (4 different approaches)
|
||||
|
||||
Most settings are self-explanatory, but we'll get into details anyway.
|
||||
|
||||
### Limitations:
|
||||
@ -56,8 +82,7 @@ In the **Options for this site** section, there's some sidenotes to be had:
|
||||
|
||||
### Automatic aspect ratio detection
|
||||
|
||||
There's a few caveats to automatic aspect ratio detection. Namely, it only works on HTML5 videos (but who doesn't use HTML5 these days?). If videos on the site are DRM-protected (e.g. Netflix), autodetection will not work unless you're using Firefox (and even then, no guarantees).
|
||||
|
||||
There's a few caveats to automatic aspect ratio detection. Namely, it only works on HTML5 videos (but who doesn't use HTML5 these days?). If videos on the site are DRM-protected (e.g. Netflix), autodetection will not work unless you're using Firefox (and even then, no guarantees). Video demonstration of autodetection can be found [here](https://www.youtube.com/watch?v=j2xn1WpbtCQ).
|
||||
|
||||
![Demo](img-demo/ui/popup/autoar.png)
|
||||
|
||||
@ -134,9 +159,9 @@ They still aren't rebindable.
|
||||
|
||||
### Permanent install / stable
|
||||
|
||||
[Latest stable for Firefox — download from AMO](https://addons.mozilla.org/en/firefox/addon/ultrawidify/)
|
||||
[Latest stable for Firefox — download from AMO](https://addons.mozilla.org/en/firefox/addon/ultrawidify/) (v3.0.0)
|
||||
|
||||
[Latest stafle for Chrome — download from Chrome store](https://chrome.google.com/webstore/detail/ultrawidify/dndehlekllfkaijdlokmmicgnlanfjbi)
|
||||
[Latest stafle for Chrome — download from Chrome store](https://chrome.google.com/webstore/detail/ultrawidify/dndehlekllfkaijdlokmmicgnlanfjbi) (v2.2.5)
|
||||
|
||||
### Installing the current, github version
|
||||
|
||||
@ -153,13 +178,13 @@ They still aren't rebindable.
|
||||
|
||||
## Plans for the future
|
||||
|
||||
~~1. Handle porting of extension settings between versions. (Some people had some issues where extension broke until reinstalled, and corrupted settings seemed to be the problem.)~~ seems to work for me?
|
||||
2. Reintroduce gradual zoom on z and u and provide a way to 'scroll' the zoomed in video up/down left/right
|
||||
reintroduce settings page (rebindable keys, blacklist/whitelist management, some settings for automatic aspect ratio detection)
|
||||
3. site-specific options for sites that require additional CSS classes or other hacks
|
||||
4. figure the best way to do GUI (injecting buttons into the player bar is not a good way. Been there, done that, each site has its own way and some appear to be impossible). Might get bumped to be released alongside #2
|
||||
~~5. Stretch mode, because some people are very salty and toxic about the fact that this extension is here to solve a problem that's different than the one they want. More salty than me rn.~~ done
|
||||
6. Improvements to automatic aspect ratio detection
|
||||
1. ~~Handle porting of extension settings between versions. (Some people had some issues where extension broke until reinstalled, and corrupted settings seemed to be the problem.)~~ seems to work for me?
|
||||
2. Reintroduce gradual zoom on z and u and provide a way to 'scroll' the zoomed in video up/down left/right.
|
||||
3. reintroduce settings page (rebindable keys, blacklist/whitelist management, some settings for automatic aspect ratio detection)
|
||||
4. site-specific options for sites that require additional CSS classes or other hacks
|
||||
5. figure the best way to do GUI (injecting buttons into the player bar is not a good way. Been there, done that, each site has its own way and some appear to be impossible). Might get bumped to be released alongside #2
|
||||
6. ~~Stretch mode, because some people are very salty and toxic about the fact that this extension is here to solve a problem that's different than the one they want. More salty than me rn.~~ done
|
||||
7. Improvements to automatic aspect ratio detection
|
||||
|
||||
## Changelog
|
||||
|
||||
|
@ -7,8 +7,8 @@ Debug = {
|
||||
keyboard: true,
|
||||
debugResizer: true,
|
||||
debugArDetect: true,
|
||||
debugStorage: true,
|
||||
comms: true,
|
||||
debugStorage: false,
|
||||
comms: false,
|
||||
// showArDetectCanvas: true,
|
||||
flushStoredSettings: false,
|
||||
playerDetectDebug: true,
|
||||
|
@ -31,7 +31,7 @@ var ExtensionConf = {
|
||||
vSamples: 360,
|
||||
// samplingInterval: 10, // we sample at columns at (width/this) * [ 1 .. this - 1]
|
||||
blackLevel_default: 10, // everything darker than 10/255 across all RGB components is considered black by
|
||||
// default. GlobalVars.blackLevel can decrease if we detect darker black.
|
||||
// default. blackLevel can decrease if we detect darker black.
|
||||
blackbarTreshold: 16, // if pixel is darker than blackLevel + blackbarTreshold, we count it as black
|
||||
// on 0-255. Needs to be fairly high (8 might not cut it) due to compression
|
||||
// artifacts in the video itself
|
||||
@ -194,13 +194,15 @@ var ExtensionConf = {
|
||||
status: "enabled", // should extension work on this site?
|
||||
arStatus: "default", // should we enable autodetection
|
||||
statusEmbedded: "enabled", // should extension work for this site when embedded on other sites?
|
||||
override: true // ignore value localStorage in favour of this
|
||||
override: false, // ignore value localStorage in favour of this
|
||||
type: 'official' // is officially supported? (Alternatives are 'community' and 'user-defined')
|
||||
},
|
||||
"www.netflix.com" : {
|
||||
status: "enabled",
|
||||
arStatus: BrowserDetect.firefox ? "default" : "disabled",
|
||||
statusEmbedded: "enabled",
|
||||
override: true
|
||||
override: false,
|
||||
type: 'official'
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ if(Debug.debug)
|
||||
class Keybinds {
|
||||
constructor(pageInfo){
|
||||
this.pageInfo = pageInfo;
|
||||
this.settings = pageInfo.settings;
|
||||
this.inputs = ['input','select','button','textarea'];
|
||||
}
|
||||
|
||||
@ -36,7 +37,7 @@ class Keybinds {
|
||||
|
||||
// building modifiers list:
|
||||
var modlist = "";
|
||||
for(var mod of ExtensionConf.keyboard.modKeys){
|
||||
for(var mod of this.settings.active.keyboard.modKeys){
|
||||
if(event[mod])
|
||||
modlist += (mod + "_")
|
||||
}
|
||||
@ -52,8 +53,8 @@ class Keybinds {
|
||||
console.log("[Keybinds::_kbd_process] our full keypress is this", keypress );
|
||||
|
||||
|
||||
if(ExtensionConf.keyboard.shortcuts[keypress]){
|
||||
var conf = ExtensionConf.keyboard.shortcuts[keypress];
|
||||
if(this.settings.active.keyboard.shortcuts[keypress]){
|
||||
var conf = this.settings.active.keyboard.shortcuts[keypress];
|
||||
|
||||
if(Debug.debug && Debug.keyboard)
|
||||
console.log("[Keybinds::_kbd_process] there's an action associated with this keypress. conf:", conf);
|
||||
|
@ -1,169 +0,0 @@
|
||||
// This file handles saving and loading of settings.
|
||||
// Actual settings are in ExtensionConf
|
||||
|
||||
if(Debug.debug)
|
||||
console.log("Loading: Settings.js");
|
||||
|
||||
var _se_init = async function(isSlave){
|
||||
|
||||
if(Debug.debug)
|
||||
console.log("[Settings::_se_init()] -------- starting init! ---------");
|
||||
|
||||
if(isSlave === undefined)
|
||||
isSlave = false;
|
||||
|
||||
if(isSlave){
|
||||
// request settings from background script. Yes, this is supposed to be global.
|
||||
var res = await Comms.sendToBackgroundScript({cmd: "gib-settings"});
|
||||
|
||||
ExtensionConf = res.response;
|
||||
|
||||
if(Debug.debug){
|
||||
console.log("[Settings::_se_init()] received settings from the background script. ExtensionConf:",ExtensionConf,"response message was this:",res);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var newSettings = await StorageManager.getopt_async("uw-settings");
|
||||
var uwVersion = browser.runtime.getManifest().version;
|
||||
|
||||
if (Debug.debug)
|
||||
console.log("[Settings::_se_init()] settings saved in localstorage are:", newSettings, " - if that's empty, it's gonna be replaced by this:", ExtensionConf, ")");
|
||||
|
||||
if ((Object.keys(newSettings).length === 0 && newSettings.constructor === Object)){
|
||||
if(Debug.debug)
|
||||
console.log("[Settings::_se_init()] no saved settings, saving default");
|
||||
StorageManager.setopt({"uw-settings": ExtensionConf});
|
||||
}
|
||||
else{
|
||||
var actualSettings = newSettings["uw-settings"];
|
||||
if(actualSettings.version === undefined || actualSettings.version != uwVersion){
|
||||
ExtensionConf['version'] = uwVersion;
|
||||
|
||||
if(Debug.debug)
|
||||
console.log("[Settings::_se_init()] extension was updated, replacing settings", ExtensionConf);
|
||||
|
||||
StorageManager.setopt({"uw-settings": ExtensionConf});
|
||||
}
|
||||
else{
|
||||
_se_patchUserSettings(actualSettings, ExtensionConf);
|
||||
}
|
||||
if(Debug.debug)
|
||||
console.log("[Settings::_se_init()] parsed settings:", actualSettings, "were they copied to ExtensionConf?",ExtensionConf);
|
||||
|
||||
}
|
||||
|
||||
if(Debug.debug)
|
||||
console.log("[Settings::_se_init] settings have been loaded/reloaded. Current state: ", ExtensionConf);
|
||||
|
||||
}
|
||||
|
||||
var _se_patchUserSettings = function(saved, extDefaults){
|
||||
for(var k in extDefaults){
|
||||
if(extDefaults[k] != null && typeof extDefaults[k] === 'object' && extDefaults[k].constructor === Object){
|
||||
if(typeof saved[k] !== 'object' || saved[k].constructor !== Object || extDefaults[k].override === true)
|
||||
continue; // if user's settings are wrong or if override flag is set, we keep value in extDefaults
|
||||
|
||||
_se_patchUserSettings(saved[k], extDefaults[k]);
|
||||
}
|
||||
else{
|
||||
extDefaults[k] = saved[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var _se_save = function(settings){
|
||||
StorageManager.delopt("uw-settings");
|
||||
|
||||
if(settings !== undefined){
|
||||
StorageManager.setopt({"uw-settings": settings});
|
||||
}
|
||||
else{
|
||||
StorageManager.setopt({"uw-settings": ExtensionConf});
|
||||
}
|
||||
|
||||
if (Debug.debug)
|
||||
console.log("[Settings::_se_save()] saving settings:", settings);
|
||||
}
|
||||
|
||||
var _se_reload = function(){
|
||||
this.init(true);
|
||||
}
|
||||
|
||||
var _se_isBlacklisted = function(site){
|
||||
return this.blacklist.indexOf(site) > -1;
|
||||
}
|
||||
|
||||
var _se_isWhitelisted = function(site){
|
||||
return this.whitelist.indexOf(site) > -1;
|
||||
}
|
||||
|
||||
var Settings = {
|
||||
init: _se_init,
|
||||
save: _se_save,
|
||||
reload: _se_reload,
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------
|
||||
// Nastavitve za posamezno stran
|
||||
// Config for a given page:
|
||||
//
|
||||
// <hostname> : {
|
||||
// status: <option> // should extension work on this site?
|
||||
// arStatus: <option> // should we do autodetection on this site?
|
||||
// statusEmbedded: <option> // reserved for future... maybe
|
||||
// }
|
||||
//
|
||||
// Veljavne vrednosti za možnosti
|
||||
// Valid values for options:
|
||||
//
|
||||
// status, arStatus, statusEmbedded:
|
||||
//
|
||||
// * enabled — always allow
|
||||
// * default — allow if default is to allow, block if default is to block
|
||||
// * disabled — never allow
|
||||
//
|
||||
|
||||
canStartExtension = function(site) {
|
||||
if(site === undefined) {
|
||||
site = window.location.hostname;
|
||||
}
|
||||
|
||||
// console.log("CAN WE START THIS EXTENSION ON SITE", site,
|
||||
// "?\n\nExtensionConf.sites[site]=",ExtensionConf.sites[site],
|
||||
// "\nExtension mode?", ExtensionConf.extensionMode
|
||||
// );
|
||||
|
||||
if (ExtensionConf.sites[site] === undefined) {
|
||||
return ExtensionConf.extensionMode === "blacklist"; // site not defined, this does default option
|
||||
}
|
||||
|
||||
if (ExtensionConf.extensionMode === "blacklist") {
|
||||
return ExtensionConf.sites[site].status !== "disabled";
|
||||
} else if (ExtensionConf.extensionMode === "whitelist" ) {
|
||||
return ExtensionConf.sites[site].status === "enabled";
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
canStartAutoAr = function(site) {
|
||||
if(site === undefined) {
|
||||
site = window.location.hostname;
|
||||
}
|
||||
|
||||
if (ExtensionConf.sites[site] === undefined) {
|
||||
return ExtensionConf.arDetect.mode === "blacklist"; // site not defined, this does default option
|
||||
}
|
||||
|
||||
if (ExtensionConf.arDetect.mode === "blacklist") {
|
||||
return ExtensionConf.sites[site].arStatus !== "disabled";
|
||||
} else if (ExtensionConf.arDetect.mode === "whitelist" ) {
|
||||
return ExtensionConf.sites[site].arStatus === "enabled";
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,257 +0,0 @@
|
||||
if(Debug.debug){
|
||||
console.log("Loading: SitesConf.js");
|
||||
}
|
||||
|
||||
|
||||
|
||||
var _sc_sites = {
|
||||
"www.youtube.com" : {
|
||||
status: "whitelisted", // should extension work on this site?
|
||||
arStatus: "follow-global", // should we enable autodetection
|
||||
statusEmbedded: "whitelisted", // should extension work for this site when embedded on other sites?
|
||||
override: false // ignore value localStorage in favour of this
|
||||
},
|
||||
"www.netflix.com" : {
|
||||
status: "whitelisted",
|
||||
arStatus: "blacklisted",
|
||||
statusEmbedded: "whitelisted",
|
||||
override: false
|
||||
},
|
||||
}
|
||||
|
||||
// var _sc_SITES = {
|
||||
// "vimeo.com" : {
|
||||
// extraCss: [],
|
||||
// bannedCss: [],
|
||||
// nonfsPlayerMod: function(){
|
||||
// // hack player to take all the width
|
||||
// $("head").append('<style type="text/css">.uw_forceFullWidth {width: 100% !important} .uw_forceCenter{text-align: center;}</style>');
|
||||
//
|
||||
// var e = document.getElementsByClassName("player_outro_area")[0];
|
||||
// e.classList.add("uw_forceFullWidth");
|
||||
// e.classList.add("uw_forceCenter");
|
||||
// e = document.getElementsByClassName("player_container")[0];
|
||||
// e.classList.add("uw_forceFullWidth");
|
||||
// e.classList.add("uw_forceCenter");
|
||||
//
|
||||
// $("video")[0].style.display = "inline-block";
|
||||
// },
|
||||
// fsPlayerMod: function(){
|
||||
// // hack player to take all the width
|
||||
// $("head").append('<style type="text/css">.uw_forceFullWidth {width: 100% !important} .uw_forceCenter{text-align: center;}</style>');
|
||||
//
|
||||
// var e = document.getElementsByClassName("player_outro_area")[0];
|
||||
// e.classList.add("uw_forceFullWidth");
|
||||
// e.classList.add("uw_forceCenter");
|
||||
// e = document.getElementsByClassName("player_container")[0];
|
||||
// e.classList.add("uw_forceFullWidth");
|
||||
// e.classList.add("uw_forceCenter");
|
||||
//
|
||||
// $("video")[0].style.display = "inline-block";
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
var _sc_init = async function(){
|
||||
|
||||
var newSettings = await StorageManager.getopt_async("uw-siteopts");
|
||||
|
||||
if (Debug.debug)
|
||||
console.log("[SitesConf::_sc_init()] settings saved in localstorage are:", newSettings, " - if that's empty, it's gonna be replaced by this:", JSON.stringify(_sc_sites), ")");
|
||||
|
||||
if ((Object.keys(newSettings).length === 0 && newSettings.constructor === Object)){
|
||||
console.log("[SitesConf::_sc_init()] replacing settings");
|
||||
StorageManager.setopt({"uw-siteopts": JSON.stringify(_sc_sites)});
|
||||
}
|
||||
else{
|
||||
var actualSettings = JSON.parse(newSettings["uw-siteopts"]);
|
||||
|
||||
if(Debug.debug)
|
||||
console.log("[SitesConf::_sc_init()] parsed settings:", actualSettings);
|
||||
|
||||
var overrides = 0;
|
||||
|
||||
for (var k in actualSettings){
|
||||
|
||||
// let sites with override=true override saved sites
|
||||
if( _sc_sites[k] != undefined && _sc_sites[k].override ){
|
||||
++overrides;
|
||||
continue;
|
||||
}
|
||||
|
||||
_sc_sites[k] = actualSettings[k];
|
||||
}
|
||||
|
||||
if(overrides > 0)
|
||||
_sc_save();
|
||||
}
|
||||
|
||||
if(Debug.debug)
|
||||
console.log("[SitesConf::_sc_init()] settings have been loaded/reloaded. Current state: ", this);
|
||||
|
||||
}
|
||||
|
||||
var _sc_reset = function(){
|
||||
StoreManager.delopt("uw-siteopts");
|
||||
_sc_init();
|
||||
}
|
||||
|
||||
var _sc_reload = function(){
|
||||
_sc_init();
|
||||
}
|
||||
|
||||
var _sc_save = function(){
|
||||
StorageManager.delopt("uw-siteopts");
|
||||
StorageManager.setopt({"uw-siteopts": JSON.stringify(_sc_sites)});
|
||||
}
|
||||
|
||||
|
||||
var _sc_createEmptySite = function(){
|
||||
return {
|
||||
status: "follow-global",
|
||||
arStatus: "follow-global",
|
||||
statusEmbedded: "follow-global",
|
||||
};
|
||||
}
|
||||
|
||||
function inIframe(){
|
||||
try {
|
||||
return window.self !== window.top;
|
||||
} catch (e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var _sc_isEnabled = function(site){
|
||||
// console.log(".... — _sc_sites[", site, "].status:", (_sc_sites[site] == undefined ? "<default>" : _sc_sites[site].status), "; ExtensionConf.extensionMode:", ExtensionConf.extensionMode)
|
||||
if( inIframe ) {
|
||||
return _sc_siteEnableEmbedded(site);
|
||||
}
|
||||
return _sc_siteEnabled(site);
|
||||
}
|
||||
|
||||
var _sc_siteEnabled = function(site){
|
||||
|
||||
// če za stran nismo določili načina delovanja, potem storimo privzeto stvar
|
||||
// if we haven't defined options for a site, we do the default thing
|
||||
if( _sc_sites[site] == undefined || _sc_sites[site].status == "follow-global"){
|
||||
|
||||
console.log(".... this site is undefined!");
|
||||
|
||||
if ( ExtensionConf.extensionMode == "blacklist" ){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if( _sc_sites[site].status == "whitelisted" )
|
||||
return true;
|
||||
|
||||
if( _sc_sites[site].status == "blacklisted" )
|
||||
return false;
|
||||
|
||||
// sem ne bi smeli priti, vendar pa za varnost naredimo en return
|
||||
// we shouldn't come here but let's do a safety return
|
||||
return false;
|
||||
}
|
||||
|
||||
var _sc_siteStatus = function(site){
|
||||
if( _sc_sites[site] == undefined)
|
||||
return "follow-global";
|
||||
return _sc_sites[site].status;
|
||||
}
|
||||
|
||||
var _sc_arEnabled = function(site){
|
||||
|
||||
if( _sc_sites[site] == undefined || _sc_sites[site].arStatus == "follow-global" ){
|
||||
if(ExtensionConf.extensionMode == "blacklist" ){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if( _sc_sites[site].arStatus == "whitelisted" )
|
||||
return true;
|
||||
|
||||
if( _sc_sites[site].arStatus == "blacklisted" )
|
||||
return false;
|
||||
}
|
||||
|
||||
var _sc_arStatus = function(site){
|
||||
if( _sc_sites[site] == undefined )
|
||||
return "follow-global";
|
||||
return _sc_sites[site].arStatus;
|
||||
}
|
||||
|
||||
var _sc_siteEnableEmbedded = function(site) {
|
||||
|
||||
if( _sc_sites[site] == undefined || _sc_sites[site].statusEmbedded == "follow-global" ){
|
||||
if(Debug.debug)
|
||||
console.log("[SitesConf::_sc_siteEnableEmbedded] site", site, "is not defined in settings.");
|
||||
|
||||
if(ExtensionConf.extensionMode == "blacklist" ){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if( _sc_sites[site].statusEmbedded == "whitelisted" )
|
||||
return true;
|
||||
|
||||
if( _sc_sites[site].statusEmbedded == "blacklisted" )
|
||||
return false;
|
||||
}
|
||||
|
||||
var _sc_updateSiteStatus = function(site, status){
|
||||
// status: {}
|
||||
// status.status - optional
|
||||
// status.arStatus - optional
|
||||
// status.statusEmbedded - optional
|
||||
//
|
||||
// <==[ Valid values for options: ]==>
|
||||
//
|
||||
// status, arStatus, statusEmbedded:
|
||||
//
|
||||
// * whitelisted — always allow
|
||||
// * follow-global — allow if default is to allow, block if default is to block
|
||||
// * blacklisted — never allow
|
||||
|
||||
if( _sc_sites[site] == undefined ){
|
||||
_sc_sites[site] = _sc_createEmptySite();
|
||||
}
|
||||
|
||||
if(status.status != undefined ){
|
||||
_sc_sites[site].status = status.status;
|
||||
}
|
||||
if(status.arStatus != undefined ){
|
||||
_sc_sites[site].arStatus = status.arStatus;
|
||||
}
|
||||
if(status.statusEmbedded != undefined ){
|
||||
_sc_sites[site].statusEmbedded = status.statusEmbedded;
|
||||
}
|
||||
|
||||
_sc_save();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var SitesConf = {
|
||||
siteopts: _sc_sites,
|
||||
init: _sc_init,
|
||||
reset: _sc_reset,
|
||||
reload: _sc_reload,
|
||||
save: _sc_save,
|
||||
updateSiteStatus: _sc_updateSiteStatus,
|
||||
updateSite: _sc_updateSiteStatus,
|
||||
getSiteStatus: _sc_siteStatus,
|
||||
getArStatus: _sc_arStatus,
|
||||
siteEnabled: _sc_siteEnabled,
|
||||
isEnabled: _sc_isEnabled,
|
||||
siteEnableEmbedded: _sc_siteEnableEmbedded,
|
||||
arEnabled: _sc_arEnabled,
|
||||
isArEnabled: _sc_arEnabled
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
var Status = {
|
||||
arStrat: "auto"
|
||||
}
|
@ -1,250 +0,0 @@
|
||||
/** Wrap an API that uses callbacks with Promises
|
||||
* This expects the pattern function withCallback(arg1, arg2, ... argN, callback)
|
||||
* @author Keith Henry <keith.henry@evolutionjobs.co.uk>
|
||||
* @license MIT */
|
||||
(function () {
|
||||
|
||||
// before we start: don't do shit in browsers that aren't Google Chrome.
|
||||
// We might need to modify this for use in IE at a later date tho
|
||||
if(chrome === undefined)
|
||||
return;
|
||||
|
||||
|
||||
'use strict';
|
||||
|
||||
/** Wrap a function with a callback with a Promise.
|
||||
* @param {function} f The function to wrap, should be pattern: withCallback(arg1, arg2, ... argN, callback).
|
||||
* @param {function} parseCB Optional function to parse multiple callback parameters into a single object.
|
||||
* @returns {Promise} Promise that resolves when the callback fires. */
|
||||
function promisify(f, parseCB) {
|
||||
return (...args) => {
|
||||
let safeArgs = args;
|
||||
let callback;
|
||||
// The Chrome API functions all use arguments, so we can't use f.length to check
|
||||
|
||||
// If there is a last arg
|
||||
if (args && args.length > 0) {
|
||||
|
||||
// ... and the last arg is a function
|
||||
const last = args[args.length - 1];
|
||||
if (typeof last === 'function') {
|
||||
// Trim the last callback arg if it's been passed
|
||||
safeArgs = args.slice(0, args.length - 1);
|
||||
callback = last;
|
||||
}
|
||||
}
|
||||
|
||||
// Return a promise
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
// Try to run the original function, with the trimmed args list
|
||||
f(...safeArgs, (...cbArgs) => {
|
||||
|
||||
// If a callback was passed at the end of the original arguments
|
||||
if (callback) {
|
||||
// Don't allow a bug in the callback to stop the promise resolving
|
||||
try { callback(...cbArgs); }
|
||||
catch (cbErr) { reject(cbErr); }
|
||||
}
|
||||
|
||||
// Chrome extensions always fire the callback, but populate chrome.runtime.lastError with exception details
|
||||
if (chrome.runtime.lastError)
|
||||
// Return as an error for the awaited catch block
|
||||
reject(new Error(chrome.runtime.lastError.message || `Error thrown by API ${chrome.runtime.lastError}`));
|
||||
else {
|
||||
if (parseCB) {
|
||||
const cbObj = parseCB(...cbArgs);
|
||||
resolve(cbObj);
|
||||
}
|
||||
else if (!cbArgs || cbArgs.length === 0)
|
||||
resolve();
|
||||
else if (cbArgs.length === 1)
|
||||
resolve(cbArgs[0]);
|
||||
else
|
||||
resolve(cbArgs);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (err) { reject(err); }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** Promisify all the known functions in the map
|
||||
* @param {object} api The Chrome native API to extend
|
||||
* @param {Array} apiMap Collection of sub-API and functions to promisify */
|
||||
function applyMap(api, apiMap) {
|
||||
if (!api)
|
||||
// Not supported by current permissions
|
||||
return;
|
||||
|
||||
for (let funcDef of apiMap) {
|
||||
let funcName;
|
||||
if (typeof funcDef === 'string')
|
||||
funcName = funcDef;
|
||||
else {
|
||||
funcName = funcDef.n;
|
||||
}
|
||||
|
||||
if (!api.hasOwnProperty(funcName))
|
||||
// Member not in API
|
||||
continue;
|
||||
|
||||
const m = api[funcName];
|
||||
if (typeof m === 'function')
|
||||
// This is a function, wrap in a promise
|
||||
api[funcName] = promisify(m, funcDef.cb);
|
||||
else
|
||||
// Sub-API, recurse this func with the mapped props
|
||||
applyMap(m, funcDef.props);
|
||||
}
|
||||
}
|
||||
|
||||
/** Apply promise-maps to the Chrome native API.
|
||||
* @param {object} apiMaps The API to apply. */
|
||||
function applyMaps(apiMaps) {
|
||||
for (let apiName in apiMaps) {
|
||||
const callbackApi = chrome[apiName];
|
||||
if (!callbackApi)
|
||||
// Not supported by current permissions
|
||||
continue;
|
||||
|
||||
const apiMap = apiMaps[apiName];
|
||||
applyMap(callbackApi, apiMap);
|
||||
}
|
||||
}
|
||||
|
||||
// accessibilityFeatures https://developer.chrome.com/extensions/accessibilityFeatures
|
||||
const knownA11ySetting = ['get', 'set', 'clear'];
|
||||
|
||||
// ContentSetting https://developer.chrome.com/extensions/contentSettings#type-ContentSetting
|
||||
const knownInContentSetting = ['clear', 'get', 'set', 'getResourceIdentifiers'];
|
||||
|
||||
// StorageArea https://developer.chrome.com/extensions/storage#type-StorageArea
|
||||
const knownInStorageArea = ['get', 'getBytesInUse', 'set', 'remove', 'clear'];
|
||||
|
||||
/** Map of API functions that follow the callback pattern that we can 'promisify' */
|
||||
applyMaps({
|
||||
accessibilityFeatures: [ // Todo: this should extend AccessibilityFeaturesSetting.prototype instead
|
||||
{ n: 'spokenFeedback', props: knownA11ySetting },
|
||||
{ n: 'largeCursor', props: knownA11ySetting },
|
||||
{ n: 'stickyKeys', props: knownA11ySetting },
|
||||
{ n: 'highContrast', props: knownA11ySetting },
|
||||
{ n: 'screenMagnifier', props: knownA11ySetting },
|
||||
{ n: 'autoclick', props: knownA11ySetting },
|
||||
{ n: 'virtualKeyboard', props: knownA11ySetting },
|
||||
{ n: 'animationPolicy', props: knownA11ySetting }],
|
||||
alarms: ['get', 'getAll', 'clear', 'clearAll'],
|
||||
bookmarks: [
|
||||
'get', 'getChildren', 'getRecent', 'getTree', 'getSubTree',
|
||||
'search', 'create', 'move', 'update', 'remove', 'removeTree'],
|
||||
browser: ['openTab'],
|
||||
browserAction: [
|
||||
'getTitle', 'setIcon', 'getPopup', 'getBadgeText', 'getBadgeBackgroundColor'],
|
||||
browsingData: [
|
||||
'settings', 'remove', 'removeAppcache', 'removeCache',
|
||||
'removeCookies', 'removeDownloads', 'removeFileSystems',
|
||||
'removeFormData', 'removeHistory', 'removeIndexedDB',
|
||||
'removeLocalStorage', 'removePluginData', 'removePasswords',
|
||||
'removeWebSQL'],
|
||||
commands: ['getAll'],
|
||||
contentSettings: [ // Todo: this should extend ContentSetting.prototype instead
|
||||
{ n: 'cookies', props: knownInContentSetting },
|
||||
{ n: 'images', props: knownInContentSetting },
|
||||
{ n: 'javascript', props: knownInContentSetting },
|
||||
{ n: 'location', props: knownInContentSetting },
|
||||
{ n: 'plugins', props: knownInContentSetting },
|
||||
{ n: 'popups', props: knownInContentSetting },
|
||||
{ n: 'notifications', props: knownInContentSetting },
|
||||
{ n: 'fullscreen', props: knownInContentSetting },
|
||||
{ n: 'mouselock', props: knownInContentSetting },
|
||||
{ n: 'microphone', props: knownInContentSetting },
|
||||
{ n: 'camera', props: knownInContentSetting },
|
||||
{ n: 'unsandboxedPlugins', props: knownInContentSetting },
|
||||
{ n: 'automaticDownloads', props: knownInContentSetting }],
|
||||
contextMenus: ['create', 'update', 'remove', 'removeAll'],
|
||||
cookies: ['get', 'getAll', 'set', 'remove', 'getAllCookieStores'],
|
||||
debugger: ['attach', 'detach', 'sendCommand', 'getTargets'],
|
||||
desktopCapture: ['chooseDesktopMedia'],
|
||||
// TODO: devtools.*
|
||||
documentScan: ['scan'],
|
||||
downloads: [
|
||||
'download', 'search', 'pause', 'resume', 'cancel',
|
||||
'getFileIcon', 'erase', 'removeFile', 'acceptDanger'],
|
||||
enterprise: [{ n: 'platformKeys', props: ['getToken', 'getCertificates', 'importCertificate', 'removeCertificate'] }],
|
||||
extension: ['isAllowedIncognitoAccess', 'isAllowedFileSchemeAccess'], // mostly deprecated in favour of runtime
|
||||
fileBrowserHandler: ['selectFile'],
|
||||
fileSystemProvider: ['mount', 'unmount', 'getAll', 'get', 'notify'],
|
||||
fontSettings: [
|
||||
'setDefaultFontSize', 'getFont', 'getDefaultFontSize', 'getMinimumFontSize',
|
||||
'setMinimumFontSize', 'getDefaultFixedFontSize', 'clearDefaultFontSize',
|
||||
'setDefaultFixedFontSize', 'clearFont', 'setFont', 'clearMinimumFontSize',
|
||||
'getFontList', 'clearDefaultFixedFontSize'],
|
||||
gcm: ['register', 'unregister', 'send'],
|
||||
history: ['search', 'getVisits', 'addUrl', 'deleteUrl', 'deleteRange', 'deleteAll'],
|
||||
i18n: ['getAcceptLanguages', 'detectLanguage'],
|
||||
identity: [
|
||||
'getAuthToken', 'getProfileUserInfo', 'removeCachedAuthToken',
|
||||
'launchWebAuthFlow', 'getRedirectURL'],
|
||||
idle: ['queryState'],
|
||||
input: [{
|
||||
n: 'ime', props: [
|
||||
'setMenuItems', 'commitText', 'setCandidates', 'setComposition', 'updateMenuItems',
|
||||
'setCandidateWindowProperties', 'clearComposition', 'setCursorPosition', 'sendKeyEvents',
|
||||
'deleteSurroundingText']
|
||||
}],
|
||||
management: [
|
||||
'setEnabled', 'getPermissionWarningsById', 'get', 'getAll',
|
||||
'getPermissionWarningsByManifest', 'launchApp', 'uninstall', 'getSelf',
|
||||
'uninstallSelf', 'createAppShortcut', 'setLaunchType', 'generateAppForLink'],
|
||||
networking: [{ n: 'config', props: ['setNetworkFilter', 'finishAuthentication'] }],
|
||||
notifications: ['create', 'update', 'clear', 'getAll', 'getPermissionLevel'],
|
||||
pageAction: ['getTitle', 'setIcon', 'getPopup'],
|
||||
pageCapture: ['saveAsMHTML'],
|
||||
permissions: ['getAll', 'contains', 'request', 'remove'],
|
||||
platformKeys: ['selectClientCertificates', 'verifyTLSServerCertificate',
|
||||
{ n: "getKeyPair", cb: (publicKey, privateKey) => { return { publicKey, privateKey }; } }],
|
||||
runtime: [
|
||||
'getBackgroundPage', 'openOptionsPage', 'setUninstallURL',
|
||||
'restartAfterDelay', 'sendMessage',
|
||||
'sendNativeMessage', 'getPlatformInfo', 'getPackageDirectoryEntry',
|
||||
{ n: "requestUpdateCheck", cb: (status, details) => { return { status, details }; } }],
|
||||
scriptBadge: ['getPopup'],
|
||||
sessions: ['getRecentlyClosed', 'getDevices', 'restore'],
|
||||
storage: [ // Todo: this should extend StorageArea.prototype instead
|
||||
{ n: 'sync', props: knownInStorageArea },
|
||||
{ n: 'local', props: knownInStorageArea },
|
||||
{ n: 'managed', props: knownInStorageArea }],
|
||||
socket: [
|
||||
'create', 'connect', 'bind', 'read', 'write', 'recvFrom', 'sendTo',
|
||||
'listen', 'accept', 'setKeepAlive', 'setNoDelay', 'getInfo', 'getNetworkList'],
|
||||
sockets: [
|
||||
{ n: 'tcp', props: [
|
||||
'create','update','setPaused','setKeepAlive','setNoDelay','connect',
|
||||
'disconnect','secure','send','close','getInfo','getSockets'] },
|
||||
{ n: 'tcpServer', props: [
|
||||
'create','update','setPaused','listen','disconnect','close','getInfo','getSockets'] },
|
||||
{ n: 'udp', props: [
|
||||
'create','update','setPaused','bind','send','close','getInfo',
|
||||
'getSockets','joinGroup','leaveGroup','setMulticastTimeToLive',
|
||||
'setMulticastLoopbackMode','getJoinedGroups','setBroadcast'] }],
|
||||
system: [
|
||||
{ n: 'cpu', props: ['getInfo'] },
|
||||
{ n: 'memory', props: ['getInfo'] },
|
||||
{ n: 'storage', props: ['getInfo', 'ejectDevice', 'getAvailableCapacity'] }],
|
||||
tabCapture: ['capture', 'getCapturedTabs'],
|
||||
tabs: [
|
||||
'get', 'getCurrent', 'sendMessage', 'create', 'duplicate',
|
||||
'query', 'highlight', 'update', 'move', 'reload', 'remove',
|
||||
'detectLanguage', 'captureVisibleTab', 'executeScript',
|
||||
'insertCSS', 'setZoom', 'getZoom', 'setZoomSettings',
|
||||
'getZoomSettings', 'discard'],
|
||||
topSites: ['get'],
|
||||
tts: ['isSpeaking', 'getVoices', 'speak'],
|
||||
types: ['set', 'get', 'clear'],
|
||||
vpnProvider: ['createConfig', 'destroyConfig', 'setParameters', 'sendPacket', 'notifyConnectionStateChanged'],
|
||||
wallpaper: ['setWallpaper'],
|
||||
webNavigation: ['getFrame', 'getAllFrames', 'handlerBehaviorChanged'],
|
||||
windows: ['get', 'getCurrent', 'getLastFocused', 'getAll', 'create', 'update', 'remove']
|
||||
});
|
||||
})();
|
10220
js/dep/jquery-3.1.1.js
vendored
10220
js/dep/jquery-3.1.1.js
vendored
File diff suppressed because it is too large
Load Diff
@ -1,15 +1,30 @@
|
||||
var _bd_usebrowser = "firefox";
|
||||
|
||||
var _bd_isFirefox = false;
|
||||
var _bd_isFirefox = true;
|
||||
var _bd_isChrome = false;
|
||||
var _bd_isEdge = false; // we'll see if FF
|
||||
|
||||
try{
|
||||
// todo: find something that works in firefox but not in edge (or vice-versa)
|
||||
_bd_isFirefox = true;
|
||||
_bd_isEdge = false;
|
||||
// todo: find something that works in firefox but not in edge (or vice-versa)
|
||||
// note that this function returns a promise! and is broken for some reason
|
||||
var browserinfo = browser.runtime.getBrowserInfo();
|
||||
|
||||
// we don't need to actually check because only firefox supports that.
|
||||
// if we're not on firefox, the above call will probably throw an exception anyway.
|
||||
// if browsers other than firefox start supporting that, well ... we'll also need to actually await for promise
|
||||
// that getBrowserInfo() returns to resolve.
|
||||
|
||||
// if (Browser.name.toLowerCase().indexOf(firefox) !== -1 || Browser.vendor.toLowerCase().indexOf(mozilla) !== -1) {
|
||||
_bd_isFirefox = true;
|
||||
_bd_isEdge = false;
|
||||
// }
|
||||
|
||||
}
|
||||
catch (e) {};
|
||||
catch (e) {
|
||||
if(Debug.debug) {
|
||||
console.info("[BrowserDetect] browser.runtime.getBrowserInfo() probably failed. This means we're probably not using firefox.", e)
|
||||
}
|
||||
};
|
||||
|
||||
if(typeof browser === "undefined"){ // This is a good sign we're in chrome or chromium-based browsers
|
||||
if(chrome){
|
||||
@ -17,6 +32,7 @@ if(typeof browser === "undefined"){ // This is a good sign we're in chrome or ch
|
||||
_bd_usebrowser = "chrome";
|
||||
_bd_isChrome = true;
|
||||
_bd_isEdge = false;
|
||||
_bd_isFirefox = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
433
js/lib/Comms.js
433
js/lib/Comms.js
@ -1,36 +1,67 @@
|
||||
if(Debug.debug){
|
||||
console.log("Loading Comms.js")
|
||||
console.log("Loading Comms.js");
|
||||
}
|
||||
|
||||
class CommsClient {
|
||||
constructor(name){
|
||||
this.port = browser.runtime.connect({name: name});
|
||||
constructor(name, settings) {
|
||||
if (BrowserDetect.firefox) {
|
||||
this.port = browser.runtime.connect({name: name});
|
||||
} else if (BrowserDetect.chrome) {
|
||||
this.port = chrome.runtime.connect({name: name});
|
||||
} else if (BrowserDetect.edge) {
|
||||
this.port = browser.runtime.connect({name: name})
|
||||
}
|
||||
|
||||
var ths = this;
|
||||
this.port.onMessage.addListener(m => ths.processReceivedMessage(m));
|
||||
this.hasSettings = false;
|
||||
this._listener = m => ths.processReceivedMessage(m);
|
||||
this.port.onMessage.addListener(this._listener);
|
||||
|
||||
this.settings = settings;
|
||||
this.pageInfo = undefined;
|
||||
this.commsId = (Math.random() * 20).toFixed(0);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.pageInfo = null;
|
||||
this.settings = null;
|
||||
this.port.onMessage.removeListener(this._listener);
|
||||
}
|
||||
|
||||
setPageInfo(pageInfo){
|
||||
|
||||
this.pageInfo = pageInfo;
|
||||
|
||||
if(Debug.debug) {
|
||||
console.log(`[CommsClient::setPageInfo] <${this.commsId}>`, "SETTING PAGEINFO —", this.pageInfo, this)
|
||||
}
|
||||
|
||||
var ths = this;
|
||||
this._listener = m => ths.processReceivedMessage(m);
|
||||
this.port.onMessage.removeListener(this._listener);
|
||||
this.port.onMessage.addListener(this._listener);
|
||||
|
||||
}
|
||||
|
||||
processReceivedMessage(message){
|
||||
if(Debug.debug && Debug.comms){
|
||||
console.log("[CommsClient.js::processMessage] Received message from background script!", message);
|
||||
console.log(`[CommsClient.js::processMessage] <${this.commsId}> Received message from background script!`, message);
|
||||
}
|
||||
|
||||
if (!this.pageInfo || !this.settings.active) {
|
||||
if(Debug.debug && Debug.comms){
|
||||
console.log(`[CommsClient.js::processMessage] <${this.commsId}> this.pageInfo (or settings) not defined. Extension is probably disabled for this site.\npageInfo:`, this.pageInfo,
|
||||
"\nsettings.active:", this.settings.active,
|
||||
"\nnobj:", this
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.cmd === "set-ar") {
|
||||
this.pageInfo.setAr(message.ratio);
|
||||
} else if (message.cmd === 'set-video-float') {
|
||||
ExtensionConf.miscFullscreenSettings.videoFloat = message.newFloat;
|
||||
this.settings.active.miscFullscreenSettings.videoFloat = message.newFloat;
|
||||
this.pageInfo.restoreAr();
|
||||
} else if (message.cmd === "has-videos") {
|
||||
|
||||
} else if (message.cmd === "set-config") {
|
||||
this.hasSettings = true;
|
||||
ExtensionConf = message.conf;
|
||||
// this.pageInfo.reset();
|
||||
} else if (message.cmd === "set-stretch") {
|
||||
this.pageInfo.setStretchMode(StretchMode[message.mode]);
|
||||
} else if (message.cmd === "autoar-start") {
|
||||
@ -45,28 +76,7 @@ class CommsClient {
|
||||
} else if (message.cmd === "resume-processing") {
|
||||
// todo: autoArStatus
|
||||
this.pageInfo.resumeProcessing(message.autoArStatus);
|
||||
} else if (message.cmd === "reload-settings") {
|
||||
ExtensionConf = message.newConf;
|
||||
this.pageInfo.reset();
|
||||
if(ExtensionConf.arDetect.mode === "disabled") {
|
||||
this.pageInfo.stopArDetection();
|
||||
} else {
|
||||
this.pageInfo.startArDetection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async waitForSettings(){
|
||||
var t = this;
|
||||
return new Promise( async (resolve, reject) => {
|
||||
while(true){
|
||||
await t.sleep(100);
|
||||
if(this.hasSettings){
|
||||
resolve();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async sleep(n){
|
||||
@ -112,14 +122,10 @@ class CommsClient {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
ExtensionConf = JSON.parse(response.extensionConf);
|
||||
this.settings.active = JSON.parse(response.extensionConf);
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
async requestSettings_fallback(){
|
||||
this.port.postMessage({cmd: "get-config"});
|
||||
}
|
||||
|
||||
registerVideo(){
|
||||
this.port.postMessage({cmd: "has-video"});
|
||||
}
|
||||
@ -132,6 +138,7 @@ class CommsClient {
|
||||
class CommsServer {
|
||||
constructor(server) {
|
||||
this.server = server;
|
||||
this.settings = server.settings;
|
||||
this.ports = [];
|
||||
|
||||
var ths = this;
|
||||
@ -158,20 +165,24 @@ class CommsServer {
|
||||
}
|
||||
}
|
||||
|
||||
sendToActive(message) {
|
||||
async _getActiveTab() {
|
||||
if (BrowserDetect.firefox) {
|
||||
return await browser.tabs.query({currentWindow: true, active: true});
|
||||
} else {
|
||||
return await new Promise( (resolve, reject) => {
|
||||
chrome.tabs.query({currentWindow: true, active: true}, function (res) {
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async sendToActive(message) {
|
||||
if(Debug.debug && Debug.comms){
|
||||
console.log("%c[CommsServer::sendToActive] trying to send a message to active tab. Message:", "background: #dda; color: #11D", message);
|
||||
}
|
||||
|
||||
if(BrowserDetect.firefox){
|
||||
this._sendToActive_ff(message);
|
||||
} else if (BrowserDetect.chrome) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
async _sendToActive_ff(message){
|
||||
var tabs = await browser.tabs.query({currentWindow: true, active: true});
|
||||
var tabs = await this._getActiveTab();
|
||||
|
||||
if(Debug.debug && Debug.comms){
|
||||
console.log("[CommsServer::_sendToActive_ff] currently active tab(s)?", tabs);
|
||||
@ -186,18 +197,6 @@ class CommsServer {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async queryTabs_chrome(tabInfo){
|
||||
return new Promise(function (resolve, reject){
|
||||
browser.tabs.query(tabInfo, function(response){
|
||||
browser.tabs.query(tabInfo);
|
||||
// Chrome/js shittiness mitigation — remove this line and an empty array will be returned
|
||||
var r = response;
|
||||
resolve(r);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
onConnect(port){
|
||||
var ths = this;
|
||||
|
||||
@ -225,92 +224,83 @@ class CommsServer {
|
||||
|
||||
processReceivedMessage(message, port){
|
||||
if (Debug.debug && Debug.comms) {
|
||||
console.log("[CommsServer.js::processMessage] Received message from background script!", message, "port", port);
|
||||
console.log("[CommsServer.js::processMessage] Received message from background script!", message, "port", port, "\nsettings and server:", this.settings,this.server);
|
||||
}
|
||||
|
||||
if(message.cmd === 'get-current-site') {
|
||||
port.postMessage({cmd: 'set-current-site', site: this.server.currentSite});
|
||||
}
|
||||
|
||||
if (message.cmd === 'get-config') {
|
||||
port.postMessage({cmd: "set-config", conf: ExtensionConf, site: this.server.currentSite})
|
||||
if(Debug.debug) {
|
||||
console.log("CommsServer: received get-config. Active settings?", this.settings.active, "\n(settings:", this.settings, ")")
|
||||
}
|
||||
port.postMessage({cmd: "set-config", conf: this.settings.active, site: this.server.currentSite})
|
||||
} else if (message.cmd === 'set-stretch') {
|
||||
this.sendToActive(message);
|
||||
} else if (message.cmd === 'set-stretch-default') {
|
||||
ExtensionConf.stretch.initialMode = message.mode;
|
||||
Settings.save(ExtensionConf);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: ExtensionConf});
|
||||
this.settings.active.stretch.initialMode = message.mode;
|
||||
this.settings.save();
|
||||
} else if (message.cmd === 'set-ar') {
|
||||
this.sendToActive(message);
|
||||
} else if (message.cmd === 'set-custom-ar') {
|
||||
ExtensionConf.keyboard.shortcuts.q.arg = message.ratio;
|
||||
Settings.save(ExtensionConf);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: ExtensionConf});
|
||||
this.settings.active.keyboard.shortcuts.q.arg = message.ratio;
|
||||
this.settings.save();
|
||||
} else if (message.cmd === 'set-video-float') {
|
||||
this.sendToActive(message);
|
||||
ExtensionConf.miscFullscreenSettings.videoFloat = message.newFloat;
|
||||
Settings.save(ExtensionConf);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: ExtensionConf});
|
||||
|
||||
this.settings.active.miscFullscreenSettings.videoFloat = message.newFloat;
|
||||
this.settings.save();
|
||||
} else if (message.cmd === 'autoar-start') {
|
||||
this.sendToActive(message);
|
||||
} else if (message.cmd === "autoar-enable") { // LEGACY - can be removed prolly?
|
||||
ExtensionConf.arDetect.mode = "blacklist";
|
||||
Settings.save(ExtensionConf);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: ExtensionConf});
|
||||
} else if (message.cmd === "autoar-disable") { // LEGACY - can be removed prolly?
|
||||
ExtensionConf.arDetect.mode = "disabled";
|
||||
this.settings.active.arDetect.mode = "disabled";
|
||||
if(message.reason){
|
||||
ExtensionConf.arDetect.disabledReason = message.reason;
|
||||
this.settings.active.arDetect.disabledReason = message.reason;
|
||||
} else {
|
||||
ExtensionConf.arDetect.disabledReason = 'User disabled';
|
||||
this.settings.active.arDetect.disabledReason = 'User disabled';
|
||||
}
|
||||
Settings.save(ExtensionConf);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: ExtensionConf});
|
||||
this.settings.save();
|
||||
} else if (message.cmd === "autoar-set-interval") {
|
||||
if(Debug.debug)
|
||||
console.log("[uw-bg] trying to set new interval for autoAr. New interval is",message.timeout,"ms");
|
||||
|
||||
// set fairly liberal limit
|
||||
var timeout = message.timeout < 4 ? 4 : message.timeout;
|
||||
ExtensionConf.arDetect.timer_playing = timeout;
|
||||
Settings.save(ExtensionConf);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: ExtensionConf});
|
||||
this.settings.active.arDetect.timer_playing = timeout;
|
||||
this.settings.save();
|
||||
} else if (message.cmd === "set-autoar-defaults") {
|
||||
ExtensionConf.arDetect.mode = message.mode;
|
||||
Settings.save(ExtensionConf);
|
||||
this.sendToAll({cmd: "reload-settings", sender: "uwbg"})
|
||||
this.settings.active.arDetect.mode = message.mode;
|
||||
this.settings.save();
|
||||
} else if (message.cmd === "set-autoar-for-site") {
|
||||
if (ExtensionConf.sites[this.server.currentSite]) {
|
||||
ExtensionConf.sites[this.server.currentSite].arStatus = message.mode;
|
||||
Settings.save(ExtensionConf);
|
||||
if (this.settings.active.sites[this.server.currentSite]) {
|
||||
this.settings.active.sites[this.server.currentSite].arStatus = message.mode;
|
||||
this.settings.save();
|
||||
} else {
|
||||
ExtensionConf.sites[this.server.currentSite] = {
|
||||
this.settings.active.sites[this.server.currentSite] = {
|
||||
status: "default",
|
||||
arStatus: message.mode,
|
||||
statusEmbedded: "default"
|
||||
};
|
||||
Settings.save(ExtensionConf);
|
||||
this.settings.save();
|
||||
}
|
||||
this.sendToAll({cmd: "reload-settings", sender: "uwbg"});
|
||||
} else if (message.cmd === "set-extension-defaults") {
|
||||
ExtensionConf.extensionMode = message.mode;
|
||||
Settings.save(ExtensionConf);
|
||||
this.sendToAll({cmd: "reload-settings", sender: "uwbg"})
|
||||
this.settings.active.extensionMode = message.mode;
|
||||
this.settings.save();
|
||||
} else if (message.cmd === "set-extension-for-site") {
|
||||
if (ExtensionConf.sites[this.server.currentSite]) {
|
||||
ExtensionConf.sites[this.server.currentSite].status = message.mode;
|
||||
Settings.save(ExtensionConf);
|
||||
if (this.settings.active.sites[this.server.currentSite]) {
|
||||
this.settings.active.sites[this.server.currentSite].status = message.mode;
|
||||
this.settings.save();
|
||||
} else {
|
||||
ExtensionConf.sites[this.server.currentSite] = {
|
||||
this.settings.active.sites[this.server.currentSite] = {
|
||||
status: message.mode,
|
||||
arStatus: "default",
|
||||
statusEmbedded: message.mode
|
||||
};
|
||||
Settings.save(ExtensionConf);
|
||||
console.log("SAVING PER-SITE OPTIONS,", this.server.currentSite, ExtensionConf.sites[this.server.currentSite])
|
||||
this.settings.save();
|
||||
if(Debug.debug) {
|
||||
console.log("SAVING PER-SITE OPTIONS,", this.server.currentSite, this.settings.active.sites[this.server.currentSite])
|
||||
}
|
||||
}
|
||||
this.sendToAll({cmd: "reload-settings", sender: "uwbg"});
|
||||
}
|
||||
|
||||
if (message.cmd.startsWith('set-')) {
|
||||
port.postMessage({cmd: "set-config", conf: ExtensionConf, site: this.server.currentSite});
|
||||
}
|
||||
}
|
||||
|
||||
@ -320,29 +310,29 @@ class CommsServer {
|
||||
}
|
||||
|
||||
if (message.cmd === 'get-config') {
|
||||
var ret = {extensionConf: JSON.stringify(ExtensionConf)};
|
||||
var ret = {extensionConf: JSON.stringify(this.settings.active)};
|
||||
if (Debug.debug && Debug.comms) {
|
||||
console.log("%c[CommsServer.js::processMessage_nonpersistent_ff] Returning this:", "background-color: #11D; color: #aad", ret);
|
||||
}
|
||||
Promise.resolve(ret);
|
||||
} else if (message.cmd === "autoar-enable") {
|
||||
ExtensionConf.arDetect.mode = "blacklist";
|
||||
Settings.save(ExtensionConf);
|
||||
this.settings.active.arDetect.mode = "blacklist";
|
||||
this.settings.save();
|
||||
this.sendToAll({cmd: "reload-settings", sender: "uwbg"})
|
||||
if(Debug.debug){
|
||||
console.log("[uw-bg] autoar set to enabled (blacklist). evidenz:", ExtensionConf);
|
||||
console.log("[uw-bg] autoar set to enabled (blacklist). evidenz:", this.settings.active);
|
||||
}
|
||||
} else if (message.cmd === "autoar-disable") {
|
||||
ExtensionConf.arDetect.mode = "disabled";
|
||||
this.settings.active.arDetect.mode = "disabled";
|
||||
if(message.reason){
|
||||
ExtensionConf.arDetect.disabledReason = message.reason;
|
||||
this.settings.active.arDetect.disabledReason = message.reason;
|
||||
} else {
|
||||
ExtensionConf.arDetect.disabledReason = 'User disabled';
|
||||
this.settings.active.arDetect.disabledReason = 'User disabled';
|
||||
}
|
||||
Settings.save(ExtensionConf);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: ExtensionConf});
|
||||
this.settings.save();
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: this.settings.active});
|
||||
if(Debug.debug){
|
||||
console.log("[uw-bg] autoar set to disabled. evidenz:", ExtensionConf);
|
||||
console.log("[uw-bg] autoar set to disabled. evidenz:", this.settings.active);
|
||||
}
|
||||
} else if (message.cmd === "autoar-set-interval") {
|
||||
if(Debug.debug)
|
||||
@ -350,9 +340,9 @@ class CommsServer {
|
||||
|
||||
// set fairly liberal limit
|
||||
var timeout = message.timeout < 4 ? 4 : message.timeout;
|
||||
ExtensionConf.arDetect.timer_playing = timeout;
|
||||
Settings.save(ExtensionConf);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: ExtensionConf});
|
||||
this.settings.active.arDetect.timer_playing = timeout;
|
||||
this.settings.save();
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: this.settings.active});
|
||||
}
|
||||
}
|
||||
|
||||
@ -362,26 +352,26 @@ class CommsServer {
|
||||
}
|
||||
|
||||
if(message.cmd === 'get-config') {
|
||||
sendResponse({extensionConf: JSON.stringify(ExtensionConf), site: getCurrentTabUrl()});
|
||||
sendResponse({extensionConf: JSON.stringify(this.settings.active), site: getCurrentTabUrl()});
|
||||
// return true;
|
||||
} else if (message.cmd === "autoar-enable") {
|
||||
ExtensionConf.arDetect.mode = "blacklist";
|
||||
Settings.save(ExtensionConf);
|
||||
this.settings.active.arDetect.mode = "blacklist";
|
||||
this.settings.save();
|
||||
this.sendToAll({cmd: "reload-settings", sender: "uwbg"})
|
||||
if(Debug.debug){
|
||||
console.log("[uw-bg] autoar set to enabled (blacklist). evidenz:", ExtensionConf);
|
||||
console.log("[uw-bg] autoar set to enabled (blacklist). evidenz:", this.settings.active);
|
||||
}
|
||||
} else if (message.cmd === "autoar-disable") {
|
||||
ExtensionConf.arDetect.mode = "disabled";
|
||||
this.settings.active.arDetect.mode = "disabled";
|
||||
if(message.reason){
|
||||
ExtensionConf.arDetect.disabledReason = message.reason;
|
||||
this.settings.active.arDetect.disabledReason = message.reason;
|
||||
} else {
|
||||
ExtensionConf.arDetect.disabledReason = 'User disabled';
|
||||
this.settings.active.arDetect.disabledReason = 'User disabled';
|
||||
}
|
||||
Settings.save(ExtensionConf);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: ExtensionConf});
|
||||
this.settings.save();
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: this.settings.active});
|
||||
if(Debug.debug){
|
||||
console.log("[uw-bg] autoar set to disabled. evidenz:", ExtensionConf);
|
||||
console.log("[uw-bg] autoar set to disabled. evidenz:", this.settings.active);
|
||||
}
|
||||
} else if (message.cmd === "autoar-set-interval") {
|
||||
if(Debug.debug)
|
||||
@ -389,9 +379,9 @@ class CommsServer {
|
||||
|
||||
// set fairly liberal limit
|
||||
var timeout = message.timeout < 4 ? 4 : message.timeout;
|
||||
ExtensionConf.arDetect.timer_playing = timeout;
|
||||
Settings.save(ExtensionConf);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: ExtensionConf});
|
||||
this.settings.active.arDetect.timer_playing = timeout;
|
||||
this.settings.save();
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: this.settings.active});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -424,176 +414,3 @@ class Comms {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// var _com_queryTabs = async function(tabInfo){
|
||||
// if(BrowserDetect.usebrowser != "firefox"){
|
||||
// return await _com_chrome_tabquery_wrapper(tabInfo);
|
||||
// }
|
||||
// else{
|
||||
// return browser.tabs.query(tabInfo);
|
||||
// }
|
||||
// }
|
||||
|
||||
// var _com_getActiveTab = async function(tabInfo){
|
||||
// if(BrowserDetect.firefox){
|
||||
// return await browser.tabs.query({currentWindow: true, active: true});
|
||||
// }
|
||||
// return _com_chrome_tabquery_wrapper({currentWindow: true, active: true});
|
||||
// }
|
||||
|
||||
|
||||
// var _com_chrome_tabs_sendmsg_wrapper = async function(tab, message, options){
|
||||
// return new Promise(function (resolve, reject){
|
||||
// try{
|
||||
// browser.tabs.sendMessage(tab, message, /*options, */function(response){
|
||||
// console.log("TESTING what is this owo? (response)", response);
|
||||
|
||||
// // Chrome/js shittiness mitigation — remove this line and an empty array will be returned
|
||||
// var r = response;
|
||||
|
||||
// resolve(r);
|
||||
// });
|
||||
// }
|
||||
// catch(e){
|
||||
// reject(e);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// var _com_sendMessage = async function(tab, message, options){
|
||||
// if(BrowserDetect.usebrowser != "firefox"){
|
||||
// var r = await _com_chrome_tabs_sendmsg_wrapper(tab, message, options);
|
||||
// console.log("TESTING what is this owo? (should be a promise)", r);
|
||||
// return r;
|
||||
// }
|
||||
// else{
|
||||
// return browser.tabs.sendMessage(tab, message, options);
|
||||
// }
|
||||
// }
|
||||
|
||||
// var _com_chrome_tabs_sendmsgrt_wrapper = async function(message){
|
||||
// return new Promise(function (resolve, reject){
|
||||
// try{
|
||||
// browser.runtime.sendMessage(message, function(response){
|
||||
|
||||
// // Chrome/js shittiness mitigation — remove this line and an empty array will be returned
|
||||
// var r = response;
|
||||
|
||||
// resolve(r);
|
||||
// });
|
||||
// }
|
||||
// catch(e){
|
||||
// reject(e);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// var _com_sendMessageRuntime = async function(message){
|
||||
// if(BrowserDetect.usebrowser != "firefox"){
|
||||
// return _com_chrome_tabs_sendmsgrt_wrapper(message);
|
||||
// }
|
||||
// else{
|
||||
// return browser.runtime.sendMessage(message);
|
||||
// }
|
||||
// }
|
||||
|
||||
// // pošlje sporočilce vsem okvirjem v trenutno odprtem zavihku. Vrne tisti odgovor od tistega okvira, ki prispe prvi.
|
||||
// // sends a message to all frames in the currently opened tab. Returns the response of a frame that replied first
|
||||
// var _com_sendToAllFrames = async function(message) {
|
||||
// if(Debug.debug)
|
||||
// console.log("[Comms::_com_sendToAllFrames] sending message to all frames of currenntly active tab");
|
||||
|
||||
// var tabs = await browser.tabs.query({currentWindow: true, active: true});
|
||||
|
||||
// if(Debug.debug)
|
||||
// console.log("[Comms::_com_sendToAllFrames] trying to send message", message, " to tab ", tabs[0], ". (all tabs:", tabs,")");
|
||||
|
||||
// var response = await browser.tabs.sendMessage(tabs[0].id, message);
|
||||
// console.log("[Comms::_com_sendToAllFrames] response is this:",response);
|
||||
// return response;
|
||||
|
||||
// // if(BrowserDetect.firefox){
|
||||
// // return
|
||||
// // }
|
||||
// }
|
||||
|
||||
// // pošlje sporočilce vsem okvirjem v trenutno odprtem zavihku in vrne _vse_ odgovore
|
||||
// // sends a message to all frames in currently opened tab and returns all responses
|
||||
// var _com_sendToEachFrame = async function(message, tabId) {
|
||||
// if(Debug.debug)
|
||||
// console.log("[Comms::_com_sendToEveryFrame] sending message to every frames of currenntly active tab");
|
||||
|
||||
// if(tabId === undefined){
|
||||
// var tabs = await browser.tabs.query({currentWindow: true, active: true});
|
||||
// tabId = tabs[0].id;
|
||||
// }
|
||||
// var frames = await browser.webNavigation.getAllFrames({tabId: tabId});
|
||||
|
||||
// if(Debug.debug)
|
||||
// console.log("[Comms::_com_sendToEveryFrame] we have this many frames:", frames.length, "||| tabId:", tabId ,"frames:",frames);
|
||||
|
||||
|
||||
// // pošlji sporočilce vsakemu okvirju, potisni obljubo v tabelo
|
||||
// // send message to every frame, push promise to array
|
||||
// var promises = [];
|
||||
// for(var frame of frames){
|
||||
// if(Debug.debug)
|
||||
// console.log("[Comms:_com_sendToEachFrame] we sending message to tab with id", tabId, ", frame with id", frame.frameId);
|
||||
// try{
|
||||
// promises.push(browser.tabs.sendMessage(tabId, message, {frameId: frame.frameId}));
|
||||
// }
|
||||
// catch(e){
|
||||
// if(Debug.debug)
|
||||
// console.log("[Comms:_com_sendToEachFrame] we sending message to tab with id", tabId, ", frame with id", frame.frameId);
|
||||
// }
|
||||
// }
|
||||
|
||||
// // počakajmo, da so obljube izpolnjene.
|
||||
// // wait for all promises to be kept
|
||||
|
||||
// var responses = [];
|
||||
|
||||
// for(var promise of promises){
|
||||
// var response = await promise;
|
||||
// if(response !== undefined)
|
||||
// responses.push(response);
|
||||
// }
|
||||
|
||||
// if(Debug.debug)
|
||||
// console.log("[Comms::_com_sendToEveryFrame] we received responses from all frames", responses);
|
||||
|
||||
// return responses;
|
||||
// }
|
||||
|
||||
// var _com_sendToMainFrame = async function(message, tabId){
|
||||
// if(Debug.debug)
|
||||
// console.log("[Comms::_com_sendToMainFrame] sending message to every frames of currenntly active tab");
|
||||
|
||||
// if(tabId === undefined){
|
||||
// var tabs = await browser.tabs.query({currentWindow: true, active: true});
|
||||
// tabId = tabs[0].id;
|
||||
// }
|
||||
|
||||
// // pošlji sporočilce glavnemu okvirju. Glavni okvir ima id=0
|
||||
// // send message to the main frame. Main frame has id=0
|
||||
// try{
|
||||
// var response = await browser.tabs.sendMessage(tabId, message, {frameId: 0});
|
||||
// console.log("[Comms::_com_sendToMainFrame] response is this:",response);
|
||||
|
||||
// }
|
||||
// catch(e){
|
||||
// console.log("[Comms:_com_sendToEachFrame] failed sending message to tab with id", tabId, ", frame with id", 0, "\nerror:",e);
|
||||
// }
|
||||
// return response;
|
||||
// }
|
||||
|
||||
// var Comms = {
|
||||
// getActiveTab: _com_getActiveTab,
|
||||
// sendToBackgroundScript: _com_sendMessageRuntime,
|
||||
// queryTabs: _com_queryTabs,
|
||||
// sendMessage: _com_sendMessage,
|
||||
// sendMessageRuntime: _com_sendMessageRuntime,
|
||||
// sendToEach: _com_sendToEachFrame,
|
||||
// sendToAll: _com_sendToAllFrames,
|
||||
// sendToMain: _com_sendToMainFrame,
|
||||
// }
|
||||
|
@ -12,11 +12,12 @@ class EdgeDetect{
|
||||
|
||||
constructor(ardConf){
|
||||
this.conf = ardConf;
|
||||
|
||||
this.sampleWidthBase = ExtensionConf.arDetect.edgeDetection.sampleWidth << 2; // corrected so we can work on imageData
|
||||
this.settings = ardConf.settings;
|
||||
|
||||
this.sampleWidthBase = this.settings.active.arDetect.edgeDetection.sampleWidth << 2; // corrected so we can work on imageData
|
||||
this.halfSample = this.sampleWidthBase >> 1;
|
||||
|
||||
this.detectionTreshold = ExtensionConf.arDetect.edgeDetection.detectionTreshold;
|
||||
this.detectionTreshold = this.settings.active.arDetect.edgeDetection.detectionTreshold;
|
||||
|
||||
this.init(); // initiate things that can change
|
||||
}
|
||||
@ -60,11 +61,11 @@ class EdgeDetect{
|
||||
var res_top = [];
|
||||
var res_bottom = [];
|
||||
|
||||
this.colsTreshold = sampleCols.length * ExtensionConf.arDetect.edgeDetection.minColsForSearch;
|
||||
this.colsTreshold = sampleCols.length * this.settings.active.arDetect.edgeDetection.minColsForSearch;
|
||||
if(this.colsTreshold == 0)
|
||||
this.colsTreshold = 1;
|
||||
|
||||
this.blackbarTreshold = this.conf.blackLevel + ExtensionConf.arDetect.blackbarTreshold;
|
||||
this.blackbarTreshold = this.conf.blackLevel + this.settings.active.arDetect.blackbarTreshold;
|
||||
|
||||
|
||||
// if guardline didn't fail and imageDetect did, we don't have to check the upper few pixels
|
||||
@ -87,14 +88,14 @@ class EdgeDetect{
|
||||
lower_bottom = this.conf.canvas.height - 1;
|
||||
} else {
|
||||
upper_top = 0;
|
||||
upper_bottom = (this.conf.canvas.height >> 1) /*- parseInt(this.conf.canvas.height * ExtensionConf.arDetect.edgeDetection.middleIgnoredArea);*/
|
||||
lower_top = (this.conf.canvas.height >> 1) /*+ parseInt(this.conf.canvas.height * ExtensionConf.arDetect.edgeDetection.middleIgnoredArea);*/
|
||||
upper_bottom = (this.conf.canvas.height >> 1) /*- parseInt(this.conf.canvas.height * this.settings.active.arDetect.edgeDetection.middleIgnoredArea);*/
|
||||
lower_top = (this.conf.canvas.height >> 1) /*+ parseInt(this.conf.canvas.height * this.settings.active.arDetect.edgeDetection.middleIgnoredArea);*/
|
||||
lower_bottom = this.conf.canvas.height - 1;
|
||||
}
|
||||
} else{
|
||||
upper_top = 0;
|
||||
upper_bottom = (this.conf.canvas.height >> 1) /*- parseInt(this.conf.canvas.height * ExtensionConf.arDetect.edgeDetection.middleIgnoredArea);*/
|
||||
lower_top = (this.conf.canvas.height >> 1) /*+ parseInt(this.conf.canvas.height * ExtensionConf.arDetect.edgeDetection.middleIgnoredArea);*/
|
||||
upper_bottom = (this.conf.canvas.height >> 1) /*- parseInt(this.conf.canvas.height * this.settings.active.arDetect.edgeDetection.middleIgnoredArea);*/
|
||||
lower_top = (this.conf.canvas.height >> 1) /*+ parseInt(this.conf.canvas.height * this.settings.active.arDetect.edgeDetection.middleIgnoredArea);*/
|
||||
lower_bottom = this.conf.canvas.height - 1;
|
||||
}
|
||||
|
||||
@ -154,8 +155,8 @@ class EdgeDetect{
|
||||
sampleEnd = this.conf.canvasImageDataRowLength;
|
||||
|
||||
// calculate row offsets for imageData array
|
||||
sampleRow_black = (sample.top - ExtensionConf.arDetect.edgeDetection.edgeTolerancePx) * this.conf.canvasImageDataRowLength;
|
||||
sampleRow_color = (sample.top + 1 + ExtensionConf.arDetect.edgeDetection.edgeTolerancePx) * this.conf.canvasImageDataRowLength;
|
||||
sampleRow_black = (sample.top - this.settings.active.arDetect.edgeDetection.edgeTolerancePx) * this.conf.canvasImageDataRowLength;
|
||||
sampleRow_color = (sample.top + 1 + this.settings.active.arDetect.edgeDetection.edgeTolerancePx) * this.conf.canvasImageDataRowLength;
|
||||
|
||||
// že ena kršitev črnega roba pomeni, da kandidat ni primeren
|
||||
// even a single black edge violation means the candidate is not an edge
|
||||
@ -196,8 +197,8 @@ class EdgeDetect{
|
||||
sampleEnd = this.conf.canvasImageDataRowLength;
|
||||
|
||||
// calculate row offsets for imageData array
|
||||
sampleRow_black = (sample.bottom + ExtensionConf.arDetect.edgeDetection.edgeTolerancePx) * this.conf.canvasImageDataRowLength;
|
||||
sampleRow_color = (sample.bottom - 1 - ExtensionConf.arDetect.edgeDetection.edgeTolerancePx) * this.conf.canvasImageDataRowLength;
|
||||
sampleRow_black = (sample.bottom + this.settings.active.arDetect.edgeDetection.edgeTolerancePx) * this.conf.canvasImageDataRowLength;
|
||||
sampleRow_color = (sample.bottom - 1 - this.settings.active.arDetect.edgeDetection.edgeTolerancePx) * this.conf.canvasImageDataRowLength;
|
||||
|
||||
// že ena kršitev črnega roba pomeni, da kandidat ni primeren
|
||||
// even a single black edge violation means the candidate is not an edge
|
||||
@ -235,7 +236,7 @@ class EdgeDetect{
|
||||
edgePostprocess(edges){
|
||||
var edgesTop = [];
|
||||
var edgesBottom = [];
|
||||
var alignMargin = this.conf.canvas.height * ExtensionConf.arDetect.allowedMisaligned;
|
||||
var alignMargin = this.conf.canvas.height * this.settings.active.arDetect.allowedMisaligned;
|
||||
|
||||
var missingEdge = edges.edgeCandidatesTopCount == 0 || edges.edgeCandidatesBottomCount == 0;
|
||||
|
||||
@ -303,7 +304,7 @@ class EdgeDetect{
|
||||
// it could be watermark. It could be a dark frame. Let's check for watermark first.
|
||||
if( edgesTop[0].distance < edgesBottom[0].distance &&
|
||||
edgesTop[0].count < edgesBottom[0].count &&
|
||||
edgesTop[0].count < GlobalVars.arDetect.sampleCols * ExtensionConf.arDetect.edgeDetection.logoTreshold){
|
||||
edgesTop[0].count < this.conf.sampleCols.length * this.settings.active.arDetect.edgeDetection.logoTreshold){
|
||||
// možno, da je watermark zgoraj. Preverimo, če se kateri od drugih potencialnih robov na zgornjem robu
|
||||
// ujema s prvim spodnjim (+/- variance). Če je temu tako, potem bo verjetno watermark. Logo mora imeti
|
||||
// manj vzorcev kot navaden rob.
|
||||
@ -334,7 +335,7 @@ class EdgeDetect{
|
||||
}
|
||||
if( edgesBottom[0].distance < edgesTop[0].distance &&
|
||||
edgesBottom[0].count < edgesTop[0].count &&
|
||||
edgesBottom[0].count < GlobalVars.arDetect.sampleCols * ExtensionConf.arDetect.edgeDetection.logoTreshold){
|
||||
edgesBottom[0].count <this.conf.sampleCols.length * this.settings.active.arDetect.edgeDetection.logoTreshold){
|
||||
|
||||
if(edgesBottom[0].length > 1){
|
||||
var lowMargin = edgesTop[0].distance - alignMargin;
|
||||
@ -367,7 +368,7 @@ class EdgeDetect{
|
||||
// either the top or the bottom edge remains undetected, but we have one more trick that we
|
||||
// can try. It also tries to work around logos.
|
||||
|
||||
var edgeDetectionTreshold = GlobalVars.arDetect.sampleCols * ExtensionConf.arDetect.edgeDetection.singleSideConfirmationTreshold;
|
||||
var edgeDetectionTreshold = this.conf.sampleCols.length * this.settings.active.arDetect.edgeDetection.singleSideConfirmationTreshold;
|
||||
|
||||
if(edges.edgeCandidatesTopCount == 0 && edges.edgeCandidatesBottomCount != 0){
|
||||
for(var edge of edgesBottom){
|
||||
@ -412,7 +413,7 @@ class EdgeDetect{
|
||||
// we also return true if we detect too much black
|
||||
|
||||
var blackbarTreshold, upper, lower;
|
||||
blackbarTreshold = this.conf.blackLevel + ExtensionConf.arDetect.blackbarTreshold;
|
||||
blackbarTreshold = this.conf.blackLevel + this.settings.active.arDetect.blackbarTreshold;
|
||||
|
||||
|
||||
var middleRowStart = (this.conf.canvas.height >> 1) * this.conf.canvas.width;
|
||||
@ -450,11 +451,11 @@ class EdgeDetect{
|
||||
|
||||
// če sta oba robova v mejah merske napake, potem vrnemo 'false'
|
||||
// if both edges resemble rounding error, we retunr 'false'
|
||||
if(edge_left < ExtensionConf.arDetect.pillarTest.ignoreThinPillarsPx && edge_right < ExtensionConf.arDetect.pillarTest.ignoreThinPillarsPx){
|
||||
if(edge_left < this.settings.active.arDetect.pillarTest.ignoreThinPillarsPx && edge_right < this.settings.active.arDetect.pillarTest.ignoreThinPillarsPx){
|
||||
return false;
|
||||
}
|
||||
|
||||
var edgeError = ExtensionConf.arDetect.pillarTest.allowMisaligned;
|
||||
var edgeError = this.settings.active.arDetect.pillarTest.allowMisaligned;
|
||||
var error_low = 1 - edgeError;
|
||||
var error_hi = 1 + edgeError;
|
||||
|
||||
|
@ -6,6 +6,7 @@ class GuardLine {
|
||||
this.imageBar = {top: undefined, bottom: undefined};
|
||||
|
||||
this.conf = ardConf;
|
||||
this.settings = ardConf.settings;
|
||||
}
|
||||
|
||||
reset() {
|
||||
@ -25,8 +26,8 @@ class GuardLine {
|
||||
}
|
||||
|
||||
setBlackbar(bbconf){
|
||||
var bbTop = bbconf.top - ExtensionConf.arDetect.guardLine.edgeTolerancePx;
|
||||
var bbBottom = bbconf.bottom + ExtensionConf.arDetect.guardLine.edgeTolerancePx;
|
||||
var bbTop = bbconf.top - this.settings.active.arDetect.guardLine.edgeTolerancePx;
|
||||
var bbBottom = bbconf.bottom + this.settings.active.arDetect.guardLine.edgeTolerancePx;
|
||||
|
||||
// to odstrani vse neveljavne nastavitve in vse možnosti, ki niso smiselne
|
||||
// this removes any configs with invalid values or values that dont make sense
|
||||
@ -42,15 +43,15 @@ class GuardLine {
|
||||
}
|
||||
|
||||
this.imageBar = {
|
||||
top: bbconf.top + 1 + ExtensionConf.arDetect.guardLine.edgeTolerancePx,
|
||||
bottom: bbconf.bottom - 1 - ExtensionConf.arDetect.guardLine.edgeTolerancePx
|
||||
top: bbconf.top + 1 + this.settings.active.arDetect.guardLine.edgeTolerancePx,
|
||||
bottom: bbconf.bottom - 1 - this.settings.active.arDetect.guardLine.edgeTolerancePx
|
||||
}
|
||||
}
|
||||
|
||||
check(image, fallbackMode){
|
||||
// izračunaj enkrat in shrani na objekt
|
||||
// calculate once and save object-instance-wide
|
||||
this.blackbarTreshold = this.conf.blackLevel + ExtensionConf.arDetect.blackbarTreshold;
|
||||
this.blackbarTreshold = this.conf.blackLevel + this.settings.active.arDetect.blackbarTreshold;
|
||||
|
||||
// dejansko testiranje
|
||||
// actual checks
|
||||
@ -94,7 +95,7 @@ class GuardLine {
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
var offset = parseInt(this.conf.canvas.width * ExtensionConf.arDetect.guardLine.ignoreEdgeMargin) << 2;
|
||||
var offset = parseInt(this.conf.canvas.width * this.settings.active.arDetect.guardLine.ignoreEdgeMargin) << 2;
|
||||
|
||||
var offenders = [];
|
||||
var firstOffender = -1;
|
||||
@ -159,11 +160,8 @@ class GuardLine {
|
||||
imageCheck(image){
|
||||
if(!this.imageBar.top || !this.imageBar.bottom)
|
||||
return { success: false };
|
||||
|
||||
|
||||
var edges = GlobalVars.arDetect.guardLine;
|
||||
|
||||
var offset = parseInt(this.conf.canvas.width * ExtensionConf.arDetect.guardLine.ignoreEdgeMargin) << 2;
|
||||
|
||||
var offset = parseInt(this.conf.canvas.width * this.settings.active.arDetect.guardLine.ignoreEdgeMargin) << 2;
|
||||
|
||||
// TODO: implement logo check.
|
||||
|
||||
@ -172,8 +170,8 @@ class GuardLine {
|
||||
// check both rows - by the rules and definitions, we shouldn't go out of bounds here. no need to check, then
|
||||
|
||||
// if(fallbackMode){
|
||||
// var edge_upper = ExtensionConf.arDetect.fallbackMode.noTriggerZonePx;
|
||||
// var edge_lower = this.conf.canvas.height - ExtensionConf.arDetect.fallbackMode.noTriggerZonePx - 1;
|
||||
// var edge_upper = this.settings.active.arDetect.fallbackMode.noTriggerZonePx;
|
||||
// var edge_lower = this.conf.canvas.height - this.settings.active.arDetect.fallbackMode.noTriggerZonePx - 1;
|
||||
// }
|
||||
// else{
|
||||
var edge_upper = this.imageBar.top;
|
||||
@ -184,7 +182,7 @@ class GuardLine {
|
||||
// robu (eden izmed robov je lahko v celoti črn)
|
||||
// how many non-black pixels we need to consider this check a success. We only need to detect enough pixels
|
||||
// on one edge (one of the edges can be black as long as both aren't)
|
||||
var successTreshold = parseInt(this.conf.canvas.width * ExtensionConf.arDetect.guardLine.imageTestTreshold);
|
||||
var successTreshold = parseInt(this.conf.canvas.width * this.settings.active.arDetect.guardLine.imageTestTreshold);
|
||||
var rowStart, rowEnd;
|
||||
|
||||
|
||||
|
43
js/lib/ObjectCopy.js
Normal file
43
js/lib/ObjectCopy.js
Normal file
@ -0,0 +1,43 @@
|
||||
class ObjectCopy {
|
||||
static addNew(existing, target){
|
||||
|
||||
// clone target
|
||||
var out = JSON.parse(JSON.stringify(target));
|
||||
|
||||
if(! existing) {
|
||||
if(Debug.debug) {
|
||||
console.log("[ObjectCopy::addNew] There's no existing value. Returning target value.");
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
for(var k in out) {
|
||||
// if current key exist, replace it with existing value. Take no action otherwise.
|
||||
if(existing[k]) {
|
||||
|
||||
// Types and constructors of objects must match. If they don't, we always use the new value.
|
||||
if(typeof out[k] === typeof existing[k] && out[k].constructor === existing[k].constructor) {
|
||||
|
||||
// objects are special, we need to check them recursively.
|
||||
if(out[k] && typeof out[k] === 'object' && out[k].constructor === Object ) {
|
||||
if(Debug.debug && Debug.settings) {
|
||||
console.log("[ObjectCopy::addNew] current key contains an object. Recursing!")
|
||||
}
|
||||
|
||||
out[k] = this.addNew(existing[k], out[k]);
|
||||
} else {
|
||||
out[k] = existing[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static pruneUnused(existing, target, ignoreKeys) {
|
||||
// TODO: implement at some other date
|
||||
// existing: object that we have.
|
||||
// target: object that we want
|
||||
// ignoreKeys: if key is an object, we don't recursively call this function on that key
|
||||
}
|
||||
}
|
262
js/lib/Settings.js
Normal file
262
js/lib/Settings.js
Normal file
@ -0,0 +1,262 @@
|
||||
class Settings {
|
||||
|
||||
constructor(activeSettings, updateCallback) {
|
||||
this.active = activeSettings ? activeSettings : undefined;
|
||||
this.default = ExtensionConf;
|
||||
this.useSync = false;
|
||||
this.version = undefined;
|
||||
this.updateCallback = updateCallback;
|
||||
|
||||
const ths = this;
|
||||
|
||||
if(BrowserDetect.firefox) {
|
||||
browser.storage.onChanged.addListener( (changes, area) => {
|
||||
if (Debug.debug && Debug.debugStorage) {
|
||||
console.log("[Settings::<storage/on change>] Settings have been changed outside of here. Updating active settings. Changes:", changes, "storage area:", area);
|
||||
if (changes['uwSettings'] && changes['uwSettings'].newValue) {
|
||||
console.log("[Settings::<storage/on change>] new settings object:", JSON.parse(changes.uwSettings.newValue));
|
||||
}
|
||||
}
|
||||
if(changes['uwSettings'] && changes['uwSettings'].newValue) {
|
||||
ths.active = JSON.parse(changes.uwSettings.newValue);
|
||||
}
|
||||
|
||||
if(this.updateCallback) {
|
||||
try {
|
||||
updateCallback();
|
||||
} catch (e) {
|
||||
console.log("[Settings] CALLING UPDATE CALLBACK FAILED.")
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (BrowserDetect.chrome) {
|
||||
chrome.storage.onChanged.addListener( (changes, area) => {
|
||||
if (Debug.debug && Debug.debugStorage) {
|
||||
console.log("[Settings::<storage/on change>] Settings have been changed outside of here. Updating active settings. Changes:", changes, "storage area:", area);
|
||||
if (changes['uwSettings'] && changes['uwSettings'].newValue) {
|
||||
console.log("[Settings::<storage/on change>] new settings object:", JSON.parse(changes.uwSettings.newValue));
|
||||
}
|
||||
}
|
||||
if(changes['uwSettings'] && changes['uwSettings'].newValue) {
|
||||
ths.active = JSON.parse(changes.uwSettings.newValue);
|
||||
}
|
||||
|
||||
if(this.updateCallback) {
|
||||
try {
|
||||
updateCallback();
|
||||
} catch (e) {
|
||||
console.log("[Settings] CALLING UPDATE CALLBACK FAILED.")
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async init() {
|
||||
const settings = await this.get();
|
||||
|
||||
if(Debug.debug) {
|
||||
console.log("[Settings::init] Configuration fetched from storage:", settings);
|
||||
}
|
||||
|
||||
// if there's no settings saved, return default settings.
|
||||
if(! settings || (Object.keys(settings).length === 0 && settings.constructor === Object)) {
|
||||
this.setDefaultSettings();
|
||||
this.active = this.getDefaultSettings();
|
||||
return this.active;
|
||||
}
|
||||
|
||||
// if there's settings, set saved object as active settings
|
||||
this.active = settings;
|
||||
|
||||
// check if extension has been updated. If not, return settings as they were retreived
|
||||
if (BrowserDetect.firefox) {
|
||||
this.version = browser.runtime.getManifest().version;
|
||||
} else if (BrowserDetect.chrome) {
|
||||
this.version = chrome.runtime.getManifest().version;
|
||||
} else if (BrowserDetect.edge) {
|
||||
this.version = browser.runtime.getManifest().version;
|
||||
}
|
||||
|
||||
if(settings.version === this.version) {
|
||||
if(Debug.debug) {
|
||||
console.log("[Settings::init] extension was saved with current version of ultrawidify (", this.version, "). Returning object as-is.");
|
||||
}
|
||||
return this.active;
|
||||
}
|
||||
|
||||
// if extension has been updated, update existing settings with any options added in the
|
||||
// new version. In addition to that, we remove old keys that are no longer used.
|
||||
const patched = ObjectCopy.addNew(settings, this.default);
|
||||
if(Debug.debug) {
|
||||
console.log("[Settings.init] Results from ObjectCopy.addNew()?", patched, "\n\nSettings from storage", settings, "\ndefault?", this.default,);
|
||||
}
|
||||
|
||||
if(patched){
|
||||
this.active = patched;
|
||||
} else {
|
||||
this.active = JSON.parse(JSON.stringify(this.default));
|
||||
}
|
||||
|
||||
this.set(this.active);
|
||||
return this.active;
|
||||
}
|
||||
|
||||
async get() {
|
||||
if (BrowserDetect.firefox || BrowserDetect.edge) {
|
||||
const ret = this.useSync ? await browser.storage.sync.get('uwSettings') : await browser.storage.local.get('uwSettings');
|
||||
try {
|
||||
return JSON.parse(ret.uwSettings);
|
||||
} catch(e) {
|
||||
return undefined;
|
||||
}
|
||||
} else if (BrowserDetect.chrome) {
|
||||
const ret = new Promise( (resolve, reject) => {
|
||||
chrome.storage.sync.get('uwSettings', (res) => resolve(res));
|
||||
});
|
||||
return ret['uwSettings'];
|
||||
}
|
||||
}
|
||||
|
||||
async set(extensionConf) {
|
||||
if (Debug.debug) {
|
||||
console.log("[Settings::set] setting new settings:", extensionConf)
|
||||
}
|
||||
|
||||
if (BrowserDetect.firefox || BrowserDetect.edge) {
|
||||
extensionConf.version = this.version;
|
||||
return this.useSync ? browser.storage.sync.set( {'uwSettings': JSON.stringify(extensionConf)}): browser.storage.local.set( {'uwSettings': JSON.stringify(extensionConf)});
|
||||
} else if (BrowserDetect.chrome) {
|
||||
return chrome.storage.sync.set( {'uwSettings': JSON.stringify(extensionConf)});
|
||||
}
|
||||
}
|
||||
|
||||
async setActive(activeSettings) {
|
||||
this.active = activeSettings;
|
||||
}
|
||||
|
||||
async setProp(prop, value) {
|
||||
this.active[prop] = value;
|
||||
}
|
||||
|
||||
async save() {
|
||||
if (Debug.debug) {
|
||||
console.log("[Settings::save] Saving active settings:", this.active);
|
||||
}
|
||||
|
||||
this.set(this.active);
|
||||
}
|
||||
|
||||
getDefaultSettings() {
|
||||
return JSON.parse(JSON.stringify(this.default));
|
||||
}
|
||||
|
||||
setDefaultSettings() {
|
||||
this.set(this.default);
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
// Nastavitve za posamezno stran
|
||||
// Config for a given page:
|
||||
//
|
||||
// <hostname> : {
|
||||
// status: <option> // should extension work on this site?
|
||||
// arStatus: <option> // should we do autodetection on this site?
|
||||
// statusEmbedded: <option> // reserved for future... maybe
|
||||
// }
|
||||
//
|
||||
// Veljavne vrednosti za možnosti
|
||||
// Valid values for options:
|
||||
//
|
||||
// status, arStatus, statusEmbedded:
|
||||
//
|
||||
// * enabled — always allow
|
||||
// * default — allow if default is to allow, block if default is to block
|
||||
// * disabled — never allow
|
||||
|
||||
canStartExtension(site) {
|
||||
// returns 'true' if extension can be started on a given site. Returns false if we shouldn't run.
|
||||
if (!site) {
|
||||
site = window.location.hostname;
|
||||
|
||||
if (!site) {
|
||||
console.log("[Settings::canStartExtension] window.location.hostname is null or undefined:", window.location.hostname)
|
||||
console.log("active settings:", this.active)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (Debug.debug) {
|
||||
// let's just temporarily disable debugging while recursively calling
|
||||
// this function to get extension status on current site without duplo
|
||||
// console logs (and without endless recursion)
|
||||
Debug.debug = false;
|
||||
const cse = this.canStartExtension(site);
|
||||
Debug.debug = true;
|
||||
|
||||
// console.log("[Settings::canStartExtension] ----------------\nCAN WE START THIS EXTENSION ON SITE", site,
|
||||
// "?\n\nsettings.active.sites[site]=", this.active.sites[site],
|
||||
// "\nExtension mode?", this.active.extensionMode,
|
||||
// "\nCan extension be started?", cse
|
||||
// );
|
||||
}
|
||||
try{
|
||||
// if site is not defined, we use default mode:
|
||||
if (! this.active.sites[site]) {
|
||||
return this.active.extensionMode === "blacklist";
|
||||
}
|
||||
|
||||
if(this.active.extensionMode === "blacklist") {
|
||||
return this.active.sites[site].status !== "disabled";
|
||||
} else if (this.active.extensionMode === "whitelist") {
|
||||
return this.active.sites[site].status === "enabled";
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}catch(e){
|
||||
if(Debug.debug){
|
||||
console.log("[Settings.js::canStartExtension] Something went wrong — are settings defined/has init() been called?\nSettings object:", this)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
canStartAutoAr(site) {
|
||||
if (!site) {
|
||||
site = window.location.hostname;
|
||||
|
||||
if (!site) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (Debug.debug) {
|
||||
// let's just temporarily disable debugging while recursively calling
|
||||
// this function to get extension status on current site without duplo
|
||||
// console logs (and without endless recursion)
|
||||
Debug.debug = false;
|
||||
const csar = this.canStartAutoAr(site);
|
||||
Debug.debug = true;
|
||||
|
||||
console.log("[Settings::canStartAutoAr] ----------------\nCAN WE START THIS EXTENSION ON SITE", site,
|
||||
"?\n\nsettings.active.sites[site]=", this.active.sites[site],
|
||||
"\nExtension mode?", this.active.arDetect.mode,
|
||||
"\nCan extension be started?", csar
|
||||
);
|
||||
}
|
||||
|
||||
// if site is not defined, we use default mode:
|
||||
if (! this.active.sites[site]) {
|
||||
return this.active.arDetect.mode === "blacklist";
|
||||
}
|
||||
|
||||
if (this.active.arDetect.mode === "blacklist") {
|
||||
return this.active.sites[site].arStatus !== "disabled";
|
||||
} else if (this.active.arDetect.mode === "whitelist") {
|
||||
return this.active.sites[site].arStatus === "enabled";
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
// setopt, getopt, delopt. Shrani oz. dobi oz. briše stvari iz skladišča
|
||||
// setopt, getopt, delopt. They set/get/delete stuff from the storage
|
||||
|
||||
var _sm_setopt = function(item){
|
||||
return browser.storage.local.set(item);
|
||||
}
|
||||
var _sm_getopt = function(prop, callback){
|
||||
if(BrowserDetect.usebrowser == "chrome")
|
||||
return browser.storage.local.get(prop, callback);
|
||||
else
|
||||
return browser.storage.local.get(prop).then(callback);
|
||||
}
|
||||
|
||||
var _sm_chrome_getopt_wrapper = async function(prop){
|
||||
return new Promise(function (resolve, reject){
|
||||
browser.storage.local.get(prop, function(response){
|
||||
resolve(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var _sm_getopt_async = async function(prop){
|
||||
if(Debug.debug && Debug.debugStorage)
|
||||
console.log("[StorageManager::_sm_getopt_async] requesting prop",prop,"from localStorage.");
|
||||
|
||||
if(BrowserDetect.usebrowser == "chrome"){
|
||||
var ret = await _sm_chrome_getopt_wrapper(prop);
|
||||
return ret;
|
||||
}
|
||||
else{
|
||||
var ret = await browser.storage.local.get(prop);
|
||||
|
||||
if(Debug.debug && Debug.debugStorage)
|
||||
console.log("[StorageManager::_sm_getopt_async] got prop", prop, "; value: ", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
var _sm_delopt = function(item){
|
||||
return browser.storage.local.remove(item);
|
||||
}
|
||||
|
||||
var StorageManager = {
|
||||
setopt: _sm_setopt,
|
||||
getopt: _sm_getopt,
|
||||
delopt: _sm_delopt,
|
||||
getopt_async: _sm_getopt_async
|
||||
}
|
0
js/lib/UiFactory.js
Normal file
0
js/lib/UiFactory.js
Normal file
@ -1,10 +1,10 @@
|
||||
class VideoData {
|
||||
|
||||
constructor(video){
|
||||
constructor(video, settings){
|
||||
this.arSetupComplete = false;
|
||||
this.video = video;
|
||||
this.destroyed = false;
|
||||
|
||||
this.settings = settings;
|
||||
// POZOR: VRSTNI RED JE POMEMBEN (arDetect mora bit zadnji)
|
||||
// NOTE: ORDERING OF OBJ INITIALIZATIONS IS IMPORTANT (arDetect needs to go last)
|
||||
this.player = new PlayerData(this);
|
||||
@ -40,6 +40,10 @@ class VideoData {
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if(Debug.debug){
|
||||
console.log("[VideoData::destroy] received destroy command");
|
||||
}
|
||||
|
||||
this.destroyed = true;
|
||||
if(this.arDetector){
|
||||
this.arDetector.stop();
|
||||
@ -49,9 +53,11 @@ class VideoData {
|
||||
if(this.resizer){
|
||||
this.resizer.destroy();
|
||||
}
|
||||
this.resizer = null;
|
||||
if(this.player){
|
||||
player.destroy();
|
||||
this.player.destroy();
|
||||
}
|
||||
this.player = null;
|
||||
this.video = null;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ class ArDetector {
|
||||
constructor(videoData){
|
||||
this.conf = videoData;
|
||||
this.video = videoData.video;
|
||||
this.settings = videoData.settings;
|
||||
|
||||
this.setupTimer = null;
|
||||
this.timer = null;
|
||||
@ -13,14 +14,14 @@ class ArDetector {
|
||||
this.canFallback = true;
|
||||
this.fallbackMode = false;
|
||||
|
||||
this.blackLevel = ExtensionConf.arDetect.blackLevel_default;
|
||||
this.blackLevel = this.settings.active.arDetect.blackLevel_default;
|
||||
}
|
||||
|
||||
init(){
|
||||
if(Debug.debug){
|
||||
console.log("[ArDetect::init] Initializing autodetection")
|
||||
}
|
||||
this.setup(ExtensionConf.arDetect.hSamples, ExtensionConf.arDetect.vSamples);
|
||||
this.setup(this.settings.active.arDetect.hSamples, this.settings.active.arDetect.vSamples);
|
||||
}
|
||||
|
||||
destroy(){
|
||||
@ -37,7 +38,7 @@ class ArDetector {
|
||||
console.log("[ArDetect::setup] Starting autodetection setup");
|
||||
}
|
||||
|
||||
if (this.fallbackMode || cheight !== ExtensionConf.arDetect.hSamples) {
|
||||
if (this.fallbackMode || cheight !== this.settings.active.arDetect.hSamples) {
|
||||
if(Debug.debug) {
|
||||
console.log("%c[ArDetect::setup] WARNING: CANVAS RESET DETECTED - recalculating guardLine", "background: #000; color: #ff2" )
|
||||
}
|
||||
@ -46,8 +47,8 @@ class ArDetector {
|
||||
}
|
||||
|
||||
if(!cwidth){
|
||||
cwidth = ExtensionConf.arDetect.hSamples;
|
||||
cheight = ExtensionConf.arDetect.vSamples;
|
||||
cwidth = this.settings.active.arDetect.hSamples;
|
||||
cheight = this.settings.active.arDetect.vSamples;
|
||||
}
|
||||
|
||||
|
||||
@ -63,8 +64,8 @@ class ArDetector {
|
||||
// // let's insert initial columns to this.sampleCols - NO!!! do it later dow
|
||||
// this.sampleCols = [];
|
||||
|
||||
// var samplingIntervalPx = parseInt(cheight / ExtensionConf.arDetect.samplingInterval)
|
||||
// for(var i = 1; i < ExtensionConf.arDetect.samplingInterval; i++){
|
||||
// var samplingIntervalPx = parseInt(cheight / this.settings.active.arDetect.samplingInterval)
|
||||
// for(var i = 1; i < this.settings.active.arDetect.samplingInterval; i++){
|
||||
// this.sampleCols.push(i * samplingIntervalPx);
|
||||
// }
|
||||
|
||||
@ -105,8 +106,8 @@ class ArDetector {
|
||||
|
||||
try{
|
||||
// determine where to sample
|
||||
var ncol = ExtensionConf.arDetect.staticSampleCols;
|
||||
var nrow = ExtensionConf.arDetect.staticSampleRows;
|
||||
var ncol = this.settings.active.arDetect.staticSampleCols;
|
||||
var nrow = this.settings.active.arDetect.staticSampleRows;
|
||||
|
||||
var colSpacing = this.canvas.width / ncol;
|
||||
var rowSpacing = (this.canvas.height << 2) / nrow;
|
||||
@ -131,7 +132,7 @@ class ArDetector {
|
||||
}
|
||||
}
|
||||
catch(ex){
|
||||
console.log("%c[ArDetect::_arSetup] something went terribly wrong when calcuating sample colums.", ExtensionConf.colors.criticalFail);
|
||||
console.log("%c[ArDetect::_arSetup] something went terribly wrong when calcuating sample colums.", this.settings.active.colors.criticalFail);
|
||||
console.log("settings object:", Settings);
|
||||
console.log("error:", ex);
|
||||
}
|
||||
@ -149,7 +150,7 @@ class ArDetector {
|
||||
this.canvasImageDataRowLength = cwidth << 2;
|
||||
this.noLetterboxCanvasReset = false;
|
||||
|
||||
if(forceStart || canStartAutoAr() ) {
|
||||
if(forceStart || this.settings.canStartAutoAr() ) {
|
||||
this.start();
|
||||
}
|
||||
}
|
||||
@ -227,12 +228,13 @@ class ArDetector {
|
||||
);
|
||||
}
|
||||
|
||||
scheduleFrameCheck(timeout, force_reset){
|
||||
async scheduleFrameCheck(timeout, force_reset){
|
||||
if(! timeout){
|
||||
this.frameCheck();
|
||||
return;
|
||||
}
|
||||
|
||||
var e = await this.settings.get();
|
||||
// run anything that needs to be run after frame check
|
||||
this.postFrameCheck();
|
||||
|
||||
@ -293,14 +295,14 @@ class ArDetector {
|
||||
getTimeout(baseTimeout, startTime){
|
||||
var execTime = (performance.now() - startTime);
|
||||
|
||||
if( execTime > ExtensionConf.arDetect.autoDisable.maxExecutionTime ){
|
||||
if( execTime > this.settings.active.arDetect.autoDisable.maxExecutionTime ){
|
||||
// this.detectionTimeoutEventCount++;
|
||||
|
||||
if(Debug.debug){
|
||||
console.log("[ArDetect::getTimeout] Exec time exceeded maximum allowed execution time. This has now happened " + this.detectionTimeoutEventCount + " times in a row.");
|
||||
}
|
||||
|
||||
// if( this.detectionTimeoutEventCount >= ExtensionConf.arDetect.autoDisable.consecutiveTimeoutCount ){
|
||||
// if( this.detectionTimeoutEventCount >= this.settings.active.arDetect.autoDisable.consecutiveTimeoutCount ){
|
||||
// if (Debug.debug){
|
||||
// console.log("[ArDetect::getTimeout] Maximum execution time was exceeded too many times. Automatic aspect ratio detection has been disabled.");
|
||||
// }
|
||||
@ -313,7 +315,7 @@ class ArDetector {
|
||||
} else {
|
||||
this.detectionTimeoutEventCount = 0;
|
||||
}
|
||||
// return baseTimeout > ExtensionConf.arDetect.minimumTimeout ? baseTimeout : ExtensionConf.arDetect.minimumTimeout;
|
||||
// return baseTimeout > this.settings.active.arDetect.minimumTimeout ? baseTimeout : this.settings.active.arDetect.minimumTimeout;
|
||||
|
||||
return baseTimeout;
|
||||
}
|
||||
@ -347,7 +349,7 @@ class ArDetector {
|
||||
var trueHeight = this.canvas.height * zoomFactor - letterbox;
|
||||
|
||||
if(this.fallbackMode){
|
||||
if(edges.top > 1 && edges.top <= ExtensionConf.arDetect.fallbackMode.noTriggerZonePx ){
|
||||
if(edges.top > 1 && edges.top <= this.settings.active.arDetect.fallbackMode.noTriggerZonePx ){
|
||||
if(Debug.debug && Debug.debugArDetect) {
|
||||
console.log("Edge is in the no-trigger zone. Aspect ratio change is not triggered.")
|
||||
}
|
||||
@ -358,7 +360,7 @@ class ArDetector {
|
||||
// x2, ker je safetyBorderPx definiran za eno stran.
|
||||
// safety border so we can detect aspect ratio narrowing (21:9 -> 16:9).
|
||||
// x2 because safetyBorderPx is for one side.
|
||||
trueHeight += (ExtensionConf.arDetect.fallbackMode.safetyBorderPx << 1);
|
||||
trueHeight += (this.settings.active.arDetect.fallbackMode.safetyBorderPx << 1);
|
||||
}
|
||||
|
||||
|
||||
@ -390,7 +392,7 @@ class ArDetector {
|
||||
if(Debug.debug && Debug.debugArDetect)
|
||||
console.log("%c[ArDetect::_ard_processAr] new aspect ratio varies from the old one by this much:\n","color: #aaf","old Ar", lastAr.ar, "current ar", trueAr, "arDiff (absolute):",arDiff,"ar diff (relative to new ar)", arDiff_percent);
|
||||
|
||||
if (arDiff < trueAr * ExtensionConf.arDetect.allowedArVariance){
|
||||
if (arDiff < trueAr * this.settings.active.arDetect.allowedArVariance){
|
||||
if(Debug.debug && Debug.debugArDetect)
|
||||
console.log("%c[ArDetect::_ard_processAr] aspect ratio change denied — diff %:", "background: #740; color: #fa2", arDiff_percent)
|
||||
|
||||
@ -424,7 +426,7 @@ class ArDetector {
|
||||
|
||||
var fallbackMode = false;
|
||||
var startTime = performance.now();
|
||||
var baseTimeout = ExtensionConf.arDetect.timer_playing;
|
||||
var baseTimeout = this.settings.active.arDetect.timer_playing;
|
||||
var triggerTimeout;
|
||||
|
||||
var guardLineResult = true; // true if success, false if fail. true by default
|
||||
@ -438,14 +440,14 @@ class ArDetector {
|
||||
if(this.video.ended ){
|
||||
// we slow down if ended. Detecting is pointless.
|
||||
|
||||
this.scheduleFrameCheck(ExtensionConf.arDetect.timer_paused);
|
||||
this.scheduleFrameCheck(this.settings.active.arDetect.timer_paused);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(this.video.paused){
|
||||
// če je video pavziran, še vedno skušamo zaznati razmerje stranic - ampak bolj poredko.
|
||||
// if the video is paused, we still do autodetection. We just do it less often.
|
||||
baseTimeout = ExtensionConf.arDetect.timer_paused;
|
||||
baseTimeout = this.settings.active.arDetect.timer_paused;
|
||||
}
|
||||
|
||||
try{
|
||||
@ -457,7 +459,7 @@ class ArDetector {
|
||||
}
|
||||
|
||||
try{
|
||||
if(! ExtensionConf.arDetect.fallbackMode.enabled)
|
||||
if(! this.settings.active.arDetect.fallbackMode.enabled)
|
||||
throw "fallbackMode is disabled.";
|
||||
|
||||
if(this.canvasReadyForDrawWindow()){
|
||||
@ -474,9 +476,9 @@ class ArDetector {
|
||||
var newCanvasWidth = window.innerHeight * (this.video.videoWidth / this.video.videoHeight);
|
||||
var newCanvasHeight = window.innerHeight;
|
||||
|
||||
if(ExtensionConf.miscFullscreenSettings.videoFloat == "center")
|
||||
if(this.settings.active.miscFullscreenSettings.videoFloat == "center")
|
||||
this.canvasDrawWindowHOffset = Math.round((window.innerWidth - newCanvasWidth) * 0.5);
|
||||
else if(ExtensionConf.miscFullscreenSettings.videFloat == "left")
|
||||
else if(this.settings.active.miscFullscreenSettings.videFloat == "left")
|
||||
this.canvasDrawWindowHOffset = 0;
|
||||
else
|
||||
this.canvasDrawWindowHOffset = window.innerWidth - newCanvasWidth;
|
||||
@ -491,7 +493,7 @@ class ArDetector {
|
||||
if(Debug.debug)
|
||||
console.log("%c[ArDetect::_ard_vdraw] okay this didnt work either", "color:#000; backgroud:#f51;", ex);
|
||||
|
||||
this.scheduleFrameCheck( ExtensionConf.arDetect.timer_error );
|
||||
this.scheduleFrameCheck( this.settings.active.arDetect.timer_error );
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -573,14 +575,14 @@ class ArDetector {
|
||||
//#endregion
|
||||
|
||||
// this means we don't have letterbox
|
||||
if ( currentMaxVal > (this.blackLevel + ExtensionConf.arDetect.blackbarTreshold) || (currentMaxVal - currentMinVal) > ExtensionConf.arDetect.blackbarTreshold*4 ){
|
||||
if ( currentMaxVal > (this.blackLevel + this.settings.active.arDetect.blackbarTreshold) || (currentMaxVal - currentMinVal) > this.settings.active.arDetect.blackbarTreshold*4 ){
|
||||
|
||||
// Če ne zaznamo letterboxa, kličemo reset. Lahko, da je bilo razmerje stranic popravljeno na roke. Možno je tudi,
|
||||
// da je letterbox izginil.
|
||||
// If we don't detect letterbox, we reset aspect ratio to aspect ratio of the video file. The aspect ratio could
|
||||
// have been corrected manually. It's also possible that letterbox (that was there before) disappeared.
|
||||
if(Debug.debug && Debug.debugArDetect){
|
||||
console.log(`%c[ArDetect::_ard_vdraw] ---- NO EDGE DETECTED! — canvas has no edge. ----\ncurrentMaxVal: ${currentMaxVal}\nBlack level (+ treshold):${this.blackLevel} (${this.blackLevel + ExtensionConf.arDetect.blackbarTreshold})\n---diff test---\nmaxVal-minVal: ${ (currentMaxVal - currentMinVal)}\ntreshold: ${ExtensionConf.arDetect.blackbarTreshold}`, "color: #aaf");
|
||||
console.log(`%c[ArDetect::_ard_vdraw] ---- NO EDGE DETECTED! — canvas has no edge. ----\ncurrentMaxVal: ${currentMaxVal}\nBlack level (+ treshold):${this.blackLevel} (${this.blackLevel + this.settings.active.arDetect.blackbarTreshold})\n---diff test---\nmaxVal-minVal: ${ (currentMaxVal - currentMinVal)}\ntreshold: ${this.settings.active.arDetect.blackbarTreshold}`, "color: #aaf");
|
||||
}
|
||||
|
||||
// Pogledamo, ali smo že kdaj ponastavili CSS. Če še nismo, potem to storimo. Če smo že, potem ne.
|
||||
@ -600,7 +602,7 @@ class ArDetector {
|
||||
}
|
||||
|
||||
if(Debug.debug && Debug.debugArDetect){
|
||||
console.log(`%c[ArDetect::_ard_vdraw] edge was detected. Here are stats:\ncurrentMaxVal: ${currentMaxVal}\nBlack level (+ treshold):${this.blackLevel} (${this.blackLevel + ExtensionConf.arDetect.blackbarTreshold})\n---diff test---\nmaxVal-minVal: ${ (currentMaxVal - currentMinVal)}\ntreshold: ${ExtensionConf.arDetect.blackbarTreshold}`, "color: #afa");
|
||||
console.log(`%c[ArDetect::_ard_vdraw] edge was detected. Here are stats:\ncurrentMaxVal: ${currentMaxVal}\nBlack level (+ treshold):${this.blackLevel} (${this.blackLevel + this.settings.active.arDetect.blackbarTreshold})\n---diff test---\nmaxVal-minVal: ${ (currentMaxVal - currentMinVal)}\ntreshold: ${this.settings.active.arDetect.blackbarTreshold}`, "color: #afa");
|
||||
}
|
||||
|
||||
// Če preverjamo naprej, potem moramo postaviti to vrednost nazaj na 'false'. V nasprotnem primeru se bo
|
||||
@ -694,7 +696,7 @@ class ArDetector {
|
||||
if(Debug.debug && Debug.debugArDetect){
|
||||
console.log(`%c[ArDetect::_ard_vdraw] edgeDetector returned this\n`, "color: #aaf", edgePost);
|
||||
}
|
||||
// console.log("SAMPLES:", blackbarSamples, "candidates:", edgeCandidates, "post:", edgePost,"\n\nblack level:",GlobalVars.arDetect.blackLevel, "tresh:", this.blackLevel + ExtensionConf.arDetect.blackbarTreshold);
|
||||
// console.log("SAMPLES:", blackbarSamples, "candidates:", edgeCandidates, "post:", edgePost,"\n\nblack level:", this.blackLevel, "tresh:", this.blackLevel + this.settings.active.arDetect.blackbarTreshold);
|
||||
|
||||
if(edgePost.status == "ar_known"){
|
||||
|
||||
@ -705,11 +707,11 @@ class ArDetector {
|
||||
// var textEdge = false;;
|
||||
|
||||
// if(edgePost.guardLineTop != null){
|
||||
// var row = edgePost.guardLineTop + ~~(this.canvas.height * ExtensionConf.arDetect.textLineTest.testRowOffset);
|
||||
// var row = edgePost.guardLineTop + ~~(this.canvas.height * this.settings.active.arDetect.textLineTest.testRowOffset);
|
||||
// textEdge |= textLineTest(image, row);
|
||||
// }
|
||||
// if(edgePost.guardLineTop != null){
|
||||
// var row = edgePost.guardLineTop - ~~(this.canvas.height * ExtensionConf.arDetect.textLineTest.testRowOffset);
|
||||
// var row = edgePost.guardLineTop - ~~(this.canvas.height * this.settings.active.arDetect.textLineTest.testRowOffset);
|
||||
// textEdge |= textLineTest(image, row);
|
||||
// }
|
||||
|
||||
@ -746,11 +748,11 @@ class ArDetector {
|
||||
} else {
|
||||
if (this.conf.player.dimensions){
|
||||
this.guardLine.setBlackbarManual({
|
||||
top: ExtensionConf.arDetect.fallbackMode.noTriggerZonePx,
|
||||
bottom: this.conf.player.dimensions.height - ExtensionConf.arDetect.fallbackMode.noTriggerZonePx - 1
|
||||
top: this.settings.active.arDetect.fallbackMode.noTriggerZonePx,
|
||||
bottom: this.conf.player.dimensions.height - this.settings.active.arDetect.fallbackMode.noTriggerZonePx - 1
|
||||
},{
|
||||
top: edgePost.guardLineTop + ExtensionConf.arDetect.guardLine.edgeTolerancePx,
|
||||
bottom: edgePost.guardLineBottom - ExtensionConf.arDetect.guardLine.edgeTolerancePx
|
||||
top: edgePost.guardLineTop + this.settings.active.arDetect.guardLine.edgeTolerancePx,
|
||||
bottom: edgePost.guardLineBottom - this.settings.active.arDetect.guardLine.edgeTolerancePx
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -772,7 +774,7 @@ class ArDetector {
|
||||
}
|
||||
|
||||
resetBlackLevel(){
|
||||
this.blackLevel = ExtensionConf.arDetect.blackLevel_default;
|
||||
this.blackLevel = this.settings.active.arDetect.blackLevel_default;
|
||||
}
|
||||
|
||||
}
|
||||
@ -797,8 +799,8 @@ var textLineTest = function(image, row){
|
||||
//
|
||||
// returns 'true' if text is detected, 'false' otherwise
|
||||
|
||||
var blackbarTreshold = this.blackLevel + ExtensionConf.arDetect.blackbarTreshold;
|
||||
var nontextTreshold = this.canvas.width * ExtensionConf.arDetect.textLineTest.nonTextPulse;
|
||||
var blackbarTreshold = this.blackLevel + this.settings.active.arDetect.blackbarTreshold;
|
||||
var nontextTreshold = this.canvas.width * this.settings.active.arDetect.textLineTest.nonTextPulse;
|
||||
|
||||
var rowStart = (row * this.canvas.width) << 2;
|
||||
var rowEnd = rowStart + (this.canvas.width << 2);
|
||||
@ -852,7 +854,7 @@ var textLineTest = function(image, row){
|
||||
|
||||
// če smo zaznali dovolj pulzov, potem vrnemo res
|
||||
// if we detected enough pulses, we return true
|
||||
if(pulseCount > ExtensionConf.arDetect.textLineTest.pulsesToConfirm){
|
||||
if(pulseCount > this.settings.active.arDetect.textLineTest.pulsesToConfirm){
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -861,7 +863,7 @@ var textLineTest = function(image, row){
|
||||
// if the longest uninterrupted line of black pixels is wider than half the width, we use a more
|
||||
// forgiving standard for determining if we found text
|
||||
if( longestBlack > (this.canvas.width >> 1) &&
|
||||
pulseCount > ExtensionConf.arDetect.textLineTest.pulsesToConfirmIfHalfBlack ){
|
||||
pulseCount > this.settings.active.arDetect.textLineTest.pulsesToConfirmIfHalfBlack ){
|
||||
return true;
|
||||
}
|
||||
|
||||
|
16
js/modules/Interface.js
Normal file
16
js/modules/Interface.js
Normal file
@ -0,0 +1,16 @@
|
||||
class Interface {
|
||||
constructor(videoData) {
|
||||
this.conf = videoData;
|
||||
this.player = videoData.player;
|
||||
}
|
||||
|
||||
injectUi() {
|
||||
|
||||
this.detectorDiv = document.createElement('div');
|
||||
this.uiRoot = document.createElement('div');
|
||||
this.detectorDiv.appendChild(this.uiRoot);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -2,12 +2,11 @@ if(Debug.debug)
|
||||
console.log("Loading: PageInfo.js");
|
||||
|
||||
class PageInfo {
|
||||
constructor(comms){
|
||||
this.keybinds = new Keybinds(this);
|
||||
this.keybinds.setup();
|
||||
constructor(comms, settings){
|
||||
this.hasVideos = false;
|
||||
this.siteDisabled = false;
|
||||
this.videos = [];
|
||||
this.settings = settings;
|
||||
|
||||
this.lastUrl = window.location.href;
|
||||
|
||||
@ -16,15 +15,27 @@ class PageInfo {
|
||||
|
||||
if(comms){
|
||||
this.comms = comms;
|
||||
if(this.videos.length > 0){
|
||||
comms.registerVideo();
|
||||
}
|
||||
}
|
||||
|
||||
if(this.videos.length > 0){
|
||||
comms.registerVideo();
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if(Debug.debug){
|
||||
console.log("[PageInfo::destroy] destroying all videos!")
|
||||
}
|
||||
if(this.rescanTimer){
|
||||
clearTimeout(this.rescanTimer);
|
||||
}
|
||||
for (var video of this.videos) {
|
||||
video.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
reset(){
|
||||
for(video of this.videos) {
|
||||
reset() {
|
||||
for(var video of this.videos) {
|
||||
video.destroy();
|
||||
}
|
||||
this.rescan(RescanReason.MANUAL);
|
||||
@ -79,7 +90,7 @@ class PageInfo {
|
||||
if(Debug.debug && Debug.periodic && Debug.videoRescan){
|
||||
console.log("[PageInfo::rescan] found new video candidate:", video)
|
||||
}
|
||||
v = new VideoData(video);
|
||||
v = new VideoData(video, this.settings);
|
||||
// console.log("[PageInfo::rescan] v is:", v)
|
||||
// debugger;
|
||||
v.initArDetection();
|
||||
@ -126,7 +137,7 @@ class PageInfo {
|
||||
ths.rescanTimer = null;
|
||||
ths.rescan(rr);
|
||||
ths = null;
|
||||
}, rescanReason === ExtensionConf.pageInfo.timeouts.rescan, RescanReason.PERIODIC)
|
||||
}, rescanReason === this.settings.active.pageInfo.timeouts.rescan, RescanReason.PERIODIC)
|
||||
} catch(e) {
|
||||
if(Debug.debug){
|
||||
console.log("[PageInfo::scheduleRescan] scheduling rescan failed. Here's why:",e)
|
||||
@ -146,7 +157,7 @@ class PageInfo {
|
||||
ths.rescanTimer = null;
|
||||
ths.ghettoUrlCheck();
|
||||
ths = null;
|
||||
}, ExtensionConf.pageInfo.timeouts.urlCheck)
|
||||
}, this.settings.active.pageInfo.timeouts.urlCheck)
|
||||
}catch(e){
|
||||
if(Debug.debug){
|
||||
console.log("[PageInfo::scheduleUrlCheck] scheduling URL check failed. Here's why:",e)
|
||||
|
@ -13,7 +13,7 @@ class Resizer {
|
||||
constructor(videoData){
|
||||
this.conf = videoData;
|
||||
this.video = videoData.video;
|
||||
|
||||
this.settings = videoData.settings;
|
||||
|
||||
this.scaler = new Scaler(this.conf);
|
||||
this.stretcher = new Stretcher(this.conf);
|
||||
@ -22,14 +22,22 @@ class Resizer {
|
||||
// load up default values
|
||||
this.correctedVideoDimensions = {};
|
||||
this.currentCss = {};
|
||||
this.currentStyleString = "";
|
||||
this.currentCssValidFor = {};
|
||||
|
||||
// restore watchdog. While true, applyCss() tries to re-apply new css until this value becomes false again
|
||||
// value becomes false when width and height of <video> tag match with what we want to set. Only necessary when
|
||||
// calling _res_restore() for some weird reason.
|
||||
this.restore_wd = false;
|
||||
|
||||
// CSS watcher will trigger _very_ often for this many iterations
|
||||
this.cssWatcherIncreasedFrequencyCounter = 0;
|
||||
|
||||
|
||||
this.lastAr = {type: 'original'};
|
||||
this.destroyed = false;
|
||||
|
||||
this.resizerId = (Math.random(99)*100).toFixed(0);
|
||||
}
|
||||
|
||||
start(){
|
||||
@ -41,14 +49,23 @@ class Resizer {
|
||||
}
|
||||
|
||||
destroy(){
|
||||
if(Debug.debug){
|
||||
console.log(`[Resizer::destroy] <rid:${this.resizerId}> received destroy command.`);
|
||||
}
|
||||
this.destroyed = true;
|
||||
this.stopCssWatcher();
|
||||
}
|
||||
|
||||
|
||||
setAr(ar, lastAr){
|
||||
if (this.destroyed) {
|
||||
return;
|
||||
}
|
||||
this.startCssWatcher();
|
||||
this.cssWatcherIncreasedFrequencyCounter = 20;
|
||||
|
||||
if(Debug.debug){
|
||||
console.log('[Resizer::setAr] trying to set ar. New ar:', ar)
|
||||
console.log('[Resizer::setAr] <rid:'+this.resizerId+'> trying to set ar. New ar:', ar)
|
||||
}
|
||||
|
||||
if(lastAr) {
|
||||
@ -80,7 +97,7 @@ class Resizer {
|
||||
|
||||
if(! stretchFactors || stretchFactors.error){
|
||||
if(Debug.debug){
|
||||
console.log("[Resizer::setAr] failed to set AR due to problem with calculating crop. Error:", (stretchFactors ? stretchFactors.error : stretchFactors));
|
||||
console.log("[Resizer::setAr] <rid:"+this.resizerId+"> failed to set AR due to problem with calculating crop. Error:", (stretchFactors ? stretchFactors.error : stretchFactors));
|
||||
}
|
||||
if(stretchFactors.error === 'no_video'){
|
||||
this.conf.destroy();
|
||||
@ -133,13 +150,44 @@ class Resizer {
|
||||
}
|
||||
|
||||
startCssWatcher(){
|
||||
// this.haltCssWatcher = false;
|
||||
if(!this.cssWatcherTimeout){
|
||||
// if(Debug.debug)
|
||||
// console.log("[Resizer.js] STARTING CSS WATCHER")
|
||||
|
||||
// this.cssWatcherTimeout = setInterval(this.cssWatcher, 200, this);
|
||||
if (this.destroyed) {
|
||||
return;
|
||||
}
|
||||
// this.haltCssWatcher = false;
|
||||
if(!this.cssWatcherTimer){
|
||||
this.scheduleCssWatcher(1);
|
||||
} else {
|
||||
clearTimeout(this.cssWatcherTimer);
|
||||
this.scheduleCssWatcher(1);
|
||||
}
|
||||
}
|
||||
|
||||
scheduleCssWatcher(timeout, force_reset) {
|
||||
if (this.destroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(timeout === undefined) {
|
||||
console.log("?")
|
||||
this.cssCheck(); // no timeout = one-off
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.cssWatcherTimeout) {
|
||||
clearTimeout(this.cssWatcherTimer);
|
||||
}
|
||||
|
||||
var ths = this;
|
||||
this.cssWatcherTimer = setTimeout(function () {
|
||||
ths.cssWatcherTimer = null;
|
||||
try {
|
||||
ths.cssCheck();
|
||||
} catch (e) {
|
||||
if(Debug.debug) {
|
||||
console.log("[Resizer.js::scheduleCssWatcher] Css check failed. Error:", e);
|
||||
}
|
||||
}
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
stopCssWatcher() {
|
||||
@ -150,7 +198,7 @@ class Resizer {
|
||||
|
||||
restore() {
|
||||
if(Debug.debug){
|
||||
console.log("[Resizer::restore] attempting to restore aspect ratio. this & settings:", {'this': this, "settings": Settings} );
|
||||
console.log("[Resizer::restore] <rid:"+this.resizerId+"> attempting to restore aspect ratio. this & settings:", {'this': this, "settings": this.settings} );
|
||||
}
|
||||
|
||||
// this is true until we verify that css has actually been applied
|
||||
@ -199,7 +247,7 @@ class Resizer {
|
||||
computeOffsets(stretchFactors){
|
||||
|
||||
if(Debug.debug)
|
||||
console.log("[Resizer::_res_computeOffsets] video will be aligned to ", ExtensionConf.miscFullscreenSettings.videoFloat);
|
||||
console.log("[Resizer::_res_computeOffsets] <rid:"+this.resizerId+"> video will be aligned to ", this.settings.active.miscFullscreenSettings.videoFloat);
|
||||
|
||||
var actualWidth = this.conf.video.offsetWidth * stretchFactors.xFactor;
|
||||
var actualHeight = this.conf.video.offsetHeight * stretchFactors.yFactor;
|
||||
@ -209,10 +257,10 @@ class Resizer {
|
||||
if (this.pan) {
|
||||
// todo: calculate translate
|
||||
} else {
|
||||
if (ExtensionConf.miscFullscreenSettings.videoFloat == "left") {
|
||||
if (this.settings.active.miscFullscreenSettings.videoFloat == "left") {
|
||||
translate.x = (this.conf.player.dimensions.width - actualWidth) * -0.5;
|
||||
}
|
||||
else if (ExtensionConf.miscFullscreenSettings.videoFloat == "right") {
|
||||
else if (this.settings.active.miscFullscreenSettings.videoFloat == "right") {
|
||||
translate.x = (this.conf.player.dimensions.width - actualWidth) * 0.5;
|
||||
}
|
||||
}
|
||||
@ -224,7 +272,7 @@ class Resizer {
|
||||
|
||||
if (! this.video) {
|
||||
if(Debug.debug)
|
||||
console.log("[Resizer::_res_applyCss] Video went missing, doing nothing.");
|
||||
console.log("[Resizer::_res_applyCss] <rid:"+this.resizerId+"> Video went missing, doing nothing.");
|
||||
this.conf.destroy();
|
||||
return;
|
||||
}
|
||||
@ -271,12 +319,15 @@ class Resizer {
|
||||
|
||||
setStyleString (styleString, count = 0) {
|
||||
this.video.setAttribute("style", styleString);
|
||||
|
||||
this.currentStyleString = this.video.getAttribute('style');
|
||||
this.currentCssValidFor = this.conf.player.dimensions;
|
||||
|
||||
if(this.restore_wd){
|
||||
|
||||
if(! this.video){
|
||||
if(Debug.debug)
|
||||
console.log("[Resizer::_res_setStyleString] Video element went missing, nothing to do here.")
|
||||
console.log("[Resizer::_res_setStyleString] <rid:"+this.resizerId+"> Video element went missing, nothing to do here.")
|
||||
return;
|
||||
}
|
||||
|
||||
@ -288,8 +339,8 @@ class Resizer {
|
||||
// if(Debug.debug)
|
||||
// console.log("[Resizer::_res_setStyleString] Style string not set ???");
|
||||
|
||||
// if(count < ExtensionConf.resizer.setStyleString.maxRetries){
|
||||
// setTimeout( this.setStyleString, ExtensionConf.resizer.setStyleString.retryTimeout, count + 1);
|
||||
// if(count < settings.active.resizer.setStyleString.maxRetries){
|
||||
// setTimeout( this.setStyleString, settings.active.resizer.setStyleString.retryTimeout, count + 1);
|
||||
// }
|
||||
// else if(Debug.debug){
|
||||
// console.log("[Resizer::_res_setStyleString] we give up. css string won't be set");
|
||||
@ -301,78 +352,47 @@ class Resizer {
|
||||
}
|
||||
else{
|
||||
if(Debug.debug)
|
||||
console.log("[Resizer::_res_setStyleString] css applied. Style string:", styleString);
|
||||
console.log("[Resizer::_res_setStyleString] <rid:"+this.resizerId+"> css applied. Style string:", styleString);
|
||||
}
|
||||
}
|
||||
|
||||
cssWatcher(ths){
|
||||
cssCheck(){
|
||||
// this means we haven't set our CSS yet, or that we changed video.
|
||||
if(! ths.currentCss.top)
|
||||
return;
|
||||
// if(! this.currentCss.tranform) {
|
||||
// this.scheduleCssWatcher(200);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// this means video went missing. videoData will be re-initialized when the next video is found
|
||||
if(! ths.video){
|
||||
ths.conf.destroy();
|
||||
if(! this.video){
|
||||
if(Debug.debug) {
|
||||
console.log("[Resizer::cssCheck] <rid:"+this.resizerId+"> no video detecting, issuing destroy command");
|
||||
}
|
||||
this.conf.destroy();
|
||||
return;
|
||||
}
|
||||
console.log("css watcher running. video?", ths.video)
|
||||
|
||||
// // our current css is fucky? Null, undefined and 0 are invalid values.
|
||||
// if(! GlobalVars.currentCss.width || ! GlobalVars.currentCss.height )
|
||||
// return;
|
||||
if(this.destroyed) {
|
||||
if(Debug.debug) {
|
||||
console.log("[Resizer::cssCheck] <rid:"+this.resizerId+"> destroyed flag is set, we shouldnt be running");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var styleString = this.video.getAttribute('style');
|
||||
|
||||
// first, a quick test:
|
||||
if (ths.currentVideoSettings.validFor == ths.conf.player.dimensions ){
|
||||
if (ths.currentVideoSettings.videoWidth != ths.video.offsetWidth ||
|
||||
ths.currentVideoSettings.videoHeight != ths.video.offsetHeight){
|
||||
ths.restore();
|
||||
return;
|
||||
}
|
||||
// if (this.currentVideoSettings.validFor == this.conf.player.dimensions ){
|
||||
if (this.currentStyleString !== styleString){
|
||||
this.restore();
|
||||
this.scheduleCssWatcher(10);
|
||||
return;
|
||||
}
|
||||
|
||||
var styleArrayStr = ths.video.getAttribute('style');
|
||||
|
||||
if (styleArrayStr){
|
||||
var styleArray = styleArrayStr.split(";");
|
||||
|
||||
var stuffChecked = 0;
|
||||
var stuffToCheck = 2;
|
||||
|
||||
for(var i in styleArray){
|
||||
styleArray[i] = styleArray[i].trim();
|
||||
|
||||
if (styleArray[i].startsWith("top:")){
|
||||
// don't force css restore if currentCss.top is not defined
|
||||
if(ths.currentCss.top && styleArray[i] != ths.currentCss.top){
|
||||
if(Debug.debug){
|
||||
console.log("[Resizer::_res_antiCssOverride] SOMEBODY TOUCHED MA SPAGHETT (our CSS got overriden, restoring our css)");
|
||||
console.log("[Resizer::_res_antiCssOverride] MA SPAGHETT: top:", ths.currentCss.top, "left:", ths.currentCss.left, "thing that touched ma spaghett", styleArrayStr);
|
||||
}
|
||||
ths.restore();
|
||||
return;
|
||||
}
|
||||
stuffChecked++;
|
||||
}
|
||||
else if(styleArray[i].startsWith("left:")){
|
||||
// don't force css restore if currentCss.left is not defined
|
||||
if(ths.currentCss.left && styleArray[i] != ths.currentCss.left){
|
||||
if(Debug.debug){
|
||||
console.log("[Resizer::_res_antiCssOverride] SOMEBODY TOUCHED MA SPAGHETT (our CSS got overriden, restoring our css)");
|
||||
console.log("[Resizer::_res_antiCssOverride] MA SPAGHETT: width:", ths.currentCss.width, "height:", ths.currentCss.height, "thing that touched ma spaghett", styleArrayStr);
|
||||
}
|
||||
ths.restore();
|
||||
return;
|
||||
}
|
||||
stuffChecked++;
|
||||
}
|
||||
|
||||
if(stuffChecked == stuffToCheck){
|
||||
// if(Debug.debug){
|
||||
// console.log("[Resizer::_res_antiCssOverride] My spaghett rests untouched. (nobody overrode our CSS, doing nothing)");
|
||||
// }
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.cssWatcherIncreasedFrequencyCounter > 0) {
|
||||
--this.cssWatcherIncreasedFrequencyCounter;
|
||||
this.scheduleCssWatcher(20);
|
||||
} else {
|
||||
this.scheduleCssWatcher(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,10 +32,10 @@ class Scaler {
|
||||
ar = this.conf.player.dimensions.width / this.conf.player.dimensions.height;
|
||||
}
|
||||
|
||||
// POMEMBNO: GlobalVars.lastAr je potrebno nastaviti šele po tem, ko kličemo _res_setAr(). _res_setAr() predvideva,
|
||||
// POMEMBNO: lastAr je potrebno nastaviti šele po tem, ko kličemo _res_setAr(). _res_setAr() predvideva,
|
||||
// da želimo nastaviti statično (type: 'static') razmerje stranic — tudi, če funkcijo kličemo tu oz. v ArDetect.
|
||||
//
|
||||
// IMPORTANT NOTE: GlobalVars.lastAr needs to be set after _res_setAr() is called, as _res_setAr() assumes we're
|
||||
// IMPORTANT NOTE: lastAr needs to be set after _res_setAr() is called, as _res_setAr() assumes we're
|
||||
// setting a static aspect ratio (even if the function is called from here or ArDetect).
|
||||
|
||||
var fileAr = this.conf.video.videoWidth / this.conf.video.videoHeight;
|
||||
|
@ -11,7 +11,8 @@ class Stretcher {
|
||||
// functions
|
||||
constructor(videoData) {
|
||||
this.conf = videoData;
|
||||
this.mode = ExtensionConf.stretch.initialMode;
|
||||
this.settings = videoData.settings;
|
||||
this.mode = this.settings.active.stretch.initialMode;
|
||||
}
|
||||
|
||||
applyConditionalStretch(stretchFactors, actualAr){
|
||||
@ -36,11 +37,11 @@ class Stretcher {
|
||||
actualWidth = newWidth;
|
||||
}
|
||||
|
||||
var minW = this.conf.player.dimensions.width * (1 - ExtensionConf.stretch.conditionalDifferencePercent);
|
||||
var maxW = this.conf.player.dimensions.width * (1 + ExtensionConf.stretch.conditionalDifferencePercent);
|
||||
var minW = this.conf.player.dimensions.width * (1 - this.settings.active.stretch.conditionalDifferencePercent);
|
||||
var maxW = this.conf.player.dimensions.width * (1 + this.settings.active.stretch.conditionalDifferencePercent);
|
||||
|
||||
var minH = this.conf.player.dimensions.height * (1 - ExtensionConf.stretch.conditionalDifferencePercent);
|
||||
var maxH = this.conf.player.dimensions.height * (1 + ExtensionConf.stretch.conditionalDifferencePercent);
|
||||
var minH = this.conf.player.dimensions.height * (1 - this.settings.active.stretch.conditionalDifferencePercent);
|
||||
var maxH = this.conf.player.dimensions.height * (1 + this.settings.active.stretch.conditionalDifferencePercent);
|
||||
|
||||
if (actualWidth >= minW && actualWidth <= maxW) {
|
||||
stretchFactors.xFactor *= this.conf.player.dimensions.width / actualWidth;
|
||||
|
@ -1,46 +0,0 @@
|
||||
var GlobalVars = {
|
||||
video: null,
|
||||
player: null,
|
||||
playerDimensions: null,
|
||||
playerElement: null,
|
||||
lastAr: null,
|
||||
lastUrl: "",
|
||||
currentCss: {
|
||||
top: null,
|
||||
left: null
|
||||
},
|
||||
canvas: {
|
||||
context: null,
|
||||
width: null,
|
||||
height: null,
|
||||
imageDataRowLength: null
|
||||
},
|
||||
correctedVideoDimensions: {
|
||||
width: null,
|
||||
height: null,
|
||||
top: null,
|
||||
left: null
|
||||
},
|
||||
arDetect: {
|
||||
autoDisable: {
|
||||
eventCount: 0
|
||||
},
|
||||
canvas: null,
|
||||
blackLevel: 10,
|
||||
sampleCols_current: 0,
|
||||
noLetterboxCanvasReset: false,
|
||||
guardLine: {
|
||||
top: null,
|
||||
bottom: null,
|
||||
logo: {
|
||||
detected: false,
|
||||
top_left: null,
|
||||
top_right: null,
|
||||
bottom_left: null,
|
||||
bottom_right: null
|
||||
},
|
||||
start: null,
|
||||
end: null
|
||||
}
|
||||
}
|
||||
}
|
253
js/uw-bg.js
253
js/uw-bg.js
@ -15,15 +15,17 @@ class UWServer {
|
||||
}
|
||||
|
||||
async setup() {
|
||||
await Settings.init();
|
||||
this.settings = new Settings();
|
||||
|
||||
await this.settings.init();
|
||||
this.comms = new CommsServer(this);
|
||||
|
||||
|
||||
var ths = this;
|
||||
if(BrowserDetect.firefox) {
|
||||
browser.tabs.onActivated.addListener((m) => ths.onTabSwitched(m));
|
||||
browser.tabs.onActivated.addListener(function(m) {ths.onTabSwitched(m)});
|
||||
} else if (BrowserDetect.chrome) {
|
||||
chrome.tabs.onActivated.addListener((m) => ths.onTabSwitched(m));
|
||||
chrome.tabs.onActivated.addListener(function(m) {ths.onTabSwitched(m)});
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,247 +81,4 @@ class UWServer {
|
||||
|
||||
}
|
||||
|
||||
var server = new UWServer();
|
||||
|
||||
|
||||
|
||||
// async function main(){
|
||||
// if(Debug.debug)
|
||||
// console.log("[uw-bg::main] setting up background script");
|
||||
|
||||
|
||||
// Keybinds.keybinds = await Keybinds.fetch();
|
||||
|
||||
|
||||
// // Poslušalci za dogodke | event listeners here
|
||||
// // {===]///[-------------------------------------]\\\[===}
|
||||
|
||||
// browser.runtime.onMessage.addListener(_uwbg_rcvmsg);
|
||||
// browser.tabs.onActivated.addListener(_uwbg_onTabSwitched);
|
||||
|
||||
// if(Debug.debug)
|
||||
// console.log("[uw-bg::main] listeners registered");
|
||||
|
||||
// // add currentSite
|
||||
// var tabs = await Comms.getActiveTab();
|
||||
// BgVars.currentSite = extractHostname(tabs[0].url);
|
||||
|
||||
// //
|
||||
// setInterval(_uwbg_check4videos, 5000);
|
||||
// }
|
||||
|
||||
// async function _uwbg_onTabSwitched(activeInfo){
|
||||
// BgVars.hasVideos = false;
|
||||
// if(Debug.debug)
|
||||
// console.log("[uw-bg::onTabSwitched] TAB CHANGED, GETTING INFO FROM MAIN TAB");
|
||||
|
||||
|
||||
// var tabId = activeInfo.tabId; // just for readability
|
||||
|
||||
// var tab = await browser.tabs.get(tabId);
|
||||
|
||||
// BgVars.currentSite = extractHostname(tab.url);
|
||||
|
||||
// // this can fail. This might also not return a promise? Check that.
|
||||
// var videoFrameList = await Comms.sendToEach({"cmd":"has-videos"}, tabId);
|
||||
|
||||
// if(Debug.debug)
|
||||
// console.log("[uw-bg::onTabSwitched] got list of frames and whether they have videos", videoFrameList);
|
||||
|
||||
// // Pogledamo, če kateri od okvirjev vsebuje video. Da omogočimo pojavno okno je zadosti že
|
||||
// // en okvir z videom.
|
||||
// // <===[///]----------------------------[\\\]===>
|
||||
// // Check if any frame has a video in it. To enable the popup there only needs to be at least one,
|
||||
// // but the popup controls all frames.
|
||||
|
||||
// var hasVideos = false;
|
||||
// for(frame of videoFrameList){
|
||||
// hasVideos |= frame.response.hasVideos;
|
||||
// }
|
||||
|
||||
// BgVars.hasVideos = hasVideos;
|
||||
|
||||
// Settings.reload();
|
||||
// // todo: change extension icon depending on whether there's a video on the page or not
|
||||
// }
|
||||
|
||||
// async function _uwbg_check4videos(){
|
||||
// if(BgVars.hasVideos)
|
||||
// return;
|
||||
|
||||
// var videoFrameList = Comms.sendToEach({"cmd":"has-videos"});
|
||||
|
||||
// if(Debug.debug)
|
||||
// console.log("[uw-bg::check4videos] got updated list of frames and whether they have videos", videoFrameList);
|
||||
|
||||
// var hasVideos = false;
|
||||
// for(frame of videoFrameList){
|
||||
// hasVideos |= frame.response.hasVideos;
|
||||
// }
|
||||
|
||||
// BgVars.hasVideos = hasVideos;
|
||||
// }
|
||||
|
||||
// async function _uwbg_registerVideo(tabId){
|
||||
// var tabs = await Comms.getActiveTab();
|
||||
|
||||
// // če ukaz pride iz zavihka, na katerem se trenunto ne nahajamo, potem se za zahtevo ne brigamo
|
||||
// // if command originated from a tab that's _not_ currently active, we ignore the request
|
||||
// if(tabId != tabs[0].id){
|
||||
// if(Debug.debug){
|
||||
// console.log("[uw-bg::_uwbg_registerVideo] request didn't come from currently active tab, ignoring");
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
// if(Debug.debug){
|
||||
// console.log("%c[uw-bg::_uwbg_registerVideo] request came from currently active tab!", "color: #afd, background: #000");
|
||||
// }
|
||||
// BgVars.hasVideos = true;
|
||||
|
||||
// // todo: change extension icon depending on whether there's a video on the page or not
|
||||
// }
|
||||
|
||||
// function _uwbg_rcvmsg(message, sender, sendResponse){
|
||||
// if(Debug.debug){
|
||||
// console.log("[uw-bg::_uwbg_rcvmsg] received message", message, "from sender", sender);
|
||||
// }
|
||||
|
||||
// message.sender = "uwbg";
|
||||
// message.receiver = "uw";
|
||||
|
||||
// if(message.cmd == "has-videos"){
|
||||
// if(Debug.debug){
|
||||
// console.log("[uw-bg::_uwbg_rcvmsg] does this tab or any of its subframes have videos?", BgVars.hasVideos );
|
||||
// }
|
||||
|
||||
// var res = {response: {hasVideos: BgVars.hasVideos}};
|
||||
// if(BrowserDetect.firefox){
|
||||
// return Promise.resolve(res);
|
||||
// }
|
||||
// sendResponse(res);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// if(message.cmd == "get-config"){
|
||||
// var config = {};
|
||||
// config.videoAlignment = ExtensionConf.miscFullscreenSettings.videoFloat;
|
||||
// config.arConf = {};
|
||||
// config.arConf.enabled_global = ExtensionConf.arDetect.enabled == "blacklist";
|
||||
|
||||
// config.site = {};
|
||||
// config.site.status = SitesConf.getSiteStatus(BgVars.currentSite);
|
||||
// config.site.arStatus = SitesConf.getArStatus(BgVars.currentSite);
|
||||
|
||||
// config.mode = ExtensionConf.extensionMode;
|
||||
// config.arMode = ExtensionConf.arDetect.mode;
|
||||
// config.arDisabledReason = ExtensionConf.arDetect.disabledReason;
|
||||
// config.arTimerPlaying = ExtensionConf.arDetect.timer_playing;
|
||||
|
||||
// if(Debug.debug)
|
||||
// console.log("[uw-bg::_uwbg_rcvmsg] Keybinds.getKeybinds() returned this:", Keybinds.getKeybinds());
|
||||
|
||||
// config.keyboardShortcuts = Keybinds.getKeybinds();
|
||||
|
||||
|
||||
// // predvidevajmo, da je enako. Če je drugače, bomo popravili ko dobimo odgovor
|
||||
// // assume current is same as global & change that when you get response from content script
|
||||
// config.arConf.enabled_current = ExtensionConf.arDetect.enabled == "blacklist";
|
||||
|
||||
// var res = {response: config}
|
||||
|
||||
// if(Debug.debug){
|
||||
// console.log("[uw-bg::_uwbg_rcvmsg] get-config: returning this to popup script:", res);
|
||||
// }
|
||||
|
||||
// if(BrowserDetect.firefox){
|
||||
// return Promise.resolve(res);
|
||||
// }
|
||||
// sendResponse(res);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// if(message.cmd == "register-video"){
|
||||
// // dobili smo sporočilce, ki pravi: "hej jaz imam video, naredi cahen" — ampak preden naredimo cahen,
|
||||
// // se je potrebno prepričati, da je sporočilce prišlo iz pravilnega zavihka. Trenutno odprt zavihek
|
||||
// // lahko dobimo to. ID zavihka, iz katerega je prišlo sporočilo, se skriva v sender.tab.id
|
||||
// // ~<><\\\][=================][///><>~
|
||||
// // we got a message that says: "hey I have a video, make a mark or something" — but before we do the
|
||||
// // mark, we should check if the message has truly arrived from currently active tab. We can get the
|
||||
// // id of currently active tab here. ID of the sender tab is ‘hidden’ in sender.tab.id.
|
||||
|
||||
// _uwbg_registerVideo(sender.tab.id);
|
||||
// }
|
||||
|
||||
// else if(message.cmd == "uw-enabled-for-site"){
|
||||
|
||||
// var mode = SitesConf.getSiteStatus(BgVars.currentSite);
|
||||
|
||||
// if(BrowserDetect.usebrowser == "firefox")
|
||||
// return Promise.resolve({response: mode});
|
||||
|
||||
// try{
|
||||
// sendResponse({response: mode});
|
||||
// }
|
||||
// catch(chromeIsShitError){};
|
||||
|
||||
// return true;
|
||||
// }
|
||||
// else if(message.cmd == "enable-for-site"){
|
||||
// SitesConf.updateSite(BgVars.currentSite, {status: message.option, statusEmbedded: message.option});
|
||||
// }
|
||||
// else if(message.cmd == "enable-autoar"){
|
||||
// ExtensionConf.arDetect.mode = "blacklist";
|
||||
// Settings.save(ExtensionConf);
|
||||
// Comms.sendToAll({cmd: "reload-settings", sender: "uwbg"})
|
||||
// if(Debug.debug){
|
||||
// console.log("[uw-bg] autoar set to enabled (blacklist). evidenz:", ExtensionConf);
|
||||
// }
|
||||
// }
|
||||
// else if(message.cmd == "disable-autoar"){
|
||||
// ExtensionConf.arDetect.mode = "disabled";
|
||||
// if(message.reason){
|
||||
// ExtensionConf.arDetect.disabledReason = message.reason;
|
||||
// } else {
|
||||
// ExtensionConf.arDetect.disabledReason = '';
|
||||
// }
|
||||
// Settings.save(ExtensionConf);
|
||||
// // Comms.sendToAll({cmd: "reload-settings", sender: "uwbg"});
|
||||
// if(Debug.debug){
|
||||
// console.log("[uw-bg] autoar set to disabled. evidenz:", ExtensionConf);
|
||||
// }
|
||||
// }
|
||||
// else if(message.cmd == "gib-settings"){
|
||||
// if(Debug.debug)
|
||||
// console.log("[uw-bg] we got asked for settings. Returning this:", ExtensionConf);
|
||||
|
||||
// if(BrowserDetect.usebrowser == "firefox")
|
||||
// return Promise.resolve({response: ExtensionConf});
|
||||
|
||||
// try{
|
||||
// sendResponse({response: ExtensionConf});
|
||||
// }
|
||||
// catch(chromeIsShitError){};
|
||||
|
||||
// return true;
|
||||
// }
|
||||
// else if(message.cmd = "autoar-set-timer-playing"){
|
||||
|
||||
// if(Debug.debug)
|
||||
// console.log("[uw-bg] trying to set new interval for autoAr. New interval is",message.timeout,"ms");
|
||||
|
||||
// var timeout = message.timeout;
|
||||
|
||||
// if(timeout < 1)
|
||||
// timeout = 1;
|
||||
// if(timeout > 999)
|
||||
// timeout = 999;
|
||||
|
||||
// ExtensionConf.arDetect.timer_playing = timeout;
|
||||
// Settings.save(ExtensionConf);
|
||||
// Comms.sendToAll({cmd: "update-settings", sender: "uwbg", newConf: ExtensionConf});
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
|
||||
// main();
|
||||
var server = new UWServer();
|
195
js/uw.js
195
js/uw.js
@ -13,151 +13,64 @@ if(Debug.debug){
|
||||
}
|
||||
|
||||
|
||||
var pageInfo;
|
||||
var comms;
|
||||
|
||||
async function init(){
|
||||
if(Debug.debug)
|
||||
console.log("[uw::main] loading configuration ...");
|
||||
|
||||
comms = new CommsClient('content-client-port');
|
||||
|
||||
// load settings
|
||||
var settingsLoaded = await comms.requestSettings();
|
||||
if(!settingsLoaded){
|
||||
if(Debug.debug) {
|
||||
console.log("[uw::main] failed to get settings (settingsLoaded=",settingsLoaded,") Waiting for settings the old fashioned way");
|
||||
}
|
||||
comms.requestSettings_fallback();
|
||||
await comms.waitForSettings();
|
||||
if(Debug.debug){
|
||||
console.log("[uw::main] settings loaded.");
|
||||
}
|
||||
class UW {
|
||||
constructor(){
|
||||
this.pageInfo = undefined;
|
||||
this.comms = undefined;
|
||||
this.settings = undefined;
|
||||
this.keybinds = undefined;
|
||||
}
|
||||
|
||||
if(Debug.debug)
|
||||
console.log("[uw::main] configuration should be loaded now");
|
||||
|
||||
async init(){
|
||||
if (Debug.debug) {
|
||||
console.log("[uw::main] loading configuration ...");
|
||||
}
|
||||
|
||||
// če smo razširitev onemogočili v nastavitvah, ne naredimo ničesar
|
||||
// If extension is soft-disabled, don't do shit
|
||||
if(! canStartExtension()){
|
||||
if(Debug.debug) {
|
||||
console.log("[uw::init] EXTENSION DISABLED, THEREFORE WONT BE STARTED")
|
||||
// init() is re-run any time settings change
|
||||
if (this.pageInfo) {
|
||||
if(Debug.debug){
|
||||
console.log("[uw::init] Destroying existing pageInfo", this.pageInfo);
|
||||
}
|
||||
this.pageInfo.destroy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
pageInfo = new PageInfo();
|
||||
comms.setPageInfo(pageInfo);
|
||||
|
||||
if(Debug.debug){
|
||||
console.log("[uw.js::setup] pageInfo initialized. Here's the object:", pageInfo);
|
||||
if (this.comms) {
|
||||
this.comms.destroy();
|
||||
}
|
||||
|
||||
if (!this.settings) {
|
||||
var ths = this;
|
||||
this.settings = new Settings(undefined, () => ths.init());
|
||||
await this.settings.init();
|
||||
}
|
||||
|
||||
this.comms = new CommsClient('content-client-port', this.settings);
|
||||
|
||||
// če smo razširitev onemogočili v nastavitvah, ne naredimo ničesar
|
||||
// If extension is soft-disabled, don't do shit
|
||||
if(! this.settings.canStartExtension()){
|
||||
if(Debug.debug) {
|
||||
console.log("[uw::init] EXTENSION DISABLED, THEREFORE WONT BE STARTED")
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.pageInfo = new PageInfo(this.comms, this.settings);
|
||||
if(Debug.debug){
|
||||
console.log("[uw.js::setup] pageInfo initialized. Here's the object:", this.pageInfo);
|
||||
}
|
||||
this.comms.setPageInfo(this.pageInfo);
|
||||
|
||||
this.keybinds = new Keybinds(this.pageInfo);
|
||||
this.keybinds.setup();
|
||||
|
||||
} catch (e) {
|
||||
console.log("[uw::init] FAILED TO START EXTENSION. Error:", e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// comms
|
||||
// function receiveMessage(message, sender, sendResponse) {
|
||||
// if(Debug.debug)
|
||||
// console.log("[uw::receiveMessage] we received a message.", message);
|
||||
|
||||
// if(message.cmd == "has-videos"){
|
||||
// var anyVideos = GlobalVars.video != null;
|
||||
|
||||
// if(Debug.debug)
|
||||
// console.log("[uw::receiveMessage] are there any videos on this page?", anyVideos, GlobalVars.video, this);
|
||||
|
||||
// if(BrowserDetect.usebrowser == "firefox")
|
||||
// return Promise.resolve({response: {"hasVideos": anyVideos }});
|
||||
|
||||
// try{
|
||||
// sendResponse({response: {"hasVideos":anyVideos}});
|
||||
// return true;
|
||||
// }
|
||||
// catch(chromeIsShitError){}
|
||||
// return;
|
||||
// }
|
||||
// else if(message.cmd == "get-config"){
|
||||
|
||||
// var config = {};
|
||||
// config.videoAlignment = ExtensionConf.miscFullscreenSettings.videoFloat;
|
||||
// config.arConf = {};
|
||||
// config.arConf.enabled_global = ExtensionConf.arDetect.enabled == "global";
|
||||
|
||||
|
||||
// var keybinds = ExtensionConf.keyboard.shortcuts;
|
||||
// if(Debug.debug)
|
||||
// console.log("[uw-bg::_uwbg_rcvmsg] Keybinds.fetch returned this:", keybinds);
|
||||
|
||||
// config.keyboardShortcuts = keybinds;
|
||||
|
||||
// // predvidevajmo, da je enako. Če je drugače, bomo popravili ko dobimo odgovor
|
||||
// // assume current is same as global & change that when you get response from content script
|
||||
// config.arConf.enabled_current = ArDetect.isRunning();
|
||||
|
||||
// if(BrowserDetect.usebrowser == "firefox")
|
||||
// return Promise.resolve({response: config});
|
||||
|
||||
// try{
|
||||
// sendResponse({response: config});
|
||||
// }
|
||||
// catch(chromeIsShitError){};
|
||||
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// else if(message.cmd == "force-ar"){
|
||||
// if(Debug.debug)
|
||||
// console.log("[uw::receiveMessage] we're being commanded to change aspect ratio to", message.newAr);
|
||||
|
||||
// if(message.arType == "legacy"){
|
||||
// ArDetect.stop();
|
||||
// Resizer.legacyAr(message.newAr);
|
||||
// }
|
||||
// else{
|
||||
// ArDetect.stop();
|
||||
// Resizer.setAr(message.newAr);
|
||||
// }
|
||||
// }
|
||||
// else if(message.cmd == "force-video-float"){
|
||||
// if(Debug.debug)
|
||||
// console.log("[uw::receiveMessage] we're aligning video to", message.newFloat);
|
||||
|
||||
// ExtensionConf.miscFullscreenSettings.videoFloat = message.newFloat;
|
||||
// Settings.save(ExtensionConf);
|
||||
// }
|
||||
// else if(message.cmd == "stop-autoar"){
|
||||
// ArDetect.stop();
|
||||
// }
|
||||
// else if(message.cmd == "update-settings"){
|
||||
// if(Debug.debug){
|
||||
// console.log("[uw] we got sent new ExtensionConf to abide by:", cmd.newConf);
|
||||
// }
|
||||
// ExtensionConf = cmd.newConf;
|
||||
// }
|
||||
// // else if(message.cmd == "enable-autoar"){
|
||||
// // if(Debug.debug){
|
||||
// // console.log("[uw] enabling autoar.");
|
||||
// // }
|
||||
// // ExtensionConf.autoAr.mode == "blacklist";
|
||||
// // Settings.save(ExtensionConf);
|
||||
// // }
|
||||
// // else if(message.cmd == "disable-autoar"){
|
||||
// // if(Debug.debug){
|
||||
// // console.log("[uw] disabling autoar.");
|
||||
// // }
|
||||
// // ExtensionConf.autoAr.mode == "disabled";
|
||||
// // Settings.save(ExtensionConf);
|
||||
// // }
|
||||
// if(message.cmd == "testing"){
|
||||
// if(Browserdetect.usebrowser = "firefox")
|
||||
// return Promise.resolve({response: "test response hier"});
|
||||
|
||||
// sendResponse({response: "test response hier"});
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
init();
|
||||
var uw = new UW();
|
||||
uw.init();
|
||||
|
@ -1,7 +1,12 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Ultrawidify",
|
||||
"version": "3.0.0",
|
||||
"version": "3.1.0",
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "{cf02b1a7-a01a-4e37-a609-516a283f1ed3}"
|
||||
}
|
||||
},
|
||||
|
||||
"icons": {
|
||||
"32":"res/icons/uw-32.png",
|
||||
@ -17,14 +22,11 @@
|
||||
|
||||
"js/lib/BrowserDetect.js",
|
||||
"js/conf/ExtensionConf.js",
|
||||
|
||||
"js/run/GlobalVars.js",
|
||||
"js/lib/StorageManager.js",
|
||||
"js/lib/Comms.js",
|
||||
|
||||
"js/conf/Settings.js",
|
||||
"js/conf/SitesConf.js",
|
||||
"js/conf/Status.js",
|
||||
"js/lib/ObjectCopy.js",
|
||||
"js/lib/Settings.js",
|
||||
|
||||
"js/lib/Comms.js",
|
||||
|
||||
"js/lib/EdgeDetect.js",
|
||||
"js/lib/GuardLine.js",
|
||||
@ -55,12 +57,10 @@
|
||||
|
||||
"js/conf/ExtensionConf.js",
|
||||
|
||||
"js/lib/StorageManager.js",
|
||||
"js/lib/Comms.js",
|
||||
|
||||
"js/conf/Settings.js",
|
||||
"js/conf/SitesConf.js",
|
||||
"js/conf/Status.js",
|
||||
|
||||
"js/lib/ObjectCopy.js",
|
||||
"js/lib/Settings.js",
|
||||
|
||||
"js/conf/Keybinds.js",
|
||||
|
||||
|
117
res/css/uw-common.css
Normal file
117
res/css/uw-common.css
Normal file
@ -0,0 +1,117 @@
|
||||
a {
|
||||
color: #af7f37;
|
||||
}
|
||||
a:hover {
|
||||
color: #c0924e;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** layout stuff **/
|
||||
|
||||
.row {
|
||||
display: block;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.button-row {
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.w24 {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** input **/
|
||||
|
||||
input {
|
||||
border: 1px solid #322;
|
||||
padding: 0.5em;
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.invalid-input {
|
||||
border: 1px solid #720 !important;
|
||||
background-color: #410 !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** buttons and stuff ***/
|
||||
|
||||
.button {
|
||||
display: inline-block;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 3px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
border: 1px solid #444;
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
color: #dbb;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
color: #fff;
|
||||
background-color: #433221;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** formatting **/
|
||||
|
||||
small{
|
||||
font-size: 0.75em;
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
.smallcaps{
|
||||
font-variant: small-caps;
|
||||
}
|
||||
|
||||
.center{
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** misc **/
|
||||
|
||||
.color_warn {
|
||||
color: #d6ba4a;
|
||||
}
|
||||
|
||||
.warning {
|
||||
color: #d6ba4a;
|
||||
padding-left: 35px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.warning::before {
|
||||
content: "⚠ ";
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
font-size: 2.5em;
|
||||
margin-left: -35px;
|
||||
padding-right: 10px;
|
||||
/* top: 0px; */
|
||||
float: left;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,57 +0,0 @@
|
||||
@import url('https://fonts.googleapis.com/css?family=Oxygen:300,400&subset=latin-ext');
|
||||
|
||||
.show{
|
||||
display: block !important;
|
||||
}
|
||||
.uw_hide{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.uw_submenu{
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: rgba(0,0,0,0.66);
|
||||
}
|
||||
/*
|
||||
.uw-setmenu{
|
||||
padding-left: 2em !important;
|
||||
padding-right: 2em !important;
|
||||
}*/
|
||||
|
||||
.uw_submenu_bottom0{
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
.display_relative{
|
||||
display: relative;
|
||||
}
|
||||
|
||||
.uw-setmenu-item{
|
||||
padding-right: 2em !important;
|
||||
padding-left: 2em !important;
|
||||
}
|
||||
|
||||
.common_anchor {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uw_button{
|
||||
display: inline-block;
|
||||
/* height: 100% !important; */
|
||||
background-size: 75% 75%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
}
|
||||
|
||||
.uw_ui_anchor{
|
||||
display: inline-block;
|
||||
}
|
||||
#uw_ui_anchor{
|
||||
display: inline-block;
|
||||
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
.uw-button{
|
||||
display: inline-block;
|
||||
/* height: 100% !important; */
|
||||
background-size: 75% 75%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
}
|
||||
|
||||
.uw-button-row {
|
||||
display: inline-block !important;
|
||||
position: absolute !important;
|
||||
top: 0 !important;
|
||||
right: 0 !important;
|
||||
width: 99% !important;
|
||||
height: 100% !important;
|
||||
z-index: 1337 !important;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.uw-button:hover{
|
||||
background-color: rgba(192,0,0,0.66);
|
||||
}
|
||||
.uw-setmenu{
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: rgba(0,0,0,0.66);
|
||||
right: 0px;
|
||||
}
|
||||
.uw-setmenu-item{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-family: "Oxygen";
|
||||
color: #ffffff !important;
|
||||
width: 90%;
|
||||
padding-left: 10%;
|
||||
}
|
||||
.uw-setmenu-item:hover{
|
||||
background-color: rgba(192,0,0,0.66);
|
||||
}
|
@ -1 +0,0 @@
|
||||
/* yeah this is also a placeholder file, this time for 'settings' page */
|
@ -1,28 +0,0 @@
|
||||
.uw-button{
|
||||
display: inline-block;
|
||||
height: 100% !important;
|
||||
background-size: 75% 75%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
}
|
||||
.uw-button:hover{
|
||||
background-color: rgba(192,0,0,0.66);
|
||||
}
|
||||
.uw-setmenu{
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: rgba(0,0,0,0.66);
|
||||
right: 0px;
|
||||
}
|
||||
.uw-setmenu-item{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-family: "Oxygen";
|
||||
color: #ffffff !important;
|
||||
}
|
||||
.uw-setmenu-item:hover{
|
||||
background-color: rgba(192,0,0,0.66);
|
||||
}
|
||||
.uw_top{
|
||||
z-index: 1337;
|
||||
}
|
@ -5,7 +5,6 @@ document.getElementById("uw-version").textContent = browser.runtime.getManifest(
|
||||
|
||||
var Menu = {};
|
||||
// Menu.noVideo = document.getElementById("no-videos-display");
|
||||
Menu.general = document.getElementById("extension-mode");
|
||||
Menu.thisSite = document.getElementById("settings-for-current-site");
|
||||
Menu.arSettings = document.getElementById("aspect-ratio-settings");
|
||||
Menu.autoAr = document.getElementById("autoar-basic-settings");
|
||||
@ -38,8 +37,8 @@ AutoArPanel.globalOptions.blacklist = document.getElementById("_ar_global_option
|
||||
AutoArPanel.globalOptions.whitelist = document.getElementById("_ar_global_options_whitelist");
|
||||
AutoArPanel.globalOptions.disabled = document.getElementById("_ar_global_options_disabled");
|
||||
AutoArPanel.siteOptions = {};
|
||||
AutoArPanel.siteOptions.disabled = document.getElementById("_ar_site_options_blacklist");
|
||||
AutoArPanel.siteOptions.enabled = document.getElementById("_ar_site_options_whitelist");
|
||||
AutoArPanel.siteOptions.disabled = document.getElementById("_ar_site_options_disabled");
|
||||
AutoArPanel.siteOptions.enabled = document.getElementById("_ar_site_options_enabled");
|
||||
AutoArPanel.siteOptions.default = document.getElementById("_ar_site_options_default");
|
||||
|
||||
var ArPanel = {};
|
||||
@ -57,19 +56,31 @@ StretchPanel.global.hybrid = document.getElementById("_stretch_global_hybri
|
||||
StretchPanel.global.conditional = document.getElementById("_stretch_global_conditional");
|
||||
|
||||
|
||||
var selectedMenu = "arSettings";
|
||||
var selectedMenu = "";
|
||||
var hasVideos = false;
|
||||
|
||||
var _config;
|
||||
var _changeAr_button_shortcuts = { "autoar":"none", "reset":"none", "219":"none", "189":"none", "169":"none", "custom":"none" }
|
||||
|
||||
var comms = new Comms();
|
||||
var settings = new Settings(undefined, () => updateConfig());
|
||||
|
||||
var site = undefined;
|
||||
|
||||
var port = browser.runtime.connect({name: 'popup-port'});
|
||||
port.onMessage.addListener( (m,p) => processReceivedMessage(m,p));
|
||||
|
||||
|
||||
async function processReceivedMessage(message, port){
|
||||
if(message.cmd === 'set-config'){
|
||||
this.loadConfig(message.conf, message.site);
|
||||
if(message.cmd === 'set-current-site'){
|
||||
site = message.site;
|
||||
loadConfig(message.site);
|
||||
}
|
||||
}
|
||||
|
||||
async function updateConfig() {
|
||||
if (site) {
|
||||
loadConfig(site);
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,16 +106,47 @@ function stringToKeyCombo(key_in){
|
||||
return keys_out;
|
||||
}
|
||||
|
||||
function loadConfig(extensionConf, site){
|
||||
if(Debug.debug)
|
||||
console.log("[popup.js::loadConfig] loading config. conf object:", extensionConf, "\n\n\n\n\n\n\n\n-------------------------------------");
|
||||
|
||||
_extensionConf = extensionConf;
|
||||
async function loadConfig(site){
|
||||
|
||||
if(Debug.debug)
|
||||
console.log("[popup.js::loadConfig] loading config. conf object:", settings.active, "\n\n\n\n\n\n\n\n-------------------------------------");
|
||||
|
||||
// -----------------------
|
||||
//#region tab-disabled
|
||||
//
|
||||
// if extension is disabled on current site, we can't do shit. Therefore, the following tabs will be disabled:
|
||||
// * AutoAR options
|
||||
// * Crop settings
|
||||
// * Stretch settings
|
||||
var canStartExtension = settings.canStartExtension(site);
|
||||
|
||||
if (canStartExtension) {
|
||||
MenuTab.arSettings.classList.remove('disabled');
|
||||
MenuTab.autoAr.classList.remove('disabled');
|
||||
MenuTab.stretchSettings.classList.remove('disabled');
|
||||
|
||||
// only switch when popup is being opened for the first time
|
||||
if(! selectedMenu) {
|
||||
openMenu('arSettings');
|
||||
}
|
||||
} else {
|
||||
MenuTab.arSettings.classList.add('disabled');
|
||||
MenuTab.autoAr.classList.add('disabled');
|
||||
MenuTab.stretchSettings.classList.add('disabled');
|
||||
|
||||
// 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('thisSite');
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//
|
||||
// ----------------------
|
||||
//#region extension-basics - SET BASIC EXTENSION OPTIONS
|
||||
if(Debug.debug)
|
||||
console.log("EXT: site is:", site, "|extensionConf for this site: ", (site && extensionConf.sites[site]) ? extensionConf.sites[site] : "default site")
|
||||
console.log("EXT: site is:", site, "|settings for this site: ", (site && settings.active.sites[site]) ? settings.active.sites[site] : "default site")
|
||||
|
||||
|
||||
for(var button in ExtPanel.globalOptions) {
|
||||
@ -114,9 +156,9 @@ function loadConfig(extensionConf, site){
|
||||
ExtPanel.siteOptions[button].classList.remove("selected");
|
||||
}
|
||||
|
||||
ExtPanel.globalOptions[extensionConf.extensionMode].classList.add("selected");
|
||||
if(site && extensionConf.sites[site]) {
|
||||
ExtPanel.siteOptions[extensionConf.sites[site].status].classList.add("selected");
|
||||
ExtPanel.globalOptions[settings.active.extensionMode].classList.add("selected");
|
||||
if(site && settings.active.sites[site]) {
|
||||
ExtPanel.siteOptions[settings.active.sites[site].status].classList.add("selected");
|
||||
} else {
|
||||
ExtPanel.siteOptions.default.classList.add("selected");
|
||||
}
|
||||
@ -126,9 +168,9 @@ function loadConfig(extensionConf, site){
|
||||
// ------------
|
||||
//#region autoar - SET AUTOAR OPTIONS
|
||||
// if(Debug.debug)
|
||||
// console.log("Autodetect mode?", extensionConf.arDetect.mode, "| site & site options:", site, ",", (site && extensionConf.sites[site]) ? extensionConf.sites[site].arStatus : "fucky wucky?" );
|
||||
// document.getElementById("_autoAr_disabled_reason").textContent = extensionConf.arDetect.DisabledReason;
|
||||
document.getElementById("_input_autoAr_timer").value = extensionConf.arDetect.timer_playing;
|
||||
// console.log("Autodetect mode?", settings.active.arDetect.mode, "| site & site options:", site, ",", (site && settings.active.sites[site]) ? settings.active.sites[site].arStatus : "fucky wucky?" );
|
||||
// document.getElementById("_autoAr_disabled_reason").textContent = settings.active.arDetect.DisabledReason;
|
||||
document.getElementById("_input_autoAr_timer").value = settings.active.arDetect.timer_playing;
|
||||
|
||||
|
||||
for(var button in AutoArPanel.globalOptions) {
|
||||
@ -139,20 +181,20 @@ function loadConfig(extensionConf, site){
|
||||
}
|
||||
|
||||
|
||||
AutoArPanel.globalOptions[extensionConf.arDetect.mode].classList.add("selected");
|
||||
if(site && extensionConf.sites[site]) {
|
||||
AutoArPanel.siteOptions[extensionConf.sites[site].arStatus].classList.add("selected");
|
||||
AutoArPanel.globalOptions[settings.active.arDetect.mode].classList.add("selected");
|
||||
if(site && settings.active.sites[site]) {
|
||||
AutoArPanel.siteOptions[settings.active.sites[site].arStatus].classList.add("selected");
|
||||
} else {
|
||||
AutoArPanel.siteOptions.default.classList.add("selected");
|
||||
}
|
||||
//#endregion
|
||||
|
||||
// process video alignment:
|
||||
if(extensionConf.miscFullscreenSettings.videoFloat){
|
||||
if(settings.active.miscFullscreenSettings.videoFloat){
|
||||
for(var button in ArPanel.alignment)
|
||||
ArPanel.alignment[button].classList.remove("selected");
|
||||
|
||||
ArPanel.alignment[extensionConf.miscFullscreenSettings.videoFloat].classList.add("selected");
|
||||
ArPanel.alignment[settings.active.miscFullscreenSettings.videoFloat].classList.add("selected");
|
||||
}
|
||||
|
||||
//#region - SET STRETCH
|
||||
@ -161,21 +203,21 @@ function loadConfig(extensionConf, site){
|
||||
for (var button in StretchPanel.global) {
|
||||
StretchPanel.global[button].classList.remove("selected");
|
||||
}
|
||||
if (extensionConf.stretch.initialMode === 0) {
|
||||
if (settings.active.stretch.initialMode === 0) {
|
||||
StretchPanel.global.none.classList.add("selected");
|
||||
} else if (extensionConf.stretch.initialMode === 1) {
|
||||
} else if (settings.active.stretch.initialMode === 1) {
|
||||
StretchPanel.global.basic.classList.add("selected");
|
||||
} else if (extensionConf.stretch.initialMode === 2) {
|
||||
} else if (settings.active.stretch.initialMode === 2) {
|
||||
StretchPanel.global.hybrid.classList.add("selected");
|
||||
} else if (extensionConf.stretch.initialMode === 3) {
|
||||
} else if (settings.active.stretch.initialMode === 3) {
|
||||
StretchPanel.global.conditional.classList.add("selected");
|
||||
}
|
||||
//#endregion
|
||||
|
||||
// process keyboard shortcuts:
|
||||
if(extensionConf.keyboard.shortcuts){
|
||||
for(var key in extensionConf.keyboard.shortcuts){
|
||||
var shortcut = extensionConf.keyboard.shortcuts[key];
|
||||
if(settings.active.keyboard.shortcuts){
|
||||
for(var key in settings.active.keyboard.shortcuts){
|
||||
var shortcut = settings.active.keyboard.shortcuts[key];
|
||||
var keypress = stringToKeyCombo(key);
|
||||
|
||||
|
||||
@ -212,8 +254,8 @@ function loadConfig(extensionConf, site){
|
||||
}
|
||||
|
||||
// fill in custom aspect ratio
|
||||
if (extensionConf.keyboard.shortcuts.q) {
|
||||
document.getElementById("_input_custom_ar").value = extensionConf.keyboard.shortcuts.q.arg;
|
||||
if (settings.active.keyboard.shortcuts.q) {
|
||||
document.getElementById("_input_custom_ar").value = settings.active.keyboard.shortcuts.q.arg;
|
||||
}
|
||||
}
|
||||
for(var key in _changeAr_button_shortcuts){
|
||||
@ -231,8 +273,8 @@ function loadConfig(extensionConf, site){
|
||||
console.log("[popup.js::loadConfig] config loaded");
|
||||
}
|
||||
|
||||
async function getConf(){
|
||||
port.postMessage({cmd: 'get-config'});
|
||||
async function getSite(){
|
||||
port.postMessage({cmd: 'get-current-site'});
|
||||
}
|
||||
|
||||
function openMenu(menu){
|
||||
@ -241,6 +283,9 @@ function openMenu(menu){
|
||||
}
|
||||
|
||||
for(var m in Menu){
|
||||
if(Menu[m] === null)
|
||||
continue; //todo: remove menus that are no longer there
|
||||
|
||||
Menu[m].classList.add("hidden");
|
||||
}
|
||||
for(var m in MenuTab){
|
||||
@ -269,51 +314,6 @@ function openMenu(menu){
|
||||
MenuTab[menu].classList.add("selected");
|
||||
}
|
||||
|
||||
function _arctl_onclick(command){
|
||||
if(! _config)
|
||||
return;
|
||||
|
||||
if(command.cmd == "stop-autoar")
|
||||
_config.arConf.enabled_current = false;
|
||||
else if(command.cmd == "force-ar")
|
||||
_config.arConf.enabled_current = true;
|
||||
else if(command.cmd == "disable-autoar")
|
||||
_config.arConf.enabled_global = false;
|
||||
else if(command.cmd == "enable-autoar")
|
||||
_config.arConf.enabled_global = true;
|
||||
|
||||
showArctlButtons();
|
||||
}
|
||||
|
||||
function showArctlButtons(){
|
||||
if(! _config)
|
||||
return;
|
||||
|
||||
// if(_config.arConf){
|
||||
// if(! _config.arConf.enabled_global){
|
||||
// ArPanel.autoar.disable.classList.add("hidden");
|
||||
// ArPanel.autoar.enable.classList.remove("hidden");
|
||||
|
||||
// ArPanel.autoar.enable_tmp.textContent = "Temporarily enable";
|
||||
// ArPanel.autoar.disable_tmp.textContent = "Temporarily disable";
|
||||
// }
|
||||
// else{
|
||||
// ArPanel.autoar.disable.classList.remove("hidden");
|
||||
// ArPanel.autoar.enable.classList.add("hidden");
|
||||
|
||||
// ArPanel.autoar.enable_tmp.textContent = "Re-enable";
|
||||
// ArPanel.autoar.disable_tmp.textContent = "Temporarily disable";
|
||||
// }
|
||||
// if(! _config.arConf.enabled_current){
|
||||
// ArPanel.autoar.disable_tmp.classList.add("hidden");
|
||||
// ArPanel.autoar.enable_tmp.classList.remove("hidden");
|
||||
// }
|
||||
// else{
|
||||
// ArPanel.autoar.disable_tmp.classList.remove("hidden");
|
||||
// ArPanel.autoar.enable_tmp.classList.add("hidden");
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
function getCustomAspectRatio() {
|
||||
var textBox_value = document.getElementById("_input_custom_ar").value.trim();
|
||||
@ -358,9 +358,9 @@ function validateCustomAr(){
|
||||
|
||||
function validateAutoArTimeout(){
|
||||
const inputField = document.getElementById("_input_autoAr_timer");
|
||||
const valueSaveButton = document.getElementById("_b_autoar_save_autoar_frequency");
|
||||
const valueSaveButton = document.getElementById("_b_autoar_save_autoar_timer");
|
||||
|
||||
if (! isNaN(parseInt(inputField.trim().value()))) {
|
||||
if (! isNaN(parseInt(inputField.value.trim().value()))) {
|
||||
inputField.classList.remove("invalid-input");
|
||||
valueSaveButton.classList.remove("disabled-button");
|
||||
} else {
|
||||
@ -369,28 +369,10 @@ function validateAutoArTimeout(){
|
||||
}
|
||||
}
|
||||
|
||||
function toggleSite(option){
|
||||
if(Debug.debug)
|
||||
console.log("[popup::toggleSite] toggling extension 'should I work' status to", option, "on current site");
|
||||
|
||||
Comms.sendToBackgroundScript({cmd:"enable-for-site", option:option});
|
||||
}
|
||||
|
||||
function getMode(isEnabled, whitelistOnly) {
|
||||
if(isEnabled) {
|
||||
return whitelistOnly ? "whitelist" : "blacklist"
|
||||
} else {
|
||||
return "disabled";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
document.addEventListener("click", (e) => {
|
||||
|
||||
|
||||
function getcmd(e){
|
||||
|
||||
|
||||
var command = {};
|
||||
command.sender = "popup";
|
||||
command.receiver = "uwbg";
|
||||
@ -399,9 +381,6 @@ document.addEventListener("click", (e) => {
|
||||
return;
|
||||
|
||||
if(e.target.classList.contains("menu-item")){
|
||||
if(e.target.classList.contains("_menu_general")){
|
||||
openMenu("general");
|
||||
}
|
||||
if(e.target.classList.contains("_menu_this_site")){
|
||||
openMenu("thisSite");
|
||||
}
|
||||
@ -427,25 +406,38 @@ document.addEventListener("click", (e) => {
|
||||
if(e.target.classList.contains("_ext")) {
|
||||
var command = {};
|
||||
if(e.target.classList.contains("_ext_global_options")){
|
||||
command.cmd = "set-extension-defaults";
|
||||
if (e.target.classList.contains("_blacklist")) {
|
||||
command.mode = "blacklist";
|
||||
settings.active.extensionMode = "blacklist";
|
||||
} else if (e.target.classList.contains("_whitelist")) {
|
||||
command.mode = "whitelist";
|
||||
settings.active.extensionMode = "whitelist";
|
||||
} else {
|
||||
command.mode = "disabled";
|
||||
settings.active.extensionMode = "disabled";
|
||||
}
|
||||
return command;
|
||||
settings.save();
|
||||
return;
|
||||
} else if (e.target.classList.contains("_ext_site_options")) {
|
||||
command.cmd = "set-extension-for-site";
|
||||
var mode;
|
||||
if(e.target.classList.contains("_blacklist")){
|
||||
command.mode = "disabled";
|
||||
mode = "disabled";
|
||||
} else if(e.target.classList.contains("_whitelist")) {
|
||||
command.mode = "enabled";
|
||||
mode = "enabled";
|
||||
} else {
|
||||
command.mode = "default";
|
||||
mode = "default";
|
||||
}
|
||||
return command;
|
||||
|
||||
if(settings.active.sites[site]) {
|
||||
settings.active.sites[site].status = mode;
|
||||
settings.active.sites[site].statusEmbedded = mode;
|
||||
} else {
|
||||
settings.active.sites[site] = {
|
||||
status: mode,
|
||||
statusEmbedded: mode,
|
||||
arStatus: 'default',
|
||||
type: 'user-defined'
|
||||
}
|
||||
}
|
||||
settings.save();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(e.target.classList.contains("_changeAr")){
|
||||
@ -504,17 +496,17 @@ document.addEventListener("click", (e) => {
|
||||
}
|
||||
if(e.target.classList.contains("_stretch")){
|
||||
if (e.target.classList.contains("_ar_stretch_global")) {
|
||||
command.cmd = "set-stretch-default"
|
||||
if (e.target.classList.contains("_none")) {
|
||||
command.mode = 0;
|
||||
settings.active.stretch.initialMode = 0;
|
||||
} else if (e.target.classList.contains("_basic")) {
|
||||
command.mode = 1;
|
||||
settings.active.stretch.initialMode = 1;
|
||||
} else if (e.target.classList.contains("_hybrid")) {
|
||||
command.mode = 2;
|
||||
settings.active.stretch.initialMode = 2;
|
||||
} else if (e.target.classList.contains("_conditional")) {
|
||||
command.mode = 3;
|
||||
settings.active.stretch.initialMode = 3;
|
||||
}
|
||||
return command;
|
||||
settings.save();
|
||||
return;
|
||||
}
|
||||
|
||||
if(e.target.classList.contains("_ar_stretch_none")) {
|
||||
@ -533,52 +525,47 @@ document.addEventListener("click", (e) => {
|
||||
return command;
|
||||
}
|
||||
if(e.target.classList.contains("_autoAr")){
|
||||
|
||||
var command = {};
|
||||
if(e.target.classList.contains("_ext_global_options")){
|
||||
command.cmd = "set-autoar-defaults";
|
||||
if(e.target.classList.contains("_ar_global_options")){
|
||||
if (e.target.classList.contains("_blacklist")) {
|
||||
command.mode = "blacklist";
|
||||
settings.active.arDetect.mode = "blacklist";
|
||||
} else if (e.target.classList.contains("_whitelist")) {
|
||||
command.mode = "whitelist";
|
||||
settings.active.arDetect.mode = "whitelist";
|
||||
} else {
|
||||
command.mode = "disabled";
|
||||
settings.active.arDetect.mode = "disabled";
|
||||
}
|
||||
return command;
|
||||
} else if (e.target.classList.contains("_autoAr_whitelist-only")) {
|
||||
var arStatus = document.getElementById("_checkbox_autoar-enabled").checked;
|
||||
var whitelist = document.getElementById("_checkbox_autoar-whitelist").checked;
|
||||
|
||||
|
||||
if(Debug.debug) {
|
||||
console.log("CHANGED CHECKMARK IN _AR-WHTIELIST:", extStatus, whitelist)
|
||||
}
|
||||
|
||||
return {
|
||||
cmd: "set-autoar-mode",
|
||||
mode: getMode(arStatus, whitelist),
|
||||
sender: "popup",
|
||||
receiver: "uwbg"
|
||||
};
|
||||
} else if (e.target.classList.contains("_save_autoAr_frequency")) {
|
||||
var value = parseInt(document.getElementById("_input_autoAr_frequency").value.trim());
|
||||
settings.save();
|
||||
return;
|
||||
} else if (e.target.classList.contains("_save_autoAr_timer")) {
|
||||
var value = parseInt(document.getElementById("_input_autoAr_timer").value.trim());
|
||||
|
||||
if(! isNaN(value)){
|
||||
var timeout = parseInt(value);
|
||||
command = {cmd: "autoar-set-timer-playing", timeout: timeout, sender: "popup", receiver: "uwbg"};
|
||||
Comms.sendToBackgroundScript(command);
|
||||
settings.active.arDetect.timer_playing = timeout;
|
||||
settings.save();
|
||||
}
|
||||
return;
|
||||
} else if (e.target.classList.contains("_ar_site_options")) {
|
||||
command.cmd = "set-autoar-for-site";
|
||||
if(e.target.classList.contains("_blacklist")){
|
||||
command.mode = "disabled";
|
||||
} else if(e.target.classList.contains("_whitelist")) {
|
||||
command.mode = "enabled";
|
||||
var mode;
|
||||
if(e.target.classList.contains("_disabled")){
|
||||
mode = "disabled";
|
||||
} else if(e.target.classList.contains("_enabled")) {
|
||||
mode = "enabled";
|
||||
} else {
|
||||
command.mode = "default";
|
||||
mode = "default";
|
||||
}
|
||||
return command;
|
||||
|
||||
if(settings.active.sites[site]) {
|
||||
settings.active.sites[site].arStatus = mode;
|
||||
} else {
|
||||
settings.active.sites[site] = {
|
||||
status: settings.active.extensionMode,
|
||||
statusEmbedded: settings.active.extensionMode,
|
||||
arStatus: mode,
|
||||
type: 'user-defined'
|
||||
}
|
||||
}
|
||||
settings.save();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -586,29 +573,17 @@ document.addEventListener("click", (e) => {
|
||||
|
||||
command.global = true;
|
||||
|
||||
if(e.target.classList.contains("_align_left")){
|
||||
command.cmd = "set-video-float",
|
||||
command.newFloat = "left"
|
||||
|
||||
// console.log(".................\n\n\n..........\n\n >>command<< \n\n\n\n ",command,"\n\n\n.........\n\n\n................................");
|
||||
|
||||
return command;
|
||||
if (e.target.classList.contains("_align_left")) {
|
||||
settings.active.miscFullscreenSettings.videoFloat = 'left';
|
||||
} else if (e.target.classList.contains("_align_center")) {
|
||||
settings.active.miscFullscreenSettings.videoFloat = 'center';
|
||||
} else if (e.target.classList.contains("_align_right")) {
|
||||
settings.active.miscFullscreenSettings.videoFloat = 'left';
|
||||
}
|
||||
if(e.target.classList.contains("_align_center")){
|
||||
command.cmd = "set-video-float"
|
||||
command.newFloat = "center"
|
||||
return command;
|
||||
}
|
||||
if(e.target.classList.contains("_align_right")){
|
||||
command.cmd = "set-video-float";
|
||||
command.newFloat = "right";
|
||||
return command;
|
||||
}
|
||||
}
|
||||
if(e.target.classList.contains("extensionEnabledOnCurrentSite")){ // legacy? can be removed?
|
||||
toggleSite(document.extensionEnabledOnCurrentSite.mode.value);
|
||||
}
|
||||
|
||||
|
||||
settings.save();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var command = getcmd(e);
|
||||
@ -618,23 +593,39 @@ document.addEventListener("click", (e) => {
|
||||
return true;
|
||||
});
|
||||
|
||||
const customArInputField = document.getElementById("_input_custom_ar");
|
||||
const autoarFrequencyInputField = document.getElementById("_input_autoAr_timer");
|
||||
|
||||
customArInputField.addEventListener("blur", (event) => {
|
||||
validateCustomAr();
|
||||
});
|
||||
customArInputField.addEventListener("mouseleave", (event) => {
|
||||
validateCustomAr();
|
||||
});
|
||||
|
||||
autoarFrequencyInputField.addEventListener("blur", (event) => {
|
||||
validateAutoArTimeout();
|
||||
});
|
||||
autoarFrequencyInputField.addEventListener("mouseleave", (event) => {
|
||||
validateAutoArTimeout();
|
||||
});
|
||||
|
||||
hideWarning("script-not-running-warning");
|
||||
openMenu(selectedMenu);
|
||||
getConf();
|
||||
|
||||
|
||||
async function popup_init() {
|
||||
// let's init settings and check if they're loaded
|
||||
await settings.init();
|
||||
|
||||
if (Debug.debug) {
|
||||
console.log("[popup] Are settings loaded?", settings)
|
||||
}
|
||||
|
||||
|
||||
const customArInputField = document.getElementById("_input_custom_ar");
|
||||
const autoarFrequencyInputField = document.getElementById("_input_autoAr_timer");
|
||||
|
||||
customArInputField.addEventListener("blur", (event) => {
|
||||
validateCustomAr();
|
||||
});
|
||||
customArInputField.addEventListener("mouseleave", (event) => {
|
||||
validateCustomAr();
|
||||
});
|
||||
|
||||
autoarFrequencyInputField.addEventListener("blur", (event) => {
|
||||
validateAutoArTimeout();
|
||||
});
|
||||
autoarFrequencyInputField.addEventListener("mouseleave", (event) => {
|
||||
validateAutoArTimeout();
|
||||
});
|
||||
|
||||
hideWarning("script-not-running-warning");
|
||||
getSite();
|
||||
}
|
||||
|
||||
popup_init();
|
@ -5,6 +5,7 @@
|
||||
<meta charset="utf-8">
|
||||
<link rel='stylesheet' type='text/css' href='../css/font/overpass.css'>
|
||||
<link rel='stylesheet' type='text/css' href='../css/font/overpass-mono.css'>
|
||||
<link rel='stylesheet' type='text/css' href='../css/uw-common.css'>
|
||||
<style>
|
||||
|
||||
html, body {
|
||||
@ -20,33 +21,10 @@
|
||||
}
|
||||
strike {
|
||||
opacity: 0.5;
|
||||
}
|
||||
a {
|
||||
color: #af7f37;
|
||||
}
|
||||
a:hover {
|
||||
color: #c0924e;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
border: 1px solid #322;
|
||||
padding: 0.5em;
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
small{
|
||||
font-size: 0.75em;
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
.small {
|
||||
font-size: 0.85em;
|
||||
}
|
||||
.darker {
|
||||
color: #666;
|
||||
}
|
||||
@ -56,11 +34,7 @@
|
||||
font-weight: 600;
|
||||
color: #ffe;
|
||||
}
|
||||
|
||||
.smallcaps{
|
||||
font-variant: small-caps;
|
||||
}
|
||||
|
||||
|
||||
.selected{
|
||||
color: #ffddaa;
|
||||
background-color: #433221;
|
||||
@ -76,10 +50,7 @@
|
||||
color: #777 !important;
|
||||
background-color: #222 !important;
|
||||
}
|
||||
.invalid-input {
|
||||
border: 1px solid #720 !important;
|
||||
background-color: #410 !important;
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: #7f1416;
|
||||
color: #fff;
|
||||
@ -126,66 +97,13 @@
|
||||
min-height: 250px;
|
||||
}
|
||||
|
||||
.button {
|
||||
display: inline-block;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 3px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
border: 1px solid #444;
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
color: #dbb;
|
||||
text-align: center;
|
||||
}
|
||||
.w24 {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.color_warn {
|
||||
color: #d6ba4a;
|
||||
}
|
||||
.warning {
|
||||
/*background-*/color: #d6ba4a;
|
||||
/* color: #000; */
|
||||
padding-left: 35px;
|
||||
float: right;
|
||||
}
|
||||
.warning::before {
|
||||
content: "⚠ ";
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
font-size: 2.5em;
|
||||
margin-left: -35px;
|
||||
padding-right: 10px;
|
||||
/* top: 0px; */
|
||||
float: left;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
color: #fff;
|
||||
background-color: #433221;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: block;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.button-row {
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#no-videos-display {
|
||||
height: 100%;
|
||||
padding-top: 50px;
|
||||
/* text-align: center; */
|
||||
}
|
||||
.center{
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -214,24 +132,7 @@
|
||||
</div>
|
||||
<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="extension-mode" class="suboption hidden">
|
||||
<p>How should extension work in general?<br/><small>NOTE: settings will be applied when page is reloaded.</small></p>
|
||||
|
||||
<form action="">
|
||||
<input type="radio" name="mode" value="white"> Enable everywhere except blacklist<br/>
|
||||
<input type="radio" name="mode" value="black"> Enable only on whitelisted sites<br/>
|
||||
<input type="radio" name="mode" value="block"> Disable extension on all sites
|
||||
</form>
|
||||
|
||||
<p>How should extension work on this site?<br><small class="important">NOTE: this doesn't apply to embedded videos!<br/>NOTE: settings will be applied when page is reloaded.</small></p>
|
||||
<form action="">
|
||||
<input type="radio" name="mode" value="default"> Follow global rules<br/>
|
||||
<input type="radio" name="mode" value="black"> Always block (blacklist)<br/>
|
||||
<input type="radio" name="mode" value="white"> Always allow (whitelist)
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="settings-for-current-site" class="suboption hidden">
|
||||
<div class="warn">Some settings will only apply after reload. Settings don't apply to videos embedded from other sites.</div>
|
||||
|
||||
@ -247,9 +148,9 @@
|
||||
<div class="row">
|
||||
<span class="label">Options for this site:</span>
|
||||
<div class="button-row">
|
||||
<a id="_ext_site_options_blacklist" class="button _ext _ext_site_options _blacklist">Blacklist</a>
|
||||
<a id="_ext_site_options_default" class="button _ext _ext_site_options _default" >Default</a>
|
||||
<a id="_ext_site_options_whitelist" class="button _ext _ext_site_options _whitelist">Whitelist</a>
|
||||
<a id="_ext_site_options_default" class="button _ext _ext_site_options _default" >Default</a>
|
||||
<a id="_ext_site_options_blacklist" class="button _ext _ext_site_options _blacklist">Blacklist</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -265,14 +166,14 @@
|
||||
</div>
|
||||
<!-- <p><small class="color_warn" id="_autoAr_disabled_reason"></small><br/> -->
|
||||
|
||||
<p>Check every <input id="_input_autoAr_timer" class="_autoAr _autoAr_timer" type="number" min="5" max="10000"> ms — <span id="_b_autoar_save_autoar_frequency" class="button _save_autoAr_frequency _autoAr">Save</span></p>
|
||||
<p>Check every <input id="_input_autoAr_timer" class="_autoAr _autoAr_timer" type="number" min="5" max="10000"> ms — <span id="_b_autoar_save_autoar_timer" class="button _save_autoAr_timer _autoAr">Save</span></p>
|
||||
|
||||
<div class="row">
|
||||
<span class="label">Options for this site:</span>
|
||||
<div class="button-row">
|
||||
<a id="_ar_site_options_blacklist" class="button _autoAr _ar_site_options _blacklist">Blacklist</a>
|
||||
<a id="_ar_site_options_default" class="button _autoAr _ar_site_options _default" >Default</a>
|
||||
<a id="_ar_site_options_whitelist" class="button _autoAr _ar_site_options _whitelist">Whitelist</a>
|
||||
<a id="_ar_site_options_enabled" class="button _autoAr _ar_site_options _enabled" >Whitelist</a>
|
||||
<a id="_ar_site_options_default" class="button _autoAr _ar_site_options _default" >Default</a>
|
||||
<a id="_ar_site_options_disabled" class="button _autoAr _ar_site_options _disabled">Blacklist</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -356,10 +257,10 @@
|
||||
<script src="../../js/conf/Debug.js"></script>
|
||||
|
||||
<script src="../../js/lib/BrowserDetect.js"></script>
|
||||
<script src="../../js/lib/StorageManager.js"></script>
|
||||
<script src="../../js/lib/Comms.js"></script>
|
||||
|
||||
<script src="../../js/conf/Settings.js"></script>
|
||||
<script src="../../js/conf/ExtensionConf.js"></script>
|
||||
<script src="../../js/lib/Settings.js"></script>
|
||||
|
||||
<script src="./js/popup.js"></script>
|
||||
</body>
|
||||
|
202
res/settings/settings.css
Normal file
202
res/settings/settings.css
Normal file
@ -0,0 +1,202 @@
|
||||
@import url("../css/font/overpass.css");
|
||||
@import url("../css/font/overpass-mono.css");
|
||||
|
||||
body {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAAUVBMVEWFhYWDg4N3d3dtbW17e3t1dXWBgYGHh4d5eXlzc3OLi4ubm5uVlZWPj4+NjY19fX2JiYl/f39ra2uRkZGZmZlpaWmXl5dvb29xcXGTk5NnZ2c8TV1mAAAAG3RSTlNAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAvEOwtAAAFVklEQVR4XpWWB67c2BUFb3g557T/hRo9/WUMZHlgr4Bg8Z4qQgQJlHI4A8SzFVrapvmTF9O7dmYRFZ60YiBhJRCgh1FYhiLAmdvX0CzTOpNE77ME0Zty/nWWzchDtiqrmQDeuv3powQ5ta2eN0FY0InkqDD73lT9c9lEzwUNqgFHs9VQce3TVClFCQrSTfOiYkVJQBmpbq2L6iZavPnAPcoU0dSw0SUTqz/GtrGuXfbyyBniKykOWQWGqwwMA7QiYAxi+IlPdqo+hYHnUt5ZPfnsHJyNiDtnpJyayNBkF6cWoYGAMY92U2hXHF/C1M8uP/ZtYdiuj26UdAdQQSXQErwSOMzt/XWRWAz5GuSBIkwG1H3FabJ2OsUOUhGC6tK4EMtJO0ttC6IBD3kM0ve0tJwMdSfjZo+EEISaeTr9P3wYrGjXqyC1krcKdhMpxEnt5JetoulscpyzhXN5FRpuPHvbeQaKxFAEB6EN+cYN6xD7RYGpXpNndMmZgM5Dcs3YSNFDHUo2LGfZuukSWyUYirJAdYbF3MfqEKmjM+I2EfhA94iG3L7uKrR+GdWD73ydlIB+6hgref1QTlmgmbM3/LeX5GI1Ux1RWpgxpLuZ2+I+IjzZ8wqE4nilvQdkUdfhzI5QDWy+kw5Wgg2pGpeEVeCCA7b85BO3F9DzxB3cdqvBzWcmzbyMiqhzuYqtHRVG2y4x+KOlnyqla8AoWWpuBoYRxzXrfKuILl6SfiWCbjxoZJUaCBj1CjH7GIaDbc9kqBY3W/Rgjda1iqQcOJu2WW+76pZC9QG7M00dffe9hNnseupFL53r8F7YHSwJWUKP2q+k7RdsxyOB11n0xtOvnW4irMMFNV4H0uqwS5ExsmP9AxbDTc9JwgneAT5vTiUSm1E7BSflSt3bfa1tv8Di3R8n3Af7MNWzs49hmauE2wP+ttrq+AsWpFG2awvsuOqbipWHgtuvuaAE+A1Z/7gC9hesnr+7wqCwG8c5yAg3AL1fm8T9AZtp/bbJGwl1pNrE7RuOX7PeMRUERVaPpEs+yqeoSmuOlokqw49pgomjLeh7icHNlG19yjs6XXOMedYm5xH2YxpV2tc0Ro2jJfxC50ApuxGob7lMsxfTbeUv07TyYxpeLucEH1gNd4IKH2LAg5TdVhlCafZvpskfncCfx8pOhJzd76bJWeYFnFciwcYfubRc12Ip/ppIhA1/mSZ/RxjFDrJC5xifFjJpY2Xl5zXdguFqYyTR1zSp1Y9p+tktDYYSNflcxI0iyO4TPBdlRcpeqjK/piF5bklq77VSEaA+z8qmJTFzIWiitbnzR794USKBUaT0NTEsVjZqLaFVqJoPN9ODG70IPbfBHKK+/q/AWR0tJzYHRULOa4MP+W/HfGadZUbfw177G7j/OGbIs8TahLyynl4X4RinF793Oz+BU0saXtUHrVBFT/DnA3ctNPoGbs4hRIjTok8i+algT1lTHi4SxFvONKNrgQFAq2/gFnWMXgwffgYMJpiKYkmW3tTg3ZQ9Jq+f8XN+A5eeUKHWvJWJ2sgJ1Sop+wwhqFVijqWaJhwtD8MNlSBeWNNWTa5Z5kPZw5+LbVT99wqTdx29lMUH4OIG/D86ruKEauBjvH5xy6um/Sfj7ei6UUVk4AIl3MyD4MSSTOFgSwsH/QJWaQ5as7ZcmgBZkzjjU1UrQ74ci1gWBCSGHtuV1H2mhSnO3Wp/3fEV5a+4wz//6qy8JxjZsmxxy5+4w9CDNJY09T072iKG0EnOS0arEYgXqYnXcYHwjTtUNAcMelOd4xpkoqiTYICWFq0JSiPfPDQdnt+4/wuqcXY47QILbgAAAABJRU5ErkJggg==);
|
||||
background-size: 75px;
|
||||
background-color: #000000;
|
||||
color: #ddd;
|
||||
font-family: 'overpass', serif;
|
||||
font-size: 1.2em;
|
||||
width: 100%;
|
||||
border: 0px;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
text-align: center;
|
||||
z-index: -1000;
|
||||
}
|
||||
|
||||
a, a:visited{
|
||||
color: #fa6607;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover{
|
||||
color: #fa6;
|
||||
}
|
||||
|
||||
.show{
|
||||
display: block !important;
|
||||
}
|
||||
.hide{
|
||||
display: none !important;
|
||||
}
|
||||
head{
|
||||
width: 100%;
|
||||
border: 0px;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
h1,h2{
|
||||
color: #ff9;
|
||||
font-weight: 300;
|
||||
}
|
||||
h1{
|
||||
font-size: 3.3em;
|
||||
}
|
||||
h2{
|
||||
font-size: 2.2em;
|
||||
}
|
||||
.sites_header{
|
||||
font-size: 1.6em;
|
||||
color: #ff9;
|
||||
}
|
||||
.content{
|
||||
display: inline-block;
|
||||
width: 52em;
|
||||
}
|
||||
.center{
|
||||
margin: 0 auto;
|
||||
}
|
||||
.basecolor {
|
||||
color: #ddd !important;
|
||||
}
|
||||
.red{
|
||||
color: #ff3a00;
|
||||
}
|
||||
.disabled {
|
||||
opacity: 0.69;
|
||||
}
|
||||
.left {
|
||||
text-align: left;
|
||||
}
|
||||
.block {
|
||||
display: inline-block;
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
.tabline {
|
||||
background-color: #000;
|
||||
width: 100%;
|
||||
margin-bottom: 1.5em;
|
||||
padding-top: 0.3em;
|
||||
padding-bottom: 0.4em;
|
||||
z-index: -200;
|
||||
}
|
||||
.tab {
|
||||
color: #fa6607;
|
||||
}
|
||||
.tab:hover{
|
||||
text-shadow: #aa5 0px 0px 0.02em,#aa5 0px 0px 0.02em;
|
||||
}
|
||||
.tab-selected {
|
||||
color: #ff9 !important;
|
||||
}
|
||||
#all{
|
||||
min-width: 100%;
|
||||
min-height: 100vh;
|
||||
background-image: url('img/settings/about-bg.png');
|
||||
background-position: calc(50vw + 20em) 10vh;
|
||||
background-attachment: fixed;
|
||||
background-size: auto 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.dup_keybinds{
|
||||
background-color: #720 !important;
|
||||
}
|
||||
input[type=text]{
|
||||
font-size: 1em;
|
||||
padding-left: 0.6em;
|
||||
margin-left: 1em;
|
||||
width: 2em;
|
||||
background-color: #000;
|
||||
border: 1px #442 solid;
|
||||
}
|
||||
.uw_shortcuts_line{
|
||||
padding-top: 0.25em;
|
||||
padding-left: 5em;
|
||||
}
|
||||
.uw_shortcuts_label{
|
||||
display: inline-block;
|
||||
color: #fff;
|
||||
width: 17.5em;
|
||||
}
|
||||
.uw_options_line{
|
||||
margin-top: 0.75em;
|
||||
font-size: 1.1em;
|
||||
width: 80%;
|
||||
margin-left: 5%;
|
||||
}
|
||||
.uw_options_option{
|
||||
margin-left: 5%;
|
||||
}
|
||||
.uw_suboption{
|
||||
margin-left: 5em;
|
||||
margin-top: 0.75em;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
.uw_options_desc, .uw_suboption_desc{
|
||||
margin-top: 0.33em;
|
||||
font-size: 0.69em;
|
||||
color: #aaa;
|
||||
}
|
||||
.uw_suboption_desc{
|
||||
margin-left: 5em;
|
||||
}
|
||||
|
||||
.buttonbar{
|
||||
/* width: 100%; */
|
||||
padding-left: 20em;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
.button{
|
||||
display: inline-block;
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
padding-top: 0.4em;
|
||||
width: 4em;
|
||||
text-align: center;
|
||||
background-color: rgba(0,0,0,0.66);
|
||||
color: #ffc;
|
||||
height: 1.7em;
|
||||
}
|
||||
|
||||
/** site options css **/
|
||||
.site_name {
|
||||
padding-left: 1em;
|
||||
padding-bottom: 0.3em;
|
||||
color: #fff;
|
||||
font-size: 1.1em;
|
||||
height: 13em !important;
|
||||
|
||||
}
|
||||
.site_details {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.site_title_ebox {
|
||||
width: 10em !important;
|
||||
font-size: 1.5em !important;
|
||||
background-color: rgba(0,0,0,0) !important;
|
||||
margin-left: 0px !important;
|
||||
border: 0px !important;
|
||||
color: #ffc !important;
|
||||
}
|
||||
.details_ebox {
|
||||
width: 12em !important;
|
||||
background-color: rgba(0,0,0,0) !important;
|
||||
border: 0px !important;
|
||||
color: #ffc !important;
|
||||
margin-left: 0em !important;
|
||||
}
|
||||
.details_ebox:disabled {
|
||||
color: #aaa !important;
|
||||
}
|
||||
.inline_button {
|
||||
display: inline-block;
|
||||
margin-top: -1.42em;
|
||||
}
|
||||
.inline_button:hover {
|
||||
color: #fff;
|
||||
}
|
@ -4,213 +4,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<base target="_blank">
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css?family=Oxygen:300,400&subset=latin-ext');
|
||||
|
||||
body{
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAMAAAAp4XiDAAAAUVBMVEWFhYWDg4N3d3dtbW17e3t1dXWBgYGHh4d5eXlzc3OLi4ubm5uVlZWPj4+NjY19fX2JiYl/f39ra2uRkZGZmZlpaWmXl5dvb29xcXGTk5NnZ2c8TV1mAAAAG3RSTlNAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAvEOwtAAAFVklEQVR4XpWWB67c2BUFb3g557T/hRo9/WUMZHlgr4Bg8Z4qQgQJlHI4A8SzFVrapvmTF9O7dmYRFZ60YiBhJRCgh1FYhiLAmdvX0CzTOpNE77ME0Zty/nWWzchDtiqrmQDeuv3powQ5ta2eN0FY0InkqDD73lT9c9lEzwUNqgFHs9VQce3TVClFCQrSTfOiYkVJQBmpbq2L6iZavPnAPcoU0dSw0SUTqz/GtrGuXfbyyBniKykOWQWGqwwMA7QiYAxi+IlPdqo+hYHnUt5ZPfnsHJyNiDtnpJyayNBkF6cWoYGAMY92U2hXHF/C1M8uP/ZtYdiuj26UdAdQQSXQErwSOMzt/XWRWAz5GuSBIkwG1H3FabJ2OsUOUhGC6tK4EMtJO0ttC6IBD3kM0ve0tJwMdSfjZo+EEISaeTr9P3wYrGjXqyC1krcKdhMpxEnt5JetoulscpyzhXN5FRpuPHvbeQaKxFAEB6EN+cYN6xD7RYGpXpNndMmZgM5Dcs3YSNFDHUo2LGfZuukSWyUYirJAdYbF3MfqEKmjM+I2EfhA94iG3L7uKrR+GdWD73ydlIB+6hgref1QTlmgmbM3/LeX5GI1Ux1RWpgxpLuZ2+I+IjzZ8wqE4nilvQdkUdfhzI5QDWy+kw5Wgg2pGpeEVeCCA7b85BO3F9DzxB3cdqvBzWcmzbyMiqhzuYqtHRVG2y4x+KOlnyqla8AoWWpuBoYRxzXrfKuILl6SfiWCbjxoZJUaCBj1CjH7GIaDbc9kqBY3W/Rgjda1iqQcOJu2WW+76pZC9QG7M00dffe9hNnseupFL53r8F7YHSwJWUKP2q+k7RdsxyOB11n0xtOvnW4irMMFNV4H0uqwS5ExsmP9AxbDTc9JwgneAT5vTiUSm1E7BSflSt3bfa1tv8Di3R8n3Af7MNWzs49hmauE2wP+ttrq+AsWpFG2awvsuOqbipWHgtuvuaAE+A1Z/7gC9hesnr+7wqCwG8c5yAg3AL1fm8T9AZtp/bbJGwl1pNrE7RuOX7PeMRUERVaPpEs+yqeoSmuOlokqw49pgomjLeh7icHNlG19yjs6XXOMedYm5xH2YxpV2tc0Ro2jJfxC50ApuxGob7lMsxfTbeUv07TyYxpeLucEH1gNd4IKH2LAg5TdVhlCafZvpskfncCfx8pOhJzd76bJWeYFnFciwcYfubRc12Ip/ppIhA1/mSZ/RxjFDrJC5xifFjJpY2Xl5zXdguFqYyTR1zSp1Y9p+tktDYYSNflcxI0iyO4TPBdlRcpeqjK/piF5bklq77VSEaA+z8qmJTFzIWiitbnzR794USKBUaT0NTEsVjZqLaFVqJoPN9ODG70IPbfBHKK+/q/AWR0tJzYHRULOa4MP+W/HfGadZUbfw177G7j/OGbIs8TahLyynl4X4RinF793Oz+BU0saXtUHrVBFT/DnA3ctNPoGbs4hRIjTok8i+algT1lTHi4SxFvONKNrgQFAq2/gFnWMXgwffgYMJpiKYkmW3tTg3ZQ9Jq+f8XN+A5eeUKHWvJWJ2sgJ1Sop+wwhqFVijqWaJhwtD8MNlSBeWNNWTa5Z5kPZw5+LbVT99wqTdx29lMUH4OIG/D86ruKEauBjvH5xy6um/Sfj7ei6UUVk4AIl3MyD4MSSTOFgSwsH/QJWaQ5as7ZcmgBZkzjjU1UrQ74ci1gWBCSGHtuV1H2mhSnO3Wp/3fEV5a+4wz//6qy8JxjZsmxxy5+4w9CDNJY09T072iKG0EnOS0arEYgXqYnXcYHwjTtUNAcMelOd4xpkoqiTYICWFq0JSiPfPDQdnt+4/wuqcXY47QILbgAAAABJRU5ErkJggg==);
|
||||
background-size: 75px;
|
||||
background-color: #000000;
|
||||
color: #ddd;
|
||||
font-family: 'Oxygen', serif;
|
||||
font-size: 1.2em;
|
||||
width: 100%;
|
||||
border: 0px;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
text-align: center;
|
||||
z-index: -1000;
|
||||
}
|
||||
|
||||
a, a:visited{
|
||||
color: #fa6607;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover{
|
||||
color: #fa6;
|
||||
}
|
||||
|
||||
.show{
|
||||
display: block !important;
|
||||
}
|
||||
.hide{
|
||||
display: none !important;
|
||||
}
|
||||
head{
|
||||
width: 100%;
|
||||
border: 0px;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
h1,h2{
|
||||
color: #ff9;
|
||||
font-weight: 300;
|
||||
}
|
||||
h1{
|
||||
font-size: 3.3em;
|
||||
}
|
||||
h2{
|
||||
font-size: 2.2em;
|
||||
}
|
||||
.sites_header{
|
||||
font-size: 1.6em;
|
||||
color: #ff9;
|
||||
}
|
||||
.content{
|
||||
display: inline-block;
|
||||
width: 52em;
|
||||
}
|
||||
.center{
|
||||
margin: 0 auto;
|
||||
}
|
||||
.basecolor: {
|
||||
color: #ddd !important;
|
||||
}
|
||||
.red{
|
||||
color: #ff3a00;
|
||||
}
|
||||
.disabled: {
|
||||
opacity: 0.69;
|
||||
}
|
||||
.left{
|
||||
text-align: left;
|
||||
}
|
||||
.block{
|
||||
display: inline-block;
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
.tabline{
|
||||
background-color: #000;
|
||||
width: 100%;
|
||||
margin-bottom: 1.5em;
|
||||
padding-top: 0.3em;
|
||||
padding-bottom: 0.4em;
|
||||
z-index: -200;
|
||||
}
|
||||
.tab{
|
||||
color: #fa6607;
|
||||
}
|
||||
.tab:hover{
|
||||
text-shadow: #aa5 0px 0px 0.02em,#aa5 0px 0px 0.02em;
|
||||
}
|
||||
.tab-selected {
|
||||
color: #ff9 !important;
|
||||
}
|
||||
#all{
|
||||
min-width: 100%;
|
||||
min-height: 100vh;
|
||||
background-image: url('img/settings/about-bg.png');
|
||||
background-position: calc(50vw + 20em) 10vh;
|
||||
background-attachment: fixed;
|
||||
background-size: auto 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.dup_keybinds{
|
||||
background-color: #720 !important;
|
||||
}
|
||||
input[type=text]{
|
||||
font-size: 1em;
|
||||
padding-left: 0.6em;
|
||||
margin-left: 1em;
|
||||
width: 2em;
|
||||
background-color: #000;
|
||||
border: 1px #442 solid;
|
||||
}
|
||||
.uw_shortcuts_line{
|
||||
padding-top: 0.25em;
|
||||
padding-left: 5em;
|
||||
}
|
||||
.uw_shortcuts_label{
|
||||
display: inline-block;
|
||||
color: #fff;
|
||||
width: 17.5em;
|
||||
}
|
||||
.uw_options_line{
|
||||
margin-top: 0.75em;
|
||||
font-size: 1.1em;
|
||||
width: 80%;
|
||||
margin-left: 5%;
|
||||
}
|
||||
.uw_options_option{
|
||||
margin-left: 5%;
|
||||
}
|
||||
.uw_suboption{
|
||||
margin-left: 5em;
|
||||
margin-top: 0.75em;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
.uw_options_desc, .uw_suboption_desc{
|
||||
margin-top: 0.33em;
|
||||
font-size: 0.69em;
|
||||
color: #aaa;
|
||||
}
|
||||
.uw_suboption_desc{
|
||||
margin-left: 5em;
|
||||
}
|
||||
|
||||
.buttonbar{
|
||||
/* width: 100%; */
|
||||
padding-left: 20em;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
.button{
|
||||
display: inline-block;
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
padding-top: 0.4em;
|
||||
width: 4em;
|
||||
text-align: center;
|
||||
background-color: rgba(0,0,0,0.66);
|
||||
color: #ffc;
|
||||
height: 1.7em;
|
||||
}optionsoptions
|
||||
Shortcuts
|
||||
About
|
||||
Official
|
||||
Shortcuts
|
||||
About
|
||||
Official
|
||||
|
||||
/** site options css **/
|
||||
.site_name {
|
||||
padding-left: 1em;
|
||||
padding-bottom: 0.3em;
|
||||
color: #fff;
|
||||
font-size: 1.1em;
|
||||
height: 13em !important;
|
||||
|
||||
}
|
||||
.site_details {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.site_title_ebox {
|
||||
width: 10em !important;
|
||||
font-size: 1.5em !important;
|
||||
background-color: rgba(0,0,0,0) !important;
|
||||
margin-left: 0px !important;
|
||||
border: 0px !important;
|
||||
color: #ffc !important;
|
||||
}
|
||||
.details_ebox {
|
||||
width: 12em !important;
|
||||
background-color: rgba(0,0,0,0) !important;
|
||||
border: 0px !important;
|
||||
color: #ffc !important;
|
||||
margin-left: 0em !important;
|
||||
}
|
||||
.details_ebox:disabled {
|
||||
color: #aaa !important;
|
||||
}
|
||||
.inline_button {
|
||||
display: inline-block;
|
||||
margin-top: -1.42em;
|
||||
}
|
||||
.inline_button:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
</head>
|
||||
@ -224,40 +18,156 @@
|
||||
</div>
|
||||
<div class="tabline center">
|
||||
<div class="content left">
|
||||
<!-- <div id="tab_general_settings" class="block tab tab-selected">General settings</div> -->
|
||||
<!-- <div id="tab_sites" class="block tab">Site options</div> -->
|
||||
<div id="tab_shortcuts" class="block tab tab-selected">Shortcuts</div>
|
||||
<div id="tab_general_settings" class="block tab tab-selected">General settings</div>
|
||||
<div id="tab_sites" class="block tab">Site options</div>
|
||||
<div id="tab_shortcuts" class="block tab">Shortcuts</div>
|
||||
<div id="tab_about" class="block tab">About</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
|
||||
<!-- GENERAL SETTINGS -->
|
||||
|
||||
|
||||
<div id="general_settings" class="hide">
|
||||
<div id="general_settings">
|
||||
<div class="content left">
|
||||
<div class="uw_options_line">
|
||||
<div class="uw_options_option"><input type="checkbox" id='enable_autoar'> <strike>Enable automatic aspect ratio detection</strike></div>
|
||||
<div class="uw_options_desc"><strike>This option uses 3rd party websites to determine aspect ratio. It may not work all the time or even properly. It only works with Netflix. <span class="red">This option is <b>NOT</b> available on Youtube. Also deprecated probably, tamius pls remove</span></strike></div>
|
||||
</div>
|
||||
<div class="uw_options_line">
|
||||
<div class="uw_options_option"><input type="checkbox" id='enable_ardetect'> Enable brute-force automatic aspect ratio detection</div>
|
||||
<div class="uw_options_desc">Pretend that this checkbox is checked and that you can't uncheck it. <br/><br/>This option works by checking where black pixels end on _every_ frame (technically every ~30ms). Because of this, this option may cause lagginess and increased CPU usage. <span class="red">also you can't not use it because we're doing a total rewrite lol</span></div>
|
||||
</div>
|
||||
<div class="uw_options_line">
|
||||
<div class="uw_options_option">Yes, the UI is gone. [..] but why is the UI gone?</div>
|
||||
|
||||
<div class="row">
|
||||
<span class="label">Enable this extension:</span>
|
||||
<div class="button-row">
|
||||
<a id="_ext_global_options_blacklist" class="button _ext _ext_global_options _blacklist">Always</a>
|
||||
<a id="_ext_global_options_whitelist" class="button _ext _ext_global_options _whitelist">On whitelisted sites</a>
|
||||
<a id="_ext_global_options_disabled" class="button _ext _ext_global_options _disabled" >Never</a>
|
||||
</div>
|
||||
<span class="description">
|
||||
<b>Always</b> enables this extension on every site you visit that you didn't blacklist.
|
||||
<b>On whitelisted sites</b> enables this extension only on sites you explicitly whitelisted.
|
||||
<b>Never</b> disables extension on all sites, even on those you whitelisted.
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<span class="label">Enable autodetection:</span>
|
||||
<div class="button-row">
|
||||
<a id="_general_ar_global_options_blacklist" class="button _autoAr _ar_global_options _blacklist">Always</a>
|
||||
<a id="_general_ar_global_options_whitelist" class="button _autoAr _ar_global_options _whitelist">On whitelisted sites</a>
|
||||
<a id="_general_ar_global_options_disabled" class="button _autoAr _ar_global_options _disabled" >Never</a>
|
||||
</div>
|
||||
<span class="description">
|
||||
<b>Always</b> enables autodetection on every site this extension is enabled for, unless blacklisted.
|
||||
<b>On whitelisted sites</b> enables autodetection only for sites that you explicitly enabled.
|
||||
<b>Never</b> disables autodetection on all sites, even on those you whitelisted.
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<span class="label">In-player UI</span>
|
||||
<div class="button-row">
|
||||
<a id="_ar_global_options_blacklist" class="button _ui _ui_global_options _blacklist">Always/a>
|
||||
<a id="_ar_global_options_whitelist" class="button _ui _ui_global_options _whitelist">On whitelisted sites</a>
|
||||
<a id="_ar_global_options_disabled" class="button _ui _ui_global_options _disabled" >Never</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="uw_options_option"><input type="checkbox" id="enable_ui"> Show UI in the player bar</div> -->
|
||||
<!-- <div class="uw_options_desc">If this option is enabled, the extension will add some extra buttons to the player bar. If this option is disabled, setting video fit and aspect ratio is only possible via keyboard shortcuts.</div> -->
|
||||
<!-- <div class="uw_suboption_line" id="compact_ui_suboption"> -->
|
||||
<!-- <div class="uw_suboption"><input type="checkbox" id="enable_ui_compact"> If possible, use compact UI</div> -->
|
||||
<!-- <div class="uw_suboption_desc">With this option enabled, only 'more settings' button is enabled. Note that this option doesn't work on every site.</div> -->
|
||||
<!-- </div> -->
|
||||
|
||||
<div class="row">
|
||||
<span class="label">Video alignment:</span>
|
||||
<div class="button-row">
|
||||
<a id="_align_left" class="button _align _align_left">left</a>
|
||||
<a id="_align_center" class="button _align _align_center">center</a>
|
||||
<a id="_align_right" class="button _align _align_right">right</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="button-row">
|
||||
<a id="_stretch_global_none" class="button _stretch _ar_stretch_global _none">Never<br/><span id="_b_stretch_default_none_key" class="smallcaps small darker"></span></a>
|
||||
<a id="_stretch_global_basic" class="button _stretch _ar_stretch_global _basic">Basic<br/><span id="_b_stretch_default_basic_key" class="smallcaps small darker"></span></a>
|
||||
<a id="_stretch_global_hybrid" class="button _stretch _ar_stretch_global _hybrid">Hybrid<br/><span id="_b_stretch_default_hybrid_key" class="smallcaps small darker"></span></a>
|
||||
<a id="_stretch_global_conditional" class="button _stretch _ar_stretch_global _conditional">Thin borders<br/><span id="_b_stretch_default_conditional_key" class="smallcaps small darker"></span></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- AUTOMATIC DETECTION SETTINGS -->
|
||||
|
||||
<div id="autoar_settings">
|
||||
|
||||
<div class="row">
|
||||
<span class="label">Enable autodetection:</span>
|
||||
<div class="button-row">
|
||||
<a id="_ar_global_options_blacklist" class="button _autoAr _ar_global_options _blacklist">Always</a>
|
||||
<a id="_ar_global_options_whitelist" class="button _autoAr _ar_global_options _whitelist">On whitelisted sites</a>
|
||||
<a id="_ar_global_options_disabled" class="button _autoAr _ar_global_options _disabled" >Never</a>
|
||||
</div>
|
||||
<div class="description">
|
||||
<b>Always</b> enables autodetection on every site this extension is enabled for, unless blacklisted.
|
||||
<b>On whitelisted sites</b> enables autodetection only for sites that you explicitly enabled.
|
||||
<b>Never</b> disables autodetection on all sites, even on those you whitelisted.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<span class="label">Checking for aspect ratio changes</span>
|
||||
<div>
|
||||
When video is playing: <input id="_input_autoAr_timer" class="_autoAr _autoAr_timer" type="number" min="5" max="10000"> ms
|
||||
<div>
|
||||
<div>
|
||||
When video is paused: <input id="_input_autoAr_timer_pause" class="_autoAr _autoAr_timer_pause" type="number" min="5" max="10000"> ms
|
||||
<div>
|
||||
<div>
|
||||
On error: <input id="_input_autoAr_timer_error" class="_autoAr _autoAr_timer_error" type="number" min="5" max="10000"> ms
|
||||
<div>
|
||||
|
||||
<div class="description">
|
||||
All values are in milliseconds.
|
||||
The values determine how often the autodetection script will scan video for changes in aspect ratio under different circumstances.
|
||||
Using shorter intervals can cause lag and increases resource usage.
|
||||
Using longer intervals increases delay between aspect ratio changing and said change being detected.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="_autoar_fallback_mode_top" class="row">
|
||||
<label>Enable fallback mode</label>
|
||||
todo: insert checkbox
|
||||
<div class="description">
|
||||
<p>In order for autodetection to work, the extension grabs a frame of the video you're watching and takes a look at it.
|
||||
Some websites use DRM, which prevents you from using the HTML5-blessed way of getting a frame from a video.
|
||||
Some browsers offer some features that can be used to circumvent DRM protection.
|
||||
With this option enabled, the extension will use said features to basically do that.
|
||||
</p>
|
||||
<p><b>Technical details: tl;dr — only works in Firefox and maybe its forks.</b><br/>
|
||||
Fallback mode depends on two things:
|
||||
<ol>
|
||||
<li>Attempting to grab a video frame from DRM protected video stream must return an error (Chrome returns black image)</li>
|
||||
<li>Supports <a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawWindow" target="_blank">CanvasRenderingContext2D.drawWindow()</a> method, which pretty much only Firefox does</li>
|
||||
</ol>
|
||||
</p>
|
||||
<p><b>But I thought it's <a href="http://www.dmlp.org/legal-guide/circumventing-copyright-controls" target="_blank">illegal</a> to circumvent DRM?</b><br/>
|
||||
Courts <a href="https://arstechnica.com/information-technology/2010/07/court-breaking-drm-for-a-fair-use-is-legal/" target="_blank">disagree</a> (at least as far as our use-case is concerned).
|
||||
At this point I'd also throw in some choice words about DRM and everyone using it, but AMO gives me "you're breaking terms of conduct" warnings over use of the word for thing you flush down the toilet, prepended by a word for male cow*, in the code comments.<small><br/>*'cow' is term for the female</small>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- INTERFACE AND SHORTCUTS -->
|
||||
|
||||
<div id="interface_shortcut_settings">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- SITE SETTINGS -->
|
||||
|
||||
<div id="uw_sites" class="hide">
|
||||
<h1>PLEASE NOTE: THIS IS COMPLETELY NON-FUNCTIONAL ATM. YOU CANT SET SITE-SPECIFIC OPTIONS ATM</h1>
|
||||
<div id="uw_sites_body" class="content left">
|
||||
@ -265,7 +175,10 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="uw_shortcuts">
|
||||
|
||||
<!-- REMOVE PLOX -->
|
||||
|
||||
<div id="uw_shortcuts" class="hide">
|
||||
<div class="content left">
|
||||
<h2>Keyboard shortcuts</h2>
|
||||
|
||||
@ -343,30 +256,29 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- ABOUT -->
|
||||
|
||||
<div id="about" class="hide">
|
||||
<div class="content left">
|
||||
<h2>Ultrawidify - an aspect ratio fixer for youtube <small>(and netflix)</small></h2>
|
||||
<p>Created by Tamius Han (me). If something is broken, you can shout at me on <a href="https://github.com/xternal7/ultrawidify">github</a> (shout nicely, though. Open an issue or bug report or something). If you're curious to see the source code, <a href="https://github.com/xternal7/ultrawidify">github's here</a>. If you're looking at this page because you're bored and want to be bored some more, <a href="http://tamius.net">my website's here</a>.</p>
|
||||
<p>Created by Tamius Han (me). If something is broken, you can shout at me on <a href="https://github.com/xternal7/ultrawidify">github</a> (shout nicely, though. Open an issue or bug report or something).
|
||||
If you're curious to see the source code, <a href="https://github.com/xternal7/ultrawidify">github's here</a>.
|
||||
If you're looking at this page because you're bored and want to be bored some more, <a href="http://tamius.net">my website's here</a>.</p>
|
||||
<h2>So you want to help?</h2>
|
||||
<p><strike>There's a lot of sites where you can stream videos. A lot of these sites keep failing to handle aspect ratios correctly, which means it would be great if this extension worked elsewhere. Unfortunately, a lot of these sites require me to pony up some money (ayy lmao) OR just flat out block anyone who's not from the US (or their small selection of approved regions). Some sites even do both.</strike></p>
|
||||
<p><strike>This means I'd need some help. There's two ways. One of them is to use 'inspect element' option of your browser to pick up IDs (or classnames) of certain elements. More detail here(TODO: add a link to quick tutorial).</strike>probably wont be necessary</p>
|
||||
<p>The second one is, well. I won't shy away from donations either. <small>Bonus respect for dank amounts!</small></p>
|
||||
<p>Needless to say, I'll be happy and thankful regardless of the way you contribute.</p>
|
||||
<p>Alan pls add quick description.</p>
|
||||
<h2>Plans for the future</h2>
|
||||
<p><strike>Support for more sizes. More flexible/customizable UI. Maybe (but absolutely no promises here) a bit more advanced autodetection.</strike></p>
|
||||
<p>this is the future lol. (at least as far as autodetection goes, keybinds need to make a comeback)</p>
|
||||
<h2>Acknowledgements</h2>
|
||||
<p>This extension uses font <a href="https://fonts.google.com/specimen/Oxygen">Oxygen</a>.</p>
|
||||
<p>Special thanks to CD Project Red (The Witcher 2), Cyanide Studios (Styx, Of Orcs and Men), and Valve (CS:GO), which made it possible for me to untrigger myself after seeing so many improperly encoded videos.</p>
|
||||
<small><p>More or less.</p>
|
||||
<!-- <p>GW2 is also roughly how the avatar was obtained. Noone tell Anet, though.</p> --></small>
|
||||
<p>Special one-finger salute to all incompetent people who don't know how to properly encode videos and upload them to youtube (to word it most nicely).</p>
|
||||
<p>This extension uses font <a href="http://overpassfont.org/">Overpass</a>.</p>
|
||||
<!-- <p>Special thanks to CD Project Red (The Witcher 2), Cyanide Studios (Styx, Of Orcs and Men), and Valve (CS:GO), which made it possible for me to untrigger myself after seeing so many improperly encoded videos.</p> -->
|
||||
<!-- <small><p>More or less.</p> -->
|
||||
<!-- <p>GW2 is also roughly how the avatar was obtained. Noone tell Anet, though.</p></small> -->
|
||||
<!-- <p>Special one-finger salute to all incompetent people who don't know how to properly encode videos and upload them to youtube (to word it most nicely).</p> -->
|
||||
<p>Special thanks to me for making this extension. You're welcome.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="../../js/dep/jquery-3.1.1.js" ></script>
|
||||
<script src="../../js/conf/Debug.js"></script>
|
||||
|
||||
<script src="../../js/lib/BrowserDetect.js"></script>
|
||||
|
@ -21,3 +21,10 @@ https://www.youtube.com/watch?v=NaTGwlfRB_c (dark, triggers minor corrections)
|
||||
### Watermark stopping AR
|
||||
|
||||
https://www.youtube.com/watch?v=tXTFdDrd7pA
|
||||
|
||||
|
||||
### HARD MODE
|
||||
|
||||
For situations that would be _really_ hard to fix (if fix is even possible)
|
||||
|
||||
https://www.youtube.com/watch?v=hg25ONutphA
|
Loading…
Reference in New Issue
Block a user