Rewrote Settings.js, did some cleanup with legacy stuff.
This commit is contained in:
parent
b01e5ebcec
commit
966f8a034d
@ -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
136
js/lib/Comms.js
136
js/lib/Comms.js
@ -27,13 +27,13 @@ class CommsClient {
|
||||
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.miscFullscreenthis.settings.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.settings.active = message.conf;
|
||||
// this.pageInfo.reset();
|
||||
} else if (message.cmd === "set-stretch") {
|
||||
this.pageInfo.setStretchMode(StretchMode[message.mode]);
|
||||
@ -50,9 +50,9 @@ class CommsClient {
|
||||
// todo: autoArStatus
|
||||
this.pageInfo.resumeProcessing(message.autoArStatus);
|
||||
} else if (message.cmd === "reload-settings") {
|
||||
ExtensionConf = message.newConf;
|
||||
this.settings.active = message.newConf;
|
||||
this.pageInfo.reset();
|
||||
if(ExtensionConf.arDetect.mode === "disabled") {
|
||||
if(this.settings.active.arDetect.mode === "disabled") {
|
||||
this.pageInfo.stopArDetection();
|
||||
} else {
|
||||
this.pageInfo.startArDetection();
|
||||
@ -116,7 +116,7 @@ class CommsClient {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
ExtensionConf = JSON.parse(response.extensionConf);
|
||||
this.settings.active = JSON.parse(response.extensionConf);
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
@ -225,88 +225,88 @@ class CommsServer {
|
||||
}
|
||||
|
||||
if (message.cmd === 'get-config') {
|
||||
port.postMessage({cmd: "set-config", conf: ExtensionConf, site: this.server.currentSite})
|
||||
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(this.settings.active);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: this.settings.active});
|
||||
} 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(this.settings.active);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: this.settings.active});
|
||||
} 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.miscFullscreenthis.settings.videoFloat = message.newFloat;
|
||||
this.settings.save(this.settings.active);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: this.settings.active});
|
||||
|
||||
} 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});
|
||||
this.settings.active.arDetect.mode = "blacklist";
|
||||
this.settings.save(this.settings.active);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: this.settings.active});
|
||||
} 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(this.settings.active);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: this.settings.active});
|
||||
} 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(this.settings.active);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: this.settings.active});
|
||||
} else if (message.cmd === "set-autoar-defaults") {
|
||||
ExtensionConf.arDetect.mode = message.mode;
|
||||
Settings.save(ExtensionConf);
|
||||
this.settings.active.arDetect.mode = message.mode;
|
||||
this.settings.save(this.settings.active);
|
||||
this.sendToAll({cmd: "reload-settings", sender: "uwbg"})
|
||||
} 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(this.settings.active);
|
||||
} 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.settings.active);
|
||||
}
|
||||
this.sendToAll({cmd: "reload-settings", sender: "uwbg"});
|
||||
} else if (message.cmd === "set-extension-defaults") {
|
||||
ExtensionConf.extensionMode = message.mode;
|
||||
Settings.save(ExtensionConf);
|
||||
this.settings.active.extensionMode = message.mode;
|
||||
this.settings.save(this.settings.active);
|
||||
this.sendToAll({cmd: "reload-settings", sender: "uwbg"})
|
||||
} 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(this.settings.active);
|
||||
} 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(this.settings.active);
|
||||
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});
|
||||
port.postMessage({cmd: "set-config", conf: this.settings.active, site: this.server.currentSite});
|
||||
}
|
||||
}
|
||||
|
||||
@ -316,29 +316,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.settings.active);
|
||||
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.settings.active);
|
||||
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)
|
||||
@ -346,9 +346,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.settings.active);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: this.settings.active});
|
||||
}
|
||||
}
|
||||
|
||||
@ -358,26 +358,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.settings.active);
|
||||
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.settings.active);
|
||||
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)
|
||||
@ -385,9 +385,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.settings.active);
|
||||
this.sendToAll({cmd: 'reload-settings', newConf: this.settings.active});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 < GlobalVars.arDetect.sampleCols * 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 < GlobalVars.arDetect.sampleCols * 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 = GlobalVars.arDetect.sampleCols * 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;
|
||||
@ -163,7 +164,7 @@ class GuardLine {
|
||||
|
||||
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 +173,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 +185,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(Settings.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
|
||||
}
|
||||
}
|
161
js/lib/Settings.js
Normal file
161
js/lib/Settings.js
Normal file
@ -0,0 +1,161 @@
|
||||
class Settings {
|
||||
|
||||
constructor() {
|
||||
this.active = {};
|
||||
this.default = ExtensionConf;
|
||||
}
|
||||
|
||||
async init() {
|
||||
const settings = await this.get('uw-settings');
|
||||
|
||||
if(Debug.debug) {
|
||||
console.log("[Settings::init] Configuration fetched from background script:", settings);
|
||||
}
|
||||
|
||||
// if there's no settings saved, return default settings.
|
||||
if(! settings || (Object.keys(newSettings).length === 0 && newSettings.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
|
||||
const uwVersion = runtime.getManifest().version;
|
||||
if(settings.version === uwVersion) {
|
||||
if(Debug.debug) {
|
||||
console.log("[Settings::init] extension was saved with current version of ultrawidify (", uwVersion, "). 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.
|
||||
this.active = ObjectCopy.addNew(settings, this.default);
|
||||
this.set(this.active);
|
||||
return this.active;
|
||||
}
|
||||
|
||||
async get() {
|
||||
if (BrowserDetect.firefox || BrowserDetect.edge) {
|
||||
return browser.storage.sync.get('uw-settings');
|
||||
} else if (BrowserDetect.chrome) {
|
||||
return chrome.storage.sync.get('uw-settings');
|
||||
}
|
||||
}
|
||||
|
||||
async set(extensionConf) {
|
||||
if (BrowserDetect.firefox || BrowserDetect.edge) {
|
||||
return browser.storage.sync.set('uw-settings', extensionConf);
|
||||
} else if (BrowserDetect.chrome) {
|
||||
return chrome.storage.sync.set('uw-settings', extensionConf);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
// 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] !== "disabled";
|
||||
} else if (this.active.extensionMode === "whitelist") {
|
||||
return this.active.sites[site] === "enabled";
|
||||
} else {
|
||||
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,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);
|
||||
|
@ -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);
|
||||
}
|
||||
@ -293,14 +294,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 +314,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 +348,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 +359,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 +391,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 +425,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 +439,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 +458,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 +475,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.miscFullscreenthis.settings.videoFloat == "center")
|
||||
this.canvasDrawWindowHOffset = Math.round((window.innerWidth - newCanvasWidth) * 0.5);
|
||||
else if(ExtensionConf.miscFullscreenSettings.videFloat == "left")
|
||||
else if(this.settings.active.miscFullscreenthis.settings.videFloat == "left")
|
||||
this.canvasDrawWindowHOffset = 0;
|
||||
else
|
||||
this.canvasDrawWindowHOffset = window.innerWidth - newCanvasWidth;
|
||||
@ -491,7 +492,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 +574,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 +601,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 +695,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:",GlobalVars.arDetect.blackLevel, "tresh:", this.blackLevel + this.settings.active.arDetect.blackbarTreshold);
|
||||
|
||||
if(edgePost.status == "ar_known"){
|
||||
|
||||
@ -705,11 +706,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 +747,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 +773,7 @@ class ArDetector {
|
||||
}
|
||||
|
||||
resetBlackLevel(){
|
||||
this.blackLevel = ExtensionConf.arDetect.blackLevel_default;
|
||||
this.blackLevel = this.settings.active.arDetect.blackLevel_default;
|
||||
}
|
||||
|
||||
}
|
||||
@ -797,8 +798,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 +853,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 +862,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;
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,13 @@ if(Debug.debug)
|
||||
console.log("Loading: PageInfo.js");
|
||||
|
||||
class PageInfo {
|
||||
constructor(comms){
|
||||
constructor(comms, settings){
|
||||
this.keybinds = new Keybinds(this);
|
||||
this.keybinds.setup();
|
||||
this.hasVideos = false;
|
||||
this.siteDisabled = false;
|
||||
this.videos = [];
|
||||
this.settings = settings;
|
||||
|
||||
this.lastUrl = window.location.href;
|
||||
|
||||
@ -79,7 +80,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 +127,7 @@ class PageInfo {
|
||||
ths.rescanTimer = null;
|
||||
ths.rescan(rr);
|
||||
ths = null;
|
||||
}, rescanReason === ExtensionConf.pageInfo.timeouts.rescan, RescanReason.PERIODIC)
|
||||
}, rescanReason === 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 +147,7 @@ class PageInfo {
|
||||
ths.rescanTimer = null;
|
||||
ths.ghettoUrlCheck();
|
||||
ths = null;
|
||||
}, ExtensionConf.pageInfo.timeouts.urlCheck)
|
||||
}, 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);
|
||||
@ -199,7 +199,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] video will be aligned to ", settings.active.miscFullscreenSettings.videoFloat);
|
||||
|
||||
var actualWidth = this.conf.video.offsetWidth * stretchFactors.xFactor;
|
||||
var actualHeight = this.conf.video.offsetHeight * stretchFactors.yFactor;
|
||||
@ -209,10 +209,10 @@ class Resizer {
|
||||
if (this.pan) {
|
||||
// todo: calculate translate
|
||||
} else {
|
||||
if (ExtensionConf.miscFullscreenSettings.videoFloat == "left") {
|
||||
if (settings.active.miscFullscreenSettings.videoFloat == "left") {
|
||||
translate.x = (this.conf.player.dimensions.width - actualWidth) * -0.5;
|
||||
}
|
||||
else if (ExtensionConf.miscFullscreenSettings.videoFloat == "right") {
|
||||
else if (settings.active.miscFullscreenSettings.videoFloat == "right") {
|
||||
translate.x = (this.conf.player.dimensions.width - actualWidth) * 0.5;
|
||||
}
|
||||
}
|
||||
@ -288,8 +288,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");
|
||||
|
@ -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,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Ultrawidify",
|
||||
"version": "3.0.1",
|
||||
"version": "3.0.2a",
|
||||
|
||||
"icons": {
|
||||
"32":"res/icons/uw-32.png",
|
||||
@ -16,13 +16,14 @@
|
||||
"js/conf/Debug.js",
|
||||
|
||||
"js/lib/BrowserDetect.js",
|
||||
"js/conf/ExtensionConf.js",
|
||||
"js/conf/Settings.active..js",
|
||||
|
||||
"js/run/GlobalVars.js",
|
||||
"js/lib/StorageManager.js",
|
||||
"js/lib/Comms.js",
|
||||
|
||||
"js/conf/Settings.js",
|
||||
"js/lib/ObjectCopy.js",
|
||||
"js/lib/Settings.js",
|
||||
"js/conf/SitesConf.js",
|
||||
"js/conf/Status.js",
|
||||
|
||||
@ -53,13 +54,13 @@
|
||||
"js/conf/Debug.js",
|
||||
"js/lib/BrowserDetect.js",
|
||||
|
||||
"js/conf/ExtensionConf.js",
|
||||
"js/conf/Settings.active..js",
|
||||
|
||||
"js/lib/StorageManager.js",
|
||||
"js/lib/Comms.js",
|
||||
|
||||
"js/conf/Settings.js",
|
||||
"js/conf/SitesConf.js",
|
||||
|
||||
"js/lib/ObjectCopy.js",
|
||||
"js/lib/Settings.js",
|
||||
"js/conf/Status.js",
|
||||
|
||||
"js/conf/Keybinds.js",
|
||||
|
@ -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