Merge branch 'master' into stable

This commit is contained in:
Tamius Han 2018-09-23 19:56:43 +02:00
commit ac59998f24
30 changed files with 1398 additions and 688 deletions

View File

@ -2,6 +2,21 @@
## v3.x
### v3.2.2
* Pan event listener now gets properly unbound
* Fixed 'reset zoom' button in popup
### v3.2.1
* Fixed issue where global video alignment setting didn't get saved properly
### v3.2.0
* Zoom and panning
* Reorganized popup
* Various bug fixes
### v3.1.1 (Chrome-only)
* Logging was accidentally left on in release version. This was fixed.

167
README.md
View File

@ -6,11 +6,17 @@ 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.")
## Known issues
* Netflix autodetection not working in Chrome, wontfix as issue is fundamentally unfixable.
* Keyboard shortcut for automatic detection (A) doesn't really work for some reason.
* Everything reported in [issues](https://github.com/xternal7/ultrawidify/issues)
### Limitations
* 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.
* That new stretching mode wasn't thoroughly tested yet. Issues may be present. (Same with zoom)
* Enabling extension everywhere (as opposed to whitelisted sites) could break some websites.
### Features
@ -18,8 +24,10 @@ If you own an ultrawide monitor, you have probably noticed that sometimes videos
* **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**
* **[EXPERIMENTAL!]** Stretch video to fit the screen (4 different approaches)
* **[EXPERIMENTAL!]** custom zooming and panning
### Officially supported sites
@ -28,7 +36,7 @@ If you own an ultrawide monitor, you have probably noticed that sometimes videos
### 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.
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, but I make no guarantees it will work everywhere.
### Installing this extension
@ -65,66 +73,62 @@ Before we go on to features, let's discuss limitations.
* Currently, this extension is only tested on Youtube and Netflix. It should work on other sites as well, but you'll need to manually enable extension on other sites via the popup.
* It's unclear how extension handles sites displaying multiple videos per site. Having multiple videos on the same page is a very tricky case that hasn't been given much thought.
* Autodetection is a very hard problem to solve. Despite various improvements, it's still not 100% correct. In cases where aspect ratio is hard to determine, extension tends to err on the side of caution and tries to avoid changing aspect ratios.
* This extension only works one way. It removes horizontal bars encoded in the video. It can't remove vertical bars encoded in the video. Especially not with autodetection.
* Autodetection is a very hard problem to solve. Despite various improvements, it's still not 100% correct. In cases where aspect ratio is hard to determine, extension tends to err on the side of caution and tries to avoid changing aspect ratios. However, sometimes aspect ratio changes will still trigger too eagerly.
### Turn extension on and off, on per-site basis
![Demo](img-demo/ui/popup/extsettings.png)
This is pretty straight-forward. Under **enable this extension** section, selecting `always` will ensure the extension runs on every site you visit. That unfortunately breaks some sites, so by default Ultrawidify will only run on the sites you manually enabled (`On whitelisted sites`). `Never` means extension is disabled for all sites.
In the **Options for this site** section, there's some sidenotes to be had:
* `Blacklist` option ensures extension _never_ runs on the site you're currently on.
* `Default` will do whatever the global option is: if 'enable this extension' is set to `always`, then extension will work on the given site. Otherwise, it won't.
* `Whitelist` ensures extension always runs on the site you're currently on, unless extension is disabled via previous option.
### 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). Video demonstration of autodetection can be found [here](https://www.youtube.com/watch?v=j2xn1WpbtCQ).
By default, automatic detection will run on every site this extension is enabled for. It does what it says on the tin: it attempts to detect aspect ratio of the video by periodically looking at a video frame.
![Demo](img-demo/ui/popup/autoar.png)
Some caveats apply:
* autodetection is very easy in 99% of cases and very tricky in the 1%. Sometimes, autodetection will be too eager. Sometimes it won't be eager enough.
* Some sites use DRM. DRM measures are designed specifically to prevent scripts from looking at video frames. Since that's exactly what this extension uses to determine aspect ratio of a video, **autodetection is not possible on sites that use DRM** (Netflix and the likes). Firefox is slight exception to this.
* Firefox offers an API that can be used to take screenshots of the page. Turns out that you can use this API to work around the above limitation. Usage of this API has its own limitations. Due to those limitations, automatic detection on DRM-protected sites in Firefox keeps a thin black bar at the top and the bottom of the video.
Top row of buttons determines the default mode of operation for automatic detection.
Autodetection can be enabled or disabled globally, per site or per video.
* **Always** — works on all sites this extension is enabled on, unless autodetection is specifically disabled for that site. [Default]
* **Only on whitelisted sites** — autodetection only works on sites, on which autodetection is enabled.
* **Never** — turn aspect ratio detection off
### Popup
Bottom row of buttons detemrmines the mode of operation for automatic detection for current site.
Most of the extension settings can be accessed and modified via the popup. If extension is enabled for the site you're currently on, the popup will display options for the video you're currently watching.
* **Blacklist** — don't ever attempt automatic aspect ratio detection on this site
* **Default** — follow global rules. If default mode of operation is 'always', automatic aspect ratio detection will work on this site, otherwise it won't.
* **Whitelist** — perform automatic detection on given site, unless automatic aspec ratio detection is turned off
![Demo](img-demo/ui/popup/popup_video_settings.png)
'Check every ___ ms box determines how often the extension will check for aspect ratio changes. Longer periods will result in this extension using less system resources, but extension will be slow to detect changes. Short periods will increase the use of system resources. Periods shorter than 500 ms will significantly increase RAM and CPU usage. **Time periods shorter than 100 _will_ result in _massive_ RAM usage due to technical limitations of Javascript and canvas API. To give a solid example, setting this value to '30' ms can result in multiple _gigabytes_ of RAM used (personal record is 7 GB, but the number is very dependant on multiple factors, such as what browser are you using and how long the browser has been running. In Firefox 56, the amount of RAM used was correlated with amount of time the browser has been running).
By default, extension is set to check for aspect ratio changes once every 666 ms, as it turned out to be a decent compromise between RAM usage (generally well under 500 MB) and the time it takes extension to react to aspect ratio changes.
### Cropping video
![Demo](img-demo/ui/popup/crop.png)
Buttons in the **cropping mode** set how the video will be cropped. For example: clicking 21:9¹ button will crop the video so it fits 21:9 area. It's not "proper" crop — this option won't magically cause letterbox to appear on 16:9 videos viewed on 16:9 player.
Special buttons in cropping mode:
Extension can crop videos to the desired aspect ratio. Options offered by the extension are (keyboard shortcuts in **bold**):
* **Reset** undoes any aspect ratio changes either you or autodetection made to the video.
* **Auto detect** starts autodetection (even on blacklisted sites)
* **Custom** applies crop to custom aspect ratio
* Automatic — **A**
* Reset (default) — **R**
* 21:9 (2.39:1) — **D**
* 18:9 (2:1) — **X**
* 16:9 (1.77) — **S**
* Custom — **Q**
Note that manually adjusting aspect ratio _disables_ autodetection for current video. Manual adjustments are temporary and should last for only one video.
In addition to that, you can crop video to fit width (**W**) or height (**E**).
**Custom aspect ratio** is a box in which you enter your custom aspect ratio. It can be in any of the following formats:
**Note:** manually adjusting aspect ratio _disables_ autodetection for current video. Manual adjustments are temporary and should last for only one video.
You can set custom aspect ratio by clicking 'set custom aspect ratio' link under the buttons, changing the value in the box and clicking 'save'. Aspect ratio can be in any of the following formats:
* `width/height` (e.g. `16/9`, `21/9` - even `2560/1080`)
* `1:ratio` (e.g. `1:2.39`. You can omit the `1:` part, too — e.g. `2.39` is equivalent to `1:2.39`)
'Save' button saves your custom aspect ratio. If you don't save changes, they'll be forgotten by the time you close the popup.
If you watch 16:9 videos in full screen on a 21:9 monitor, there's obviously going to be black bars on either side of the video. The video will be centered, though. Some people don't want video to be centered in such situations, instead preferring having the video aligned to either side. **Video alignment** option does that.
![Demo](img-demo/ui/popup/crop_custom.png)
--
¹21:9 is a marketing buzzword. It's an approximation of the following aspect ratios: `1:2.35` and `1:2.39` (as far as videos go). 21:9 option presumes 1:2.39.
²Vertically centered relative to the source video
### Zoom
Keys 'Z' and 'U' manually zoom the video. You can use those to zoom farther than merely adjusting aspect ratio would. At high magnification, you can pan the video by moving mouse over it. Panning is off by default and can be activated by holding 'shift' or toggled by pressing 'P' key.
You can also zoom video by using the slider in the popup:
![Demo](img-demo/ui/popup/zoom.png)
### Align video
If you watch 16:9 videos in full screen on a 21:9 monitor, there's obviously going to be black bars on either side of the video. The video will be centered, though. Some people don't want video to be centered in such situations, instead preferring having the video aligned to either side. **Video alignment** option does that.
### Stretching videos
@ -132,15 +136,55 @@ If you watch 16:9 videos in full screen on a 21:9 monitor, there's obviously goi
When you watch a 16:9 content on a 21:9 monitor, you can deal with this issue in three ways: A) you don't, B) you crop or C) you stretch the 16:9 video to fit a 21:9 container. Obviously not everyone is a person of culture, some people prefer to choose the greater evil of the three: they prefer their videos stretched!
As of v3.0, Ultrawidify does stretching. In fact, it offers you several ways of dealing with the issue:
Ultrawidify offers you several ways of dealing with the issue:
* **Never** — don't stretch at all
* **Basic** — stretch the video to fit screen. Doesn't remove black bars encoded in the video. While this option is active, automatic aspect ratio detection is disabled.
* **Hybrid** — this mode first crops away the black bars encoded in the video file. If the video doesn't fit your monitor after being cropped, the extension will proceed to stretch it in a smart way. Automatic detection remains active with this option.
* **Thin borders** — this mode only applies stretching only when borders around video are thin (less than 5% of total width or height).
## Global and per-site default settings
You can change default settings for extension or site you're currently on by visiting 'Extension settings' and 'Site settings' tabs in the popup. Per-site settings override extension defaults, video settings override both. Both tabs also have the same options:
![Demo](img-demo/ui/popup/extension_settings.png)
Quick rundown of the options:
* **Enable this extension** (Extension settings)
Whether the extension is enabled. Options:
`Always` — allow this extension to run on every site (unless the site is blacklisted)
`On whitelisted sites` — allow this extension to run only on sites you manually enabled
`Never` — this extension won't work. At all.
* **Enable autodetection** (Extension settings)
Whether extension should automatically detect aspect ratio. Uses same options as _Enable this extension_ options.
* **Enable this extension** (Site settings)
Whether the extension is enabled on current site. Options:
`Whitelist` — allow this extension to run on current site.
`Default` — follow global settings (allow if global option is set to 'always', don't allow if global option is set to any of the other two)
`Blacklist` — never allow extension to run on current site.
* **Enable autodetection** (Site settings)
Whether extension should automatically detect aspect ratio on current site. Uses same options as _Enable this extension_ options.
* **Default stretching mode**
How, if at all, should extension stretch the video by default.
* **Video alignment**
How to align the video by default.
## Keyboard shortcuts
They still aren't rebindable.
The keyboard shortcuts have already been listed, but let's list them all again in the same, handy place.
### Default keyboard shortcuts
@ -155,13 +199,34 @@ They still aren't rebindable.
`x` - force 18:9
`q` - force custom aspect ratio
`z` - zoom
`u` - unzoom
`p` - toggle video panning
`shift`- pan video (while holding)
### Rebinding keyboard shortcuts
is currently not possible. Settings page for this extension has been disabled sometime with 2.0 release (because it [broke](https://github.com/xternal7/ultrawidify/issues/16)), and fixing the setting page has been very low priority as I've had more important issues to work on.
However, I do plan on implementing this feature. Hopefully by the end of the year, but given how consistently I've been breaking self-imposed deadlines and goals for this extension don't hold your breath. After all, [Hofstadter's a bitch](https://en.wikipedia.org/wiki/Hofstadter%27s_law).
## Plans for the future
1. Handle porting of extension settings between versions.
2. ~~Reintroduce gradual zoom on z and u and provide a way to 'scroll' the zoomed in video up/down left/right.~~ (v3.2.0)
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~~no it wont lol
6. Improvements to automatic aspect ratio detection
## Installing
### Permanent install / stable
[Latest stable for Firefox — download from AMO](https://addons.mozilla.org/en/firefox/addon/ultrawidify/) (v3.0.0)
[Latest stable for Firefox — download from AMO](https://addons.mozilla.org/en/firefox/addon/ultrawidify/)
[Latest stafle for Chrome — download from Chrome store](https://chrome.google.com/webstore/detail/ultrawidify/dndehlekllfkaijdlokmmicgnlanfjbi) (v2.2.5)
[Latest stafle for Chrome — download from Chrome store](https://chrome.google.com/webstore/detail/ultrawidify/dndehlekllfkaijdlokmmicgnlanfjbi)
### Installing the current, github version
@ -171,20 +236,6 @@ They still aren't rebindable.
4. Add temporary addon
5. Browse to wherever you saved it and select manifest.json
## Known issues
* Netflix autodetection not working in Chrome, wontfix as issue is fundamentally unfixable. (Although a different kind of workaround could probably be put in place, but don't count on it)
* Everything reported in [issues](https://github.com/xternal7/ultrawidify/issues)
## Plans for the future
1. Handle porting of extension settings between versions.
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. Improvements to automatic aspect ratio detection
## Changelog
see changelog.md

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
img-demo/ui/popup/zoom.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -3,14 +3,16 @@ _prod = true;
// _prod = false;
Debug = {
debug: true,
init: true,
debug: false,
keyboard: true,
debugResizer: true,
debugArDetect: true,
debugStorage: false,
comms: false,
// showArDetectCanvas: true,
flushStoredSettings: false,
flushStoredSettings: true,
// flushStoredSettings: false,
playerDetectDebug: true,
periodic: true,
videoRescan: true,

View File

@ -96,8 +96,17 @@ var ExtensionConf = {
arChange: {
samenessTreshold: 0.025, // if aspect ratios are within 2.5% within each other, don't resize
},
zoom: {
minLogZoom: -1,
maxLogZoom: 3,
announceDebounce: 200 // we wait this long before announcing new zoom
},
miscFullscreenSettings: {
videoFloat: "center"
videoFloat: "center",
mousePan: {
enabled: false
},
defaultAr: "original",
},
stretch: {
initialMode: 0, // 0 - no stretch, 1 - basic, 2 - hybrid, 3 - conditional
@ -163,6 +172,26 @@ var ExtensionConf = {
"u": {
action: "zoom",
arg: -0.1
},
"p": {
action: "pan",
arg: 'toggle' // possible: 'enable', 'disable', 'toggle'
},
"shiftKey_shift": {
action: "pan",
arg: 'toggle',
keyup: {
action: 'pan',
arg: 'toggle'
}
},
"shift": {
action: "",
arg: "",
keyup: {
action: 'pan',
arg: 'toggle',
}
}
//#endregion
},
@ -178,6 +207,15 @@ var ExtensionConf = {
// status: <option> // should extension work on this site?
// arStatus: <option> // should we do autodetection on this site?
// statusEmbedded: <option> // reserved for future... maybe
//
// defaultAar?: <ratio> // automatically apply this aspect ratio on this side. Use extension defaults if undefined.
// stretch? <stretch mode> // automatically stretch video on this site in this manner
// videoAlignment? <left|center|right>
//
// type: <official|community|user> // 'official' — blessed by Tam.
// // 'community' — blessed by reddit.
// // 'user' — user-defined (not here)
// override: <true|false> // override user settings for this site on update
// }
//
// Veljavne vrednosti za možnosti

View File

@ -11,9 +11,10 @@ class Keybinds {
setup(){
var ths = this;
document.addEventListener('keydown', (event) => ths.handleKeypress(event) );
document.addEventListener('keyup', (event) => ths.handleKeypress(event,true) );
}
handleKeypress(event) { // Tukaj ugotovimo, katero tipko smo pritisnili
handleKeypress(event, isKeyUp) { // Tukaj ugotovimo, katero tipko smo pritisnili
if(Debug.debug && Debug.keyboard ){
console.log("%c[Keybinds::_kbd_process] we pressed a key: ", "color: #ff0", event.key , " | keydown: ", event.keydown, "event:", event);
@ -56,19 +57,28 @@ class Keybinds {
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);
if (isKeyUp) {
if (conf.keyup) {
conf = conf.keyup;
} else {
return;
}
}
if(conf.action === "crop"){
if(Debug.debug && Debug.keyboard) {
console.log("[Keybinds::_kbd_process] there's an action associated with this keypress. conf:", conf, "conf.arg:", conf.arg);
}
if (conf.action === "crop"){
this.pageInfo.stopArDetection();
this.pageInfo.setAr(conf.arg);
}
if(conf.action === "zoom"){
} else if (conf.action === "zoom"){
this.pageInfo.stopArDetection();
this.pageInfo.zoomStep(conf.arg);
}
if(conf.action === "auto-ar"){
} else if (conf.action === "auto-ar"){
this.pageInfo.startArDetection();
} else if (conf.action === "pan") {
this.pageInfo.setPanMode(conf.arg);
}
}
}

View File

@ -57,10 +57,14 @@ class CommsClient {
return;
}
if (message.cmd === 'get-current-zoom') {
this.pageInfo.requestCurrentZoom();
}
if (message.cmd === "set-ar") {
this.pageInfo.setAr(message.ratio);
} else if (message.cmd === 'set-video-float') {
this.settings.active.miscFullscreenSettings.videoFloat = message.newFloat;
} else if (message.cmd === 'set-alignment') {
this.pageInfo.setVideoFloat(message.mode);
this.pageInfo.restoreAr();
} else if (message.cmd === "set-stretch") {
this.pageInfo.setStretchMode(StretchMode[message.mode]);
@ -76,6 +80,8 @@ class CommsClient {
} else if (message.cmd === "resume-processing") {
// todo: autoArStatus
this.pageInfo.resumeProcessing(message.autoArStatus);
} else if (message.cmd === 'set-zoom') {
this.pageInfo.setZoom(message.zoom, true);
}
}
@ -130,6 +136,10 @@ class CommsClient {
this.port.postMessage({cmd: "has-video"});
}
announceZoom(scale){
this.port.postMessage({cmd: "announce-zoom", zoom: scale});
}
unregisterVideo(){
this.port.postMessage({cmd: "noVideo"}); // ayymd
}
@ -153,8 +163,24 @@ class CommsServer {
}
}
async getCurrentTabUrl() {
async getCurrentTabHostname() {
const activeTab = await this._getActiveTab();
const url = activeTab[0].url;
var hostname;
if (url.indexOf("://") > -1) { //find & remove protocol (http, ftp, etc.) and get hostname
hostname = url.split('/')[2];
}
else {
hostname = url.split('/')[0];
}
hostname = hostname.split(':')[0]; //find & remove port number
hostname = hostname.split('?')[0]; //find & remove "?"
return hostname;
}
sendToAll(message){
@ -170,7 +196,7 @@ class CommsServer {
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) {
chrome.tabs.query({lastFocusedWindow: true, active: true}, function (res) {
resolve(res);
});
});
@ -222,13 +248,24 @@ class CommsServer {
});
}
processReceivedMessage(message, port){
async processReceivedMessage(message, port){
if (Debug.debug && Debug.comms) {
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 === 'announce-zoom') {
// forward off to the popup, no use for this here
try {
this.popupPort.postMessage({cmd: 'set-current-zoom', zoom: message.zoom});
} catch (e) {
// can't forward stuff to popup if it isn't open
}
} else if (message.cmd === 'get-current-zoom') {
this.sendToActive(message);
}
if (message.cmd === 'get-current-site') {
port.postMessage({cmd: 'set-current-site', site: await this.getCurrentTabHostname()});
}
if (message.cmd === 'get-config') {
@ -238,21 +275,16 @@ class CommsServer {
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') {
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') {
this.settings.active.keyboard.shortcuts.q.arg = message.ratio;
this.settings.save();
} else if (message.cmd === 'set-video-float') {
} else if (message.cmd === 'set-alignment') {
this.sendToActive(message);
this.settings.active.miscFullscreenSettings.videoFloat = message.newFloat;
this.settings.save();
} else if (message.cmd === 'autoar-start') {
this.sendToActive(message);
} else if (message.cmd === "autoar-disable") { // LEGACY - can be removed prolly?
} else if (message.cmd === "autoar-disable") { // LEGACY - can be removed prolly
this.settings.active.arDetect.mode = "disabled";
if(message.reason){
this.settings.active.arDetect.disabledReason = message.reason;
@ -260,47 +292,8 @@ class CommsServer {
this.settings.active.arDetect.disabledReason = 'User disabled';
}
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;
this.settings.active.arDetect.timer_playing = timeout;
this.settings.save();
} else if (message.cmd === "set-autoar-defaults") {
this.settings.active.arDetect.mode = message.mode;
this.settings.save();
} else if (message.cmd === "set-autoar-for-site") {
if (this.settings.active.sites[this.server.currentSite]) {
this.settings.active.sites[this.server.currentSite].arStatus = message.mode;
this.settings.save();
} else {
this.settings.active.sites[this.server.currentSite] = {
status: "default",
arStatus: message.mode,
statusEmbedded: "default"
};
this.settings.save();
}
} else if (message.cmd === "set-extension-defaults") {
this.settings.active.extensionMode = message.mode;
this.settings.save();
} else if (message.cmd === "set-extension-for-site") {
if (this.settings.active.sites[this.server.currentSite]) {
this.settings.active.sites[this.server.currentSite].status = message.mode;
this.settings.save();
} else {
this.settings.active.sites[this.server.currentSite] = {
status: message.mode,
arStatus: "default",
statusEmbedded: message.mode
};
this.settings.save();
if(Debug.debug) {
console.log("SAVING PER-SITE OPTIONS,", this.server.currentSite, this.settings.active.sites[this.server.currentSite])
}
}
} else if (message.cmd === 'set-zoom') {
this.sendToActive(message);
}
}
@ -352,7 +345,7 @@ class CommsServer {
}
if(message.cmd === 'get-config') {
sendResponse({extensionConf: JSON.stringify(this.settings.active), site: getCurrentTabUrl()});
sendResponse({extensionConf: JSON.stringify(this.settings.active), site: this.getCurrentTabHostname()});
// return true;
} else if (message.cmd === "autoar-enable") {
this.settings.active.arDetect.mode = "blacklist";

View File

@ -32,6 +32,16 @@ class ObjectCopy {
}
}
}
// add the values that would otherwise be deleted back to our object. (We need that so user-defined
// sites don't get forgotten)
for(var k in existing) {
if (! out[k]) {
out[k] = existing[k];
}
}
return out;
}
static pruneUnused(existing, target, ignoreKeys) {

View File

@ -32,9 +32,11 @@ class PlayerData {
constructor(videoData) {
this.videoData = videoData;
this.video = videoData.video;
this.settings = videoData.settings;
this.element = undefined;
this.dimensions = undefined;
this.getPlayerDimensions();
this.startChangeDetection();
}
@ -43,7 +45,9 @@ class PlayerData {
return ( window.innerHeight == window.screen.height && window.innerWidth == window.screen.width);
}
panListener(event) {
this.panHandler(event);
}
start(){
this.startChangeDetection();
@ -55,6 +59,7 @@ class PlayerData {
}
destroy() {
this.element.removeEventListener('mousemove', this.panListener);
this.stopChangeDetection();
}
@ -139,6 +144,10 @@ class PlayerData {
this.scheduleGhettoWatcher();
}
panHandler(event) {
this.videoData.panHandler(event);
}
getPlayerDimensions(elementNames){
// element names — reserved for future use. If element names are provided, this function should return first element that
// has classname or id that matches at least one in the elementNames array.
@ -148,6 +157,10 @@ class PlayerData {
if(Debug.debug)
console.log("[PlayerDetect::_pd_getPlayerDimensions] element is not valid, doing nothing.", element)
if(this.element) {
const ths = this;
this.element.removeEventListener('mousemove', this.panListener);
}
this.element = undefined;
this.dimensions = undefined;
return;
@ -212,14 +225,24 @@ class PlayerData {
height: window.innerHeight,
fullscreen: true
}
const ths = this;
if(this.element) {
this.element.removeEventListener('mousemove', (event) => ths.panListener);
}
this.element = element;
this.element.addEventListener('mousemove', ths.panListener);
} else {
this.dimensions = {
width: candidate_width,
height: candidate_height,
fullscreen: isFullScreen
};
const ths = this;
if(this.element) {
this.element.removeEventListener('mousemove', (event) => ths.panListener);
}
this.element = playerCandidateNode;
this.element.addEventListener('mousemove', (event) => ths.panListener);
}
}

View File

@ -18,7 +18,7 @@ class Settings {
}
}
if(changes['uwSettings'] && changes['uwSettings'].newValue) {
ths.active = JSON.parse(changes.uwSettings.newValue);
ths.setActive(JSON.parse(changes.uwSettings.newValue));
}
if(this.updateCallback) {
@ -38,7 +38,7 @@ class Settings {
}
}
if(changes['uwSettings'] && changes['uwSettings'].newValue) {
ths.active = JSON.parse(changes.uwSettings.newValue);
ths.setActive(JSON.parse(changes.uwSettings.newValue));
}
if(this.updateCallback) {
@ -155,6 +155,7 @@ class Settings {
this.set(this.default);
}
// -----------------------------------------
// Nastavitve za posamezno stran
// Config for a given page:
@ -174,6 +175,16 @@ class Settings {
// * default — allow if default is to allow, block if default is to block
// * disabled — never allow
getSiteSettings(site) {
if (!site) {
site = window.location.hostname;
}
if (!site || !this.active.sites[site]) {
return {};
}
return this.active.sites[site];
}
canStartExtension(site) {
// returns 'true' if extension can be started on a given site. Returns false if we shouldn't run.
if (!site) {
@ -193,12 +204,6 @@ class Settings {
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:
@ -221,6 +226,13 @@ class Settings {
}
}
extensionEnabled(){
return this.active.extensionMode !== 'disabled'
}
extensionEnabledForSite(site) {
return this.canStartExtension(site);
}
canStartAutoAr(site) {
if (!site) {
@ -259,4 +271,31 @@ class Settings {
return false;
}
}
getDefaultAr(site) {
site = this.getSiteSettings(site);
if (site.defaultAr) {
return site.defaultAr;
}
return this.active.miscFullscreenSettings.defaultAr;
}
getDefaultStretchMode(site) {
site = this.getSiteSettings(site);
if (site.stretch) {
return site.stretch;
}
return this.active.stretch.initialMode;
}
getDefaultVideoAlignment(site) {
site = this.getSiteSettings(site);
if (site.videoAlignment) {
return site.videoAlignment;
}
return this.active.miscFullscreenSettings.videoFloat;
}
}

View File

@ -1,6 +1,6 @@
class VideoData {
constructor(video, settings){
constructor(video, settings, pageInfo){
this.arSetupComplete = false;
this.video = video;
this.destroyed = false;
@ -13,15 +13,26 @@ class VideoData {
this.arDetector = new ArDetector(this); // this starts Ar detection. needs optional parameter that prevets ardetdctor from starting
// player dimensions need to be in:
// this.player.dimensions
this.pageInfo = pageInfo;
this.vdid = (Math.random()*100).toFixed();
if (Debug.init) {
console.log("[VideoData::ctor] Created videoData with vdid", this.vdid);
}
}
firstTimeArdInit(){
if(this.destroyed) {
throw {error: 'VIDEO_DATA_DESTROYED', data: {videoData: this}};
}
if(! this.arSetupComplete){
this.arDetector = new ArDetector(this);
}
}
initArDetection() {
if(this.destroyed) {
throw {error: 'VIDEO_DATA_DESTROYED', data: {videoData: this}};
}
if(this.arDetector){
this.arDetector.init();
}
@ -32,6 +43,9 @@ class VideoData {
}
startArDetection() {
if(this.destroyed) {
throw {error: 'VIDEO_DATA_DESTROYED', data: {videoData: this}};
}
if(!this.arDetector) {
this.arDetector.init();
}
@ -45,10 +59,11 @@ class VideoData {
}
destroy() {
if(Debug.debug){
console.log("[VideoData::destroy] received destroy command");
if(Debug.debug || Debug.init){
console.log(`[VideoData::destroy] <vdid:${this.vdid}> received destroy command`);
}
this.pause();
this.destroyed = true;
if(this.arDetector){
this.arDetector.stop();
@ -80,6 +95,9 @@ class VideoData {
}
resume(){
if(this.destroyed) {
throw {error: 'VIDEO_DATA_DESTROYED', data: {videoData: this}};
}
this.paused = false;
try {
this.resizer.start();
@ -106,6 +124,29 @@ class VideoData {
this.resizer.setAr(ar, lastAr);
}
resetAr() {
this.resizer.reset();
}
panHandler(event) {
if(this.destroyed) {
throw {error: 'VIDEO_DATA_DESTROYED', data: {videoData: this}};
}
if(!this.resizer) {
this.destroy();
return;
}
this.resizer.panHandler(event);
}
setPanMode(mode) {
this.resizer.setPanMode(mode);
}
setVideoFloat(videoFloat) {
this.resizer.setVideoFloat(videoFloat);
}
restoreAr(){
this.resizer.restore();
}
@ -114,8 +155,15 @@ class VideoData {
this.resizer.setStretchMode(stretchMode);
}
zoomStep(step){
this.resizer.zoomStep();
setZoom(zoomLevel, no_announce){
this.resizer.setZoom(zoomLevel, no_announce);
}
zoomStep(step){
this.resizer.zoomStep(step);
}
announceZoom(scale){
this.pageInfo.announceZoom(scale);
}
}

View File

@ -15,17 +15,27 @@ class ArDetector {
this.fallbackMode = false;
this.blackLevel = this.settings.active.arDetect.blackLevel_default;
this.arid = (Math.random()*100).toFixed();
if (Debug.init) {
console.log("[ArDetector::ctor] creating new ArDetector. arid:", this.arid);
}
}
init(){
if(Debug.debug){
console.log("[ArDetect::init] Initializing autodetection")
if (Debug.debug || Debug.init) {
console.log("[ArDetect::init] Initializing autodetection. arid:", this.arid);
}
this.setup(this.settings.active.arDetect.hSamples, this.settings.active.arDetect.vSamples);
}
destroy(){
if(Debug.debug || Debug.init) {
console.log(`[ArDetect::destroy] <arid:${this.arid}>`)
}
this.debugCanvas.destroy();
this.stop();
}
setup(cwidth, cheight, forceStart){
@ -34,8 +44,8 @@ class ArDetector {
this.edgeDetector = new EdgeDetect(this);
this.debugCanvas = new DebugCanvas(this);
if(Debug.debug) {
console.log("[ArDetect::setup] Starting autodetection setup");
if(Debug.debug || Debug.init) {
console.log("[ArDetect::setup] Starting autodetection setup. arid:", this.arid);
}
if (this.fallbackMode || cheight !== this.settings.active.arDetect.hSamples) {
@ -476,12 +486,13 @@ class ArDetector {
var newCanvasWidth = window.innerHeight * (this.video.videoWidth / this.video.videoHeight);
var newCanvasHeight = window.innerHeight;
if(this.settings.active.miscFullscreenSettings.videoFloat == "center")
if (this.conf.resizer.videoFloat === "center") {
this.canvasDrawWindowHOffset = Math.round((window.innerWidth - newCanvasWidth) * 0.5);
else if(this.settings.active.miscFullscreenSettings.videFloat == "left")
} else if (this.conf.resizer.videoFloat == "left") {
this.canvasDrawWindowHOffset = 0;
else
} else {
this.canvasDrawWindowHOffset = window.innerWidth - newCanvasWidth;
}
this.setup(newCanvasWidth, newCanvasHeight);

View File

@ -18,12 +18,15 @@ class PageInfo {
}
if(this.videos.length > 0){
console.log("registering video")
comms.registerVideo();
}
this.currentZoomScale = 1;
}
destroy() {
if(Debug.debug){
if(Debug.debug || Debug.init){
console.log("[PageInfo::destroy] destroying all videos!")
}
if(this.rescanTimer){
@ -90,7 +93,7 @@ class PageInfo {
if(Debug.debug && Debug.periodic && Debug.videoRescan){
console.log("[PageInfo::rescan] found new video candidate:", video)
}
v = new VideoData(video, this.settings);
v = new VideoData(video, this.settings, this);
// console.log("[PageInfo::rescan] v is:", v)
// debugger;
v.initArDetection();
@ -118,7 +121,6 @@ class PageInfo {
this.videos = this.videos.filter( vid => vid.destroyed === false);
}
scheduleRescan(rescanReason){
if(rescanReason != RescanReason.PERIODIC){
this.rescan(rescanReason);
@ -220,11 +222,30 @@ class PageInfo {
if(ar !== 'auto') {
this.stopArDetection();
}
// TODO: find a way to only change aspect ratio for one video
for(var vd of this.videos){
if (ar === 'reset') {
for (var vd of this.videos) {
vd.resetAr();
}
} else {
for (var vd of this.videos) {
vd.setAr(ar)
}
}
}
setVideoFloat(videoFloat) {
for(var vd of this.videos) {
vd.setVideoFloat(videoFloat)
}
}
setPanMode(mode) {
for(var vd of this.videos) {
vd.setPanMode(mode);
}
}
restoreAr() {
for(var vd of this.videos){
@ -240,11 +261,30 @@ class PageInfo {
}
}
setZoom(zoomLevel, no_announce) {
for(var vd of this.videos) {
vd.setZoom(zoomLevel, no_announce);
}
}
zoomStep(step){
for(var vd of this.videos){
vd.zoomStep(step);
}
}
announceZoom(scale) {
if (this.announceZoomTimeout) {
clearTimeout(this.announceZoom);
}
this.currentZoomScale = scale;
const ths = this;
this.announceZoomTimeout = setTimeout(() => ths.comms.announceZoom(scale), this.settings.active.zoom.announceDebounce);
}
requestCurrentZoom() {
this.comms.announceZoom(this.currentZoomScale);
}
}
var RescanReason = {

View File

@ -34,22 +34,32 @@ class Resizer {
this.cssWatcherIncreasedFrequencyCounter = 0;
this.lastAr = {type: 'original'};
this.lastAr = this.settings.getDefaultAr(); // this is the aspect ratio we start with
this.videoFloat = this.settings.getDefaultVideoAlignment(); // this is initial video alignment
this.destroyed = false;
this.resizerId = (Math.random(99)*100).toFixed(0);
if (this.settings.active.pan) {
console.log("can pan:", this.settings.active.miscFullscreenSettings.mousePan.enabled, "(default:", this.settings.active.miscFullscreenSettings.mousePan.enabled, ")")
this.canPan = this.settings.active.miscFullscreenSettings.mousePan.enabled;
} else {
this.canPan = false;
}
}
start(){
if(!this.destroyed) {
this.startCssWatcher();
}
}
stop(){
this.stopCssWatcher();
}
destroy(){
if(Debug.debug){
if(Debug.debug || Debug.init){
console.log(`[Resizer::destroy] <rid:${this.resizerId}> received destroy command.`);
}
this.destroyed = true;
@ -83,7 +93,7 @@ class Resizer {
this.videoData.destroy();
}
// pause AR on basic stretch, unpause when using other mdoes
// // pause AR on basic stretch, unpause when using other mdoes
// fir sine reason unpause doesn't unpause. investigate that later
// if (this.stretcher.mode === StretchMode.BASIC) {
// this.conf.arDetector.pause();
@ -138,6 +148,24 @@ class Resizer {
this.restore();
}
panHandler(event) {
// console.log("this.conf.canPan:", this.conf.canPan)
if (this.canPan) {
// console.log("event?", event)
// console.log("this?", this)
if(!this.conf.player || !this.conf.player.element) {
return;
}
const player = this.conf.player.element;
const relativeX = (event.pageX - player.offsetLeft) / player.offsetWidth;
const relativeY = (event.pageY - player.offsetTop) / player.offsetHeight;
this.setPan(relativeX, relativeY);
}
}
setPan(relativeMousePosX, relativeMousePosY){
// relativeMousePos[X|Y] - on scale from 0 to 1, how close is the mouse to player edges.
// use these values: top, left: 0, bottom, right: 1
@ -145,14 +173,28 @@ class Resizer {
this.pan = {};
}
this.pan.relativeOffsetX = relativeMousePosX*2.5 - 1.25;
this.pan.relativeOffsetY = relativeMousePosY*2.5 - 1.25;
this.pan.relativeOffsetX = -(relativeMousePosX * 1.1) + 0.55;
this.pan.relativeOffsetY = -(relativeMousePosY * 1.1) + 0.55;
// if(Debug.debug){
// console.log("[Resizer::setPan] relative cursor pos:", relativeMousePosX, ",",relativeMousePosY, " | new pan obj:", this.pan)
// }
this.restore();
}
setVideoFloat(videoFloat) {
this.videoFloat = videoFloat;
this.restore();
}
startCssWatcher(){
if(Debug.debug) {
console.log("[Resizer.js::startCssWatcher] starting css watcher. Is resizer destroyed?", this.destroyed);
}
if (this.destroyed) {
return;
}
// this.haltCssWatcher = false;
if(!this.cssWatcherTimer){
this.scheduleCssWatcher(1);
@ -219,10 +261,24 @@ class Resizer {
this.setAr('reset');
}
setPanMode(mode) {
if (mode === 'enable') {
this.canPan = true;
} else if (mode === 'disable') {
this.canPan = false;
} else if (mode === 'toggle') {
this.canPan = !this.canPan;
}
}
resetPan(){
this.pan = undefined;
}
setZoom(zoomLevel, no_announce) {
this.zoom.setZoom(zoomLevel, no_announce);
}
zoomStep(step){
this.zoom.zoomStep(step);
}
@ -246,33 +302,48 @@ class Resizer {
computeOffsets(stretchFactors){
if(Debug.debug)
if (Debug.debug) {
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;
var wdiff = actualWidth - this.conf.player.dimensions.width;
var hdiff = actualHeight - this.conf.player.dimensions.height;
var translate = {x: 0, y: 0};
if (this.pan) {
// todo: calculate translate
// don't offset when video is smaller than player
if(wdiff < 0 && hdiff < 0) {
return translate;
}
translate.x = wdiff * this.pan.relativeOffsetX / this.zoom.scale;
translate.y = hdiff * this.pan.relativeOffsetY / this.zoom.scale;
} else {
if (this.settings.active.miscFullscreenSettings.videoFloat == "left") {
translate.x = (this.conf.player.dimensions.width - actualWidth) * -0.5;
if (this.videoFloat == "left") {
translate.x = wdiff * 0.5;
}
else if (this.settings.active.miscFullscreenSettings.videoFloat == "right") {
translate.x = (this.conf.player.dimensions.width - actualWidth) * 0.5;
else if (this.videoFloat == "right") {
translate.x = wdiff * -0.5;
}
}
if(Debug.debug) {
console.log("[Resizer::_res_computeOffsets] <rid:"+this.resizerId+"> calculated offsets:", translate);
}
return translate;
}
applyCss(stretchFactors, translate){
if (! this.video) {
if(Debug.debug)
if(Debug.debug) {
console.log("[Resizer::_res_applyCss] <rid:"+this.resizerId+"> Video went missing, doing nothing.");
}
this.conf.destroy();
return;
}
@ -376,6 +447,7 @@ class Resizer {
if(Debug.debug) {
console.log("[Resizer::cssCheck] <rid:"+this.resizerId+"> destroyed flag is set, we shouldnt be running");
}
this.stopCssWatcher();
return;
}

View File

@ -12,7 +12,7 @@ class Stretcher {
constructor(videoData) {
this.conf = videoData;
this.settings = videoData.settings;
this.mode = this.settings.active.stretch.initialMode;
this.mode = this.settings.getDefaultStretchMode();
}
applyConditionalStretch(stretchFactors, actualAr){

View File

@ -8,9 +8,10 @@ class Zoom {
// functions
constructor(videoData) {
this.scale = 1;
this.logScale = 0;
this.scaleStep = 0.1;
this.minScale = 0.5; // not accurate, actually slightly less
this.maxScale = 8; // not accurate, actually slightly more
this.minScale = -1; // 50% (log2(0.5) = -1)
this.maxScale = 3; // 800% (log2(8) = 3)
this.conf = videoData;
}
@ -18,41 +19,39 @@ class Zoom {
this.scale = 1;
}
zoomIn(){
this.scale += this.scaleStep;
if (this.scale >= this.maxScale) {
this.scale = this.maxScale;
}
}
zoomOut(){
this.scale -= this.scaleStep;
if (this.scale <= this.minScale) {
this.scale = this.minScale;
}
}
zoomStep(amount){
this.scale += amount;
this.logScale += amount;
if (this.scale <= this.minScale) {
this.scale = this.minScale;
}
if (this.scale >= this.maxScale) {
this.scale = this.maxScale;
if (this.logScale <= this.minScale) {
this.logScale = this.minScale;
}
if (this.logScale >= this.maxScale) {
this.logScale = this.maxScale;
}
this.scale = Math.pow(2, this.logScale);
if (Debug.debug) {
console.log("[Zoom::zoomStep] changing zoom by", amount, ". New zoom level:", this.scale);
}
this.conf.restoreAr();
this.conf.announceZoom(this.scale);
}
setZoom(scale, no_announce){
// NOTE: SCALE IS NOT LOGARITHMIC
if(scale < Math.pow(this.minScale)) {
scale = this.minScale;
} else if (scale > Math.pow(this.maxScale)) {
scale = this.maxScale;
}
setZoom(scale){
if(scale < this.minScale) {
this.scale = this.minScale;
} else if (scale > this.maxScale) {
this.scale = this.maxScale;
} else {
this.scale = scale;
this.conf.restoreAr();
if (!no_announce) {
this.conf.announceZoom(this.scale);
}
}

View File

@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "Ultrawidify",
"version": "3.1.0",
"version": "3.2.2",
"applications": {
"gecko": {
"id": "{cf02b1a7-a01a-4e37-a609-516a283f1ed3}"

214
res/css/common.css Normal file
View File

@ -0,0 +1,214 @@
html, body {
color: #f8f8f8;
background-color: #1f1f1f;
font-family: "overpass";
font-size: 1em;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
/* STANDARD WIDTHS AND HEIGHTS */
.w100 {
width: 100%;
}
.w24 {
width: 100px;
}
.m-t-0-33em {
margin-top: 0.33em;
}
.x-pad-1em {
padding-left: 1em;
padding-right: 1em;
}
/* ELEMENT POSITIONING */
.row {
display: block;
margin-top: 20px;
margin-bottom: 10px;
}
.button-row {
display: block;
margin-top: 5px;
margin-bottom: 10px;
}
.float-left {
float: left;
}
.float-right {
float: right;
}
.inline-block {
display: inline-block;
}
.block {
display: block;
}
.hidden {
display: none !important;
}
.hide {
display: none !important;
}
/* TEXT FORMATTING (no colors) */
small {
font-size: 0.75em;
font-weight: 200;
}
.small {
font-size: 0.75em;
font-weight: 200;
}
.medium-small {
font-size: 0.85em;
font-weight: 200;
}
.smallcaps{
font-variant: small-caps;
}
.center{
text-align: center;
width: 100%;
}
/* COLORS */
a {
color: #af7f37;
}
a:hover {
color: #c0924e;
}
.color_warn {
color: #d6ba4a;
}
strike {
opacity: 0.5;
}
.darker {
color: #666;
}
.label{
font-size: 1.1em;
font-weight: 600;
color: #ffe;
}
.selected{
color: #ffddaa;
background-color: #433221;
}
.disabled {
pointer-events: none;
/* color: #666; */
filter: contrast(50%) brightness(40%) grayscale(100%);
}
.disabled-button {
color: #666 !important;
cursor: not-allowed !important;
}
.disabled-button:hover {
color: #777 !important;
background-color: #222 !important;
}
/* BUTTONS AND INPUTS */
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;
}
.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;
}
/** misc **/
.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;
}
.experimental::after {
content: "Experimental";
background-color: #ffde12;
color: #1f1f1f;
display: inline-block;
font-size: .75em;
font-variant: small-caps;
padding-left: 5px;
padding-right: 5px;
margin-left: 10px;
}

View File

@ -1,117 +0,0 @@
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;
}

59
res/popup/css/popup.css Normal file
View File

@ -0,0 +1,59 @@
html, body {
width: 780px !important;
max-width: 800px !important;
padding: 0px;
margin: 0px;
}
.header {
background-color: #7f1416;
color: #fff;
margin: 0px;
margin-top: 0px;
padding-top: 8px;
padding-left: 15px;
padding-bottom: 1px;
font-size: 2.7em;
}
.menu-item-inline-desc{
font-size: 0.60em;
font-weight: 300;
font-variant: normal;
}
.left-side {
display: inline-block;
width: 39%;
float: left;
font-size: 1.6em;
}
.right-side {
display: inline-block;
width: 60%;
float: right;
}
.menu-item {
padding-left: 15px;
padding-top: 5px;
padding-bottom: 5px;
font-variant: small-caps;
}
.suboption {
display: block;
padding-left: 15px;
padding-right: 15px;
padding-top: 5px;
padding-bottom: 20px;
min-height: 250px;
}
#no-videos-display {
height: 100%;
padding-top: 50px;
/* text-align: center; */
}

View File

@ -5,60 +5,108 @@ document.getElementById("uw-version").textContent = browser.runtime.getManifest(
var Menu = {};
// Menu.noVideo = document.getElementById("no-videos-display");
Menu.thisSite = document.getElementById("settings-for-current-site");
Menu.arSettings = document.getElementById("aspect-ratio-settings");
Menu.autoAr = document.getElementById("autoar-basic-settings");
Menu.cssHacks = document.getElementById("css-hacks-settings");
Menu.about = document.getElementById("panel-about");
Menu.stretchSettings = document.getElementById("stretch-settings")
Menu.extensionSettings = document.getElementById('_menu_settings_ext');
Menu.siteSettings = document.getElementById('_menu_settings_site');
Menu.videoSettings = document.getElementById('_menu_settings_video');
Menu.about = document.getElementById('_menu_about')
var MenuTab = {};
MenuTab.general = document.getElementById("_menu_general");
MenuTab.thisSite = document.getElementById("_menu_this_site");
MenuTab.arSettings = document.getElementById("_menu_aspectratio");
MenuTab.cssHacks = document.getElementById("_menu_hacks");
MenuTab.about = document.getElementById("_menu_about");
MenuTab.autoAr = document.getElementById("_menu_autoar");
MenuTab.stretchSettings = document.getElementById("_menu_stretch");
MenuTab.extensionSettings = document.getElementById('_menu_tab_settings_ext');
MenuTab.siteSettings = document.getElementById('_menu_tab_settings_site');
MenuTab.videoSettings = document.getElementById('_menu_tab_settings_video');
MenuTab.about = document.getElementById('_menu_tab_about')
//#region ExtPanel
var ExtPanel = {};
ExtPanel.globalOptions = {};
ExtPanel.globalOptions.blacklist = document.getElementById("_ext_global_options_blacklist");
ExtPanel.globalOptions.whitelist = document.getElementById("_ext_global_options_whitelist");
ExtPanel.globalOptions.disabled = document.getElementById("_ext_global_options_disabled");
ExtPanel.siteOptions = {};
ExtPanel.siteOptions.disabled = document.getElementById("_ext_site_options_blacklist");
ExtPanel.siteOptions.enabled = document.getElementById("_ext_site_options_whitelist");
ExtPanel.siteOptions.default = document.getElementById("_ext_site_options_default");
ExtPanel.extOptions = {};
ExtPanel.extOptions.blacklist = document.getElementById("_ext_global_options_blacklist");
ExtPanel.extOptions.whitelist = document.getElementById("_ext_global_options_whitelist");
ExtPanel.extOptions.disabled = document.getElementById("_ext_global_options_disabled");
ExtPanel.arOptions = {};
ExtPanel.arOptions.blacklist = document.getElementById("_ar_global_options_blacklist");
ExtPanel.arOptions.whitelist = document.getElementById("_ar_global_options_whitelist");
ExtPanel.arOptions.disabled = document.getElementById("_ar_global_options_disabled");
ExtPanel.alignment = {};
ExtPanel.alignment.left = document.getElementById("_align_ext_left");
ExtPanel.alignment.center = document.getElementById("_align_ext_center");
ExtPanel.alignment.right = document.getElementById("_align_ext_right");
ExtPanel.stretch = {};
ExtPanel.stretch['0'] = document.getElementById("_stretch_global_none");
ExtPanel.stretch['1'] = document.getElementById("_stretch_global_basic");
ExtPanel.stretch['2'] = document.getElementById("_stretch_global_hybrid");
ExtPanel.stretch['3'] = document.getElementById("_stretch_global_conditional");
//#endregion
//#region SitePanel
var SitePanel = {};
SitePanel.extOptions = {};
SitePanel.extOptions.enabled = document.getElementById("_ext_site_options_whitelist");
SitePanel.extOptions.default = document.getElementById("_ext_site_options_default");
SitePanel.extOptions.disabled = document.getElementById("_ext_site_options_blacklist");
SitePanel.arOptions = {};
SitePanel.arOptions.disabled = document.getElementById("_ar_site_options_disabled");
SitePanel.arOptions.enabled = document.getElementById("_ar_site_options_enabled");
SitePanel.arOptions.default = document.getElementById("_ar_site_options_default");
SitePanel.alignment = {};
SitePanel.alignment.left = document.getElementById("_align_site_left");
SitePanel.alignment.center = document.getElementById("_align_site_center");
SitePanel.alignment.right = document.getElementById("_align_site_right");
SitePanel.alignment.default = document.getElementById("_align_site_default");
SitePanel.stretch = {};
SitePanel.stretch['-1'] = document.getElementById("_stretch_site_default")
SitePanel.stretch['0'] = document.getElementById("_stretch_site_none")
SitePanel.stretch['1'] = document.getElementById("_stretch_site_basic")
SitePanel.stretch['2'] = document.getElementById("_stretch_site_hybrid")
SitePanel.stretch['3'] = document.getElementById("_stretch_site_conditional")
//#endregion
//#region VideoPanel
var VideoPanel = {};
VideoPanel.alignment = {};
VideoPanel.alignment.left = document.getElementById("_align_video_left");
VideoPanel.alignment.center = document.getElementById("_align_video_center");
VideoPanel.alignment.right = document.getElementById("_align_video_right");
var AutoArPanel = {};
AutoArPanel.globalOptions = {};
AutoArPanel.globalOptions.blacklist = document.getElementById("_ar_global_options_blacklist");
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_disabled");
AutoArPanel.siteOptions.enabled = document.getElementById("_ar_site_options_enabled");
AutoArPanel.siteOptions.default = document.getElementById("_ar_site_options_default");
// labels on buttons
VideoPanel.buttonLabels = {};
VideoPanel.buttonLabels.crop = {};
VideoPanel.buttonLabels.crop['auto-ar'] = document.getElementById("_b_changeAr_auto-ar_key");
VideoPanel.buttonLabels.crop.reset = document.getElementById("_b_changeAr_reset_key");
VideoPanel.buttonLabels.crop['219'] = document.getElementById("_b_changeAr_219_key");
VideoPanel.buttonLabels.crop['189'] = document.getElementById("_b_changeAr_189_key");
VideoPanel.buttonLabels.crop['169'] = document.getElementById("_b_changeAr_169_key");
VideoPanel.buttonLabels.crop.custom = document.getElementById("_b_changeAr_custom_key");
VideoPanel.buttonLabels.zoom = {};
var ArPanel = {};
ArPanel.alignment = {};
ArPanel.alignment.left = document.getElementById("_align_left");
ArPanel.alignment.center = document.getElementById("_align_center");
ArPanel.alignment.right = document.getElementById("_align_right");
ArPanel.autoar = {};
// buttons: for toggle, select
VideoPanel.buttons = {};
VideoPanel.buttons.zoom = {};
VideoPanel.buttons.zoom.showShortcuts = document.getElementById("_zoom_b_show_shortcuts");
VideoPanel.buttons.zoom.hideShortcuts = document.getElementById("_zoom_b_hide_shortcuts");
VideoPanel.buttons.changeAr = {};
VideoPanel.buttons.changeAr.showCustomAr = document.getElementById("_changeAr_b_show_customAr");
VideoPanel.buttons.changeAr.hideCustomAr = document.getElementById("_changeAr_b_hide_customAr");
var StretchPanel = {};
StretchPanel.global = {};
StretchPanel.global.none = document.getElementById("_stretch_global_none");
StretchPanel.global.basic = document.getElementById("_stretch_global_basic");
StretchPanel.global.hybrid = document.getElementById("_stretch_global_hybrid");
StretchPanel.global.conditional = document.getElementById("_stretch_global_conditional");
// inputs (getting values)
VideoPanel.inputs = {};
VideoPanel.inputs.customCrop = document.getElementById("_input_custom_ar");
VideoPanel.inputs.zoomSlider = document.getElementById("_input_zoom_slider");
VideoPanel.inputs.allowPan = document.getElementById("_input_zoom_site_allow_pan");
// various labels
VideoPanel.labels = {};
VideoPanel.labels.zoomLevel = document.getElementById("_label_zoom_level");
// misc stuff
VideoPanel.misc = {};
VideoPanel.misc.zoomShortcuts = document.getElementById("_zoom_shortcuts");
VideoPanel.misc.customArChanger = document.getElementById("_changeAr_customAr");
//#endregion
var selectedMenu = "";
var hasVideos = false;
var zoom_videoScale = 1;
var _config;
var _changeAr_button_shortcuts = { "autoar":"none", "reset":"none", "219":"none", "189":"none", "169":"none", "custom":"none" }
@ -72,18 +120,42 @@ port.onMessage.addListener( (m,p) => processReceivedMessage(m,p));
async function processReceivedMessage(message, port){
if (Debug.debug) {
console.log("[popup.js] received message", message)
}
if(message.cmd === 'set-current-site'){
if (site !== message.site) {
port.postMessage({cmd: 'get-current-zoom'});
}
site = message.site;
loadConfig(message.site);
} else if (message.cmd === 'set-current-zoom') {
setCurrentZoom(message.zoom);
}
}
async function updateConfig() {
if (Debug.debug) {
console.log("[popup.js] settings changed. updating popup if site exists. Site:", site);
}
if (site) {
loadConfig(site);
}
}
async function setCurrentZoom(scale) {
zoom_videoScale = scale;
if(Debug.debug) {
console.log("[popup.js::setCurrentZoom] we're setting zoom:", zoom_videoScale);
}
VideoPanel.inputs.zoomSlider.value = Math.log2(zoom_videoScale);
VideoPanel.labels.zoomLevel.textContent = (zoom_videoScale * 100).toFixed();
}
function hideWarning(warn){
document.getElementById(warn).classList.add("hidden");
}
@ -106,121 +178,144 @@ function stringToKeyCombo(key_in){
return keys_out;
}
async function loadConfig(site){
function configurePopupTabs(site) {
// Determine which tabs can we touch.
// If extension is disabled, we can't touch 'site settings' and 'video settings'
// If extension is enabled, but site is disabled, we can't touch 'video settings'
var extensionEnabled = settings.extensionEnabled();
var extensionEnabledForSite = settings.extensionEnabledForSite(site);
if(Debug.debug)
console.log("[popup.js::loadConfig] loading config. conf object:", settings.active, "\n\n\n\n\n\n\n\n-------------------------------------");
MenuTab.siteSettings.classList.add('disabled');
// -----------------------
//#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 (extensionEnabledForSite) {
MenuTab.videoSettings.classList.remove('disabled');
}
if (extensionEnabled) {
MenuTab.videoSettings.classList.remove('disabled');
}
if (canStartExtension) {
MenuTab.arSettings.classList.remove('disabled');
MenuTab.autoAr.classList.remove('disabled');
MenuTab.stretchSettings.classList.remove('disabled');
// we assume that these two can be shown. If extension or site are disabled, we'll
// add 'disabled' class later down the line:
document.getElementById("_site_only_when_site_enabled").classList.remove("disabled");
document.getElementById("_ext_only_when_ext_enabled").classList.remove("disabled");
// only switch when popup is being opened for the first time
if(! selectedMenu) {
openMenu('arSettings');
if (! extensionEnabledForSite) {
MenuTab.videoSettings.classList.add('disabled');
// also disable extra settings for site
document.getElementById("_site_only_when_site_enabled").classList.add("disabled");
if (! extensionEnabled) {
MenuTab.siteSettings.classList.add('disabled');
// also disable extra settings for extension
document.getElementById("_ext_only_when_ext_enabled").classList.add("disabled");
if (!selectedMenu) {
openMenu('extensionSettings');
}
} else {
MenuTab.arSettings.classList.add('disabled');
MenuTab.autoAr.classList.add('disabled');
MenuTab.stretchSettings.classList.add('disabled');
MenuTab.siteSettings.classList.remove('disabled');
if (!selectedMenu) {
openMenu('siteSettings');
}
}
} else {
MenuTab.videoSettings.classList.remove('disabled');
MenuTab.siteSettings.classList.remove('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');
if (!selectedMenu) {
openMenu('videoSettings');
}
}
}
//#endregion
//
// ----------------------
//#region extension-basics - SET BASIC EXTENSION OPTIONS
if(Debug.debug)
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) {
ExtPanel.globalOptions[button].classList.remove("selected");
}
for(var button in ExtPanel.siteOptions) {
ExtPanel.siteOptions[button].classList.remove("selected");
function configureGlobalTab() {
if (Debug.debug) {
console.log("[popup.js] Configuring global tab (ExtPanel).",
"\nextension mode: ", settings.active.extensionMode,
"\narDetect mode: ", settings.active.arDetect.mode,
"\nvideo float mode:", settings.active.miscFullscreenSettings.videoFloat,
"\nstretch mode: ", settings.active.stretch.initialMode,
"\n..")
}
ExtPanel.globalOptions[settings.active.extensionMode].classList.add("selected");
if(site && settings.active.sites[site]) {
ExtPanel.siteOptions[settings.active.sites[site].status].classList.add("selected");
for(var button in ExtPanel.extOptions) {
ExtPanel.extOptions[button].classList.remove("selected");
}
for(var button in ExtPanel.arOptions) {
ExtPanel.arOptions[button].classList.remove("selected");
}
for(var button in ExtPanel.alignment) {
ExtPanel.alignment[button].classList.remove("selected");
}
for(var button in ExtPanel.stretch) {
ExtPanel.stretch[button].classList.remove("selected");
}
ExtPanel.extOptions[settings.active.extensionMode].classList.add("selected");
ExtPanel.arOptions[settings.active.arDetect.mode].classList.add("selected");
ExtPanel.alignment[settings.active.miscFullscreenSettings.videoFloat].classList.add("selected");
ExtPanel.stretch[settings.active.stretch.initialMode].classList.add("selected");
}
function configureSitesTab(site) {
if (Debug.debug) {
console.log("[popup.js] Configuring sites tab (SitePanel).",
"\nsite: ", site,
"\nextension mode: ", settings.active.sites[site] ? settings.active.sites[site].status : 'no site-special settings for this site',
"\narDetect mode: ", settings.active.sites[site] ? settings.active.sites[site].arStatus : 'no site-special settings for this site',
"\nvideo float mode:", settings.active.sites[site] ? settings.active.sites[site].videoFloat : 'no site-special settings for this site',
"\ndefault ar: ", settings.active.sites[site] ? settings.active.sites[site].ar : 'no site-special settings for this site',
"\nstretch mode: ", settings.active.sites[site] ? settings.active.sites[site].stretch : 'no site-special settings for this site',
"\n...")
}
for(const button in SitePanel.extOptions) {
SitePanel.extOptions[button].classList.remove("selected");
}
for(const button in SitePanel.arOptions) {
SitePanel.arOptions[button].classList.remove("selected");
}
for(const button in SitePanel.alignment) {
SitePanel.alignment[button].classList.remove("selected");
}
for(const button in SitePanel.stretch) {
SitePanel.stretch[button].classList.remove("selected");
}
if (settings.active.sites[site] && settings.active.sites[site]) {
console.log("settings for", site, "exist!")
SitePanel.extOptions[settings.active.sites[site].status].classList.add("selected");
SitePanel.arOptions[settings.active.sites[site].arStatus].classList.add("selected");
} else {
ExtPanel.siteOptions.default.classList.add("selected");
SitePanel.extOptions.default.classList.add("selected");
SitePanel.arOptions.default.classList.add("selected");
}
//#endregion extension-basics
//
// ------------
//#region autoar - SET AUTOAR OPTIONS
// if(Debug.debug)
// 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) {
AutoArPanel.globalOptions[button].classList.remove("selected");
}
for(var button in AutoArPanel.siteOptions) {
AutoArPanel.siteOptions[button].classList.remove("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");
// optional settings:
if (settings.active.sites[site] && settings.active.sites[site].videoAlignment) {
SitePanel.alignment[settings.active.sites[site].videoAlignment].classList.add("selected");
} else {
AutoArPanel.siteOptions.default.classList.add("selected");
}
//#endregion
// process video alignment:
if(settings.active.miscFullscreenSettings.videoFloat){
for(var button in ArPanel.alignment)
ArPanel.alignment[button].classList.remove("selected");
ArPanel.alignment[settings.active.miscFullscreenSettings.videoFloat].classList.add("selected");
SitePanel.alignment.default.classList.add('selected');
}
//#region - SET STRETCH
// set stretching
for (var button in StretchPanel.global) {
StretchPanel.global[button].classList.remove("selected");
if(settings.active.sites[site] && settings.active.sites[site].stretch !== undefined) { // can be 0
SitePanel.stretch[settings.active.sites[site].stretch].classList.add("selected");
} else {
SitePanel.stretch['-1'].classList.add("selected");
}
if (settings.active.stretch.initialMode === 0) {
StretchPanel.global.none.classList.add("selected");
} else if (settings.active.stretch.initialMode === 1) {
StretchPanel.global.basic.classList.add("selected");
} else if (settings.active.stretch.initialMode === 2) {
StretchPanel.global.hybrid.classList.add("selected");
} else if (settings.active.stretch.initialMode === 3) {
StretchPanel.global.conditional.classList.add("selected");
}
//#endregion
}
// process keyboard shortcuts:
function configureVideoTab() {
// process keyboard shortcuts for crop settings
if(settings.active.keyboard.shortcuts){
for(var key in settings.active.keyboard.shortcuts){
var shortcut = settings.active.keyboard.shortcuts[key];
var keypress = stringToKeyCombo(key);
try{
if(shortcut.action == "crop"){
if (key == 'q') {
@ -252,12 +347,13 @@ async function loadConfig(site){
catch(Ex){
//do nothing if key doesn't exist
}
}
// fill in custom aspect ratio
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){
try{
document.getElementById(`_b_changeAr_${key}_key`).textContent = `(${_changeAr_button_shortcuts[key]})`;
@ -268,24 +364,66 @@ async function loadConfig(site){
}
}
// todo: get min, max from settings
VideoPanel.inputs.zoomSlider.min = Math.log2(0.5);
VideoPanel.inputs.zoomSlider.max = Math.log2(8);
VideoPanel.inputs.zoomSlider.value = Math.log2(zoom_videoScale);
if(Debug.debug)
console.log("[popup.js::loadConfig] config loaded");
VideoPanel.inputs.zoomSlider.addEventListener('input', (event) => {
var newZoom = Math.pow(2, VideoPanel.inputs.zoomSlider.value);
// save value so it doesn't get reset next time the popup updates
zoom_videoScale = newZoom;
// update zoom% label
VideoPanel.labels.zoomLevel.textContent = (newZoom * 100).toFixed();
// send the command to bg script
var command = {
cmd: 'set-zoom',
zoom: newZoom
};
port.postMessage(command);
});
}
async function loadConfig(site){
console.log("NEW CONFIG!")
if (Debug.debug) {
console.log("\n\n-------------------------------------\n[popup.js::loadConfig] loading config. conf object:", settings.active);
}
document.getElementById("_menu_tab_settings_site_site_label").textContent = site;
configurePopupTabs(site);
configureGlobalTab();
configureSitesTab(site);
configureVideoTab();
if (Debug.debug) {
console.log("[popup.js::loadConfig] config loaded\n-----------------------\n\n");
}
}
async function getSite(){
if (Debug.debug) {
console.log("[popup.js] requesting current site");
}
port.postMessage({cmd: 'get-current-site'});
}
function openMenu(menu){
if(Debug.debug){
console.log("[popup.js::openMenu] trying to open menu", menu, "| element: ", Menu[menu]);
console.log("[popup.js::openMenu] trying to open menu", menu, "\n element: ", Menu[menu]);
}
for(var m in Menu){
if(Menu[m] === null)
continue; //todo: remove menus that are no longer there
if(Menu[m])
Menu[m].classList.add("hidden");
}
for(var m in MenuTab){
@ -293,25 +431,11 @@ function openMenu(menu){
MenuTab[m].classList.remove("selected");
}
if(menu == "arSettings" || menu == "cssHacks" ){
// if(!hasVideos)
// Menu.noVideo.classList.remove("hidden");
// else{
Menu[menu].classList.remove("hidden");
if(Debug.debug){
console.log("[popup.js::openMenu] unhid", menu, "| element: ", Menu[menu]);
}
// }
}
else{
Menu[menu].classList.remove("hidden");
if(Debug.debug){
console.log("[popup.js::openMenu] unhid", menu, "| element: ", Menu[menu]);
}
}
MenuTab[menu].classList.add("selected");
selectedMenu = menu;
MenuTab[menu].classList.add("selected");
}
@ -381,24 +505,20 @@ document.addEventListener("click", (e) => {
return;
if(e.target.classList.contains("menu-item")){
if(e.target.classList.contains("_menu_this_site")){
openMenu("thisSite");
if(Debug.debug) {
console.log("[popup.js::eventListener] clicked on a tab. Class list:", e.target.classList);
}
else if(e.target.classList.contains("_menu_aspectratio")){
openMenu("arSettings");
}
else if(e.target.classList.contains("_menu_stretch")){
openMenu("stretchSettings");
}
else if(e.target.classList.contains("_menu_hacks")){
openMenu("cssHacks");
}
else if(e.target.classList.contains("_menu_about")){
if(e.target.classList.contains("_menu_tab_settings_ext")){
openMenu("extensionSettings");
} else if(e.target.classList.contains("_menu_tab_settings_site")){
openMenu("siteSettings");
} else if(e.target.classList.contains("_menu_tab_settings_video")){
openMenu("videoSettings");
} else if(e.target.classList.contains("_menu_tab_about")){
openMenu("about");
}
else if(e.target.classList.contains("_menu_autoar")){
openMenu("autoAr");
}
// don't send commands
return;
@ -495,6 +615,7 @@ document.addEventListener("click", (e) => {
}
}
if(e.target.classList.contains("_stretch")){
// stretch, global
if (e.target.classList.contains("_ar_stretch_global")) {
if (e.target.classList.contains("_none")) {
settings.active.stretch.initialMode = 0;
@ -509,6 +630,23 @@ document.addEventListener("click", (e) => {
return;
}
// stretch, site
if (e.target.classList.contains("_ar_stretch_site")) {
if (e.target.classList.contains("_none")) {
settings.active.sites[site].stretch = 0;
} else if (e.target.classList.contains("_basic")) {
settings.active.sites[site].stretch = 1;
} else if (e.target.classList.contains("_hybrid")) {
settings.active.sites[site].stretch = 2;
} else if (e.target.classList.contains("_conditional")) {
settings.active.sites[site].stretch = 3;
} else {
delete(settings.active.sites[site].stretch);
}
settings.save();
return;
}
if(e.target.classList.contains("_ar_stretch_none")) {
command.cmd = "set-stretch";
command.mode = "NO_STRETCH";
@ -569,21 +707,88 @@ document.addEventListener("click", (e) => {
}
}
if(e.target.classList.contains("_align")){
command.global = true;
if (e.target.classList.contains("_align_left")) {
if (e.target.classList.contains("_align_ext")) {
if (e.target.classList.contains("_align_ext_left")) {
settings.active.miscFullscreenSettings.videoFloat = 'left';
} else if (e.target.classList.contains("_align_center")) {
} else if (e.target.classList.contains("_align_ext_center")) {
settings.active.miscFullscreenSettings.videoFloat = 'center';
} else if (e.target.classList.contains("_align_right")) {
settings.active.miscFullscreenSettings.videoFloat = 'left';
} else if (e.target.classList.contains("_align_ext_right")) {
settings.active.miscFullscreenSettings.videoFloat = 'right';
}
settings.save();
return;
}
if (e.target.classList.contains("_align_site")) {
if (!site) {
return;
}
if (e.target.classList.contains("_align_site_left")) {
settings.active.sites[site].videoAlignment = 'left';
} else if (e.target.classList.contains("_align_site_center")) {
settings.active.sites[site].videoAlignment = 'center';
} else if (e.target.classList.contains("_align_site_right")) {
settings.active.sites[site].videoAlignment = 'right';
} else {
// default case — remove this object
delete(settings.active.sites[site].videoAlignment);
}
settings.save();
return;
}
if (e.target.classList.contains("_align")) {
command.cmd = "set-alignment";
if (e.target.classList.contains("_align_video_left")) {
command.mode = 'left';
} else if (e.target.classList.contains("_align_video_center")) {
command.mode = 'center';
} else if (e.target.classList.contains("_align_video_right")) {
command.mode = 'right';
}
return command;
}
//#region zoom buttons
if (e.target.classList.contains("_zoom_show_shortcuts")) {
VideoPanel.misc.zoomShortcuts.classList.remove("hidden");
VideoPanel.buttons.zoom.hideShortcuts.classList.remove("hidden");
VideoPanel.buttons.zoom.showShortcuts.classList.add("hidden");
return;
}
if (e.target.classList.contains("_zoom_hide_shortcuts")) {
VideoPanel.misc.zoomShortcuts.classList.add("hidden");
VideoPanel.buttons.zoom.hideShortcuts.classList.add("hidden");
VideoPanel.buttons.zoom.showShortcuts.classList.remove("hidden");
return;
}
if (e.target.classList.contains("_zoom_reset")) {
zoom_videoScale = scale;
VideoPanel.labels.zoomLevel.textContent = 100;
VideoPanel.inputs.zoomSlider.value = 0; // log₂(1)
command.cmd = 'set-zoom';
command.zoom = 1;
return command;
}
//#endregion
//#region show/hide custom ar
if (e.target.classList.contains("_changeAr_show_customAr")) {
VideoPanel.misc.customArChanger.classList.remove("hidden");
VideoPanel.buttons.changeAr.showCustomAr.classList.add("hidden");
VideoPanel.buttons.changeAr.hideCustomAr.classList.remove("hidden");
return;
}
if (e.target.classList.contains("_changeAr_hide_customAr")) {
VideoPanel.misc.customArChanger.classList.add("hidden");
VideoPanel.buttons.changeAr.showCustomAr.classList.remove("hidden");
VideoPanel.buttons.changeAr.hideCustomAr.classList.add("hidden");
return;
}
//#endregion
}
var command = getcmd(e);
@ -596,7 +801,11 @@ document.addEventListener("click", (e) => {
async function sleep(t) {
return new Promise( (resolve,reject) => {
setTimeout(() => resolve(), t);
});
}
async function popup_init() {
// let's init settings and check if they're loaded
@ -617,15 +826,19 @@ async function popup_init() {
validateCustomAr();
});
autoarFrequencyInputField.addEventListener("blur", (event) => {
validateAutoArTimeout();
});
autoarFrequencyInputField.addEventListener("mouseleave", (event) => {
validateAutoArTimeout();
});
// autoarFrequencyInputField.addEventListener("blur", (event) => {
// validateAutoArTimeout();
// });
// autoarFrequencyInputField.addEventListener("mouseleave", (event) => {
// validateAutoArTimeout();
// });
hideWarning("script-not-running-warning");
while (true) {
console.log("GETTING SITE")
getSite();
await sleep(5000);
}
}
popup_init();

View File

@ -5,137 +5,45 @@
<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 {
width: 780px !important;
max-width: 800px !important;
padding: 0px;
margin: 0px;
/* width: 100%; */
color: #f8f8f8;
background-color: #1f1f1f;
font-family: "overpass";
font-size: 1em;
}
strike {
opacity: 0.5;
}
.darker {
color: #666;
}
.label{
font-size: 1.1em;
font-weight: 600;
color: #ffe;
}
.selected{
color: #ffddaa;
background-color: #433221;
}
.disabled {
color: #666;
}
.disabled-button {
color: #666 !important;
cursor: not-allowed !important;
}
.disabled-button:hover {
color: #777 !important;
background-color: #222 !important;
}
.header {
background-color: #7f1416;
color: #fff;
margin: 0px;
margin-top: 0px;
padding-top: 8px;
padding-left: 15px;
padding-bottom: 1px;
font-size: 2.7em;
}
.menu-item-inline-desc{
font-size: 0.60em;
font-weight: 300;
font-variant: normal;
}
.left-side {
display: inline-block;
width: 39%;
float: left;
font-size: 1.6em;
}
.right-side {
display: inline-block;
width: 60%;
float: right;
}
.menu-item {
padding-left: 15px;
padding-top: 5px;
padding-bottom: 5px;
font-variant: small-caps;
}
.suboption {
display: block;
padding-left: 15px;
padding-right: 15px;
padding-top: 5px;
padding-bottom: 20px;
min-height: 250px;
}
#no-videos-display {
height: 100%;
padding-top: 50px;
/* text-align: center; */
}
</style>
<link rel='stylesheet' type='text/css' href='../css/common.css'>
<link rel='stylesheet' type='text/css' href='./css/popup.css'>
</head>
<body>
<div class="header">
U<span class="smallcaps">ltrawidify</span>: <small>Quick settings</small>
</div>
<!-- TABS/SIDEBAR -->
<div class="left-side">
<div id="_menu_this_site" class="menu-item _menu_this_site">
Settings for this site
<div id="_menu_tab_settings_ext" class="menu-item _menu_tab_settings_ext">
Extension settings
</div>
<div id="_menu_autoar" class="menu-item _menu_autoar">
Automatic aspect ratio detection (auto-ar)
<div id="_menu_tab_settings_site" class="menu-item _menu_tab_settings_site">
Site settings
<span class="menu-item-inline-desc"><br/>Settings for <span id="_menu_tab_settings_site_site_label"></span></span>
</div>
<div id="_menu_aspectratio" class="menu-item selected _menu_aspectratio">
Crop settings
<div id="_menu_tab_settings_video" class="menu-item _menu_tab_settings_video">
Video settings
<span class="menu-item-inline-desc"><br/>Crop & stretch options for current video</span>
</div>
<div id="_menu_stretch" class="menu-item _menu_stretch">
Stretch settings
</div>
<div id="_menu_csshacks" class="menu-item disabled hidden _menu_hacks">
CSS hacks for this site
</div>
<div id="_menu_about" class="menu-item _menu_about">
<div id="_menu_tab_about" class="menu-item _menu_tab_about">
About Ultrawidify<span class="menu-item-inline-desc"><br/>See for bug reports</span>
</div>
</div>
<!-- PANELS/CONTENT -->
<div class="right-side">
<div id="script-not-running-warning" class="warning">If you see this line, then your browser didn't start the popup script yet. This is a problem caused by the browser. Please wait a few seconds.</div>
<div id="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>
<!-- EXTENSION SETTINGS -->
<div id="_menu_settings_ext" class="suboption hidden">
<p>These settings can be overriden on per-site basis.</p>
<div class="row">
<span class="label">Enable this extension:</span>
<div class="button-row">
@ -143,19 +51,8 @@
<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>
</div>
<div class="row">
<span class="label">Options for this site:</span>
<div class="button-row">
<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>
<div id="autoar-basic-settings" class="suboption hidden">
<div id="_ext_only_when_ext_enabled">
<div class="row">
<span class="label">Enable autodetection:</span>
<div class="button-row">
@ -164,23 +61,86 @@
<a id="_ar_global_options_disabled" class="button _autoAr _ar_global_options _disabled" >Never</a>
</div>
</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_timer" class="button _save_autoAr_timer _autoAr">Save</span></p>
<!-- TODO: default aspect ratio settings -->
<div class="row">
<span class="label experimental">Default stretching mode</span>
<div class="button-row">
<a id="_stretch_global_none" class="button _stretch _ar_stretch_global _none w24">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 w24">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 w24">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 w24">Thin borders<br/><span id="_b_stretch_default_conditional_key" class="smallcaps small darker"></span></a>
</div>
</div>
<!-- VIDEO ALIGNMENT -->
<div class="row">
<span class="label">Video alignment:</span>
<div class="button-row">
<a id="_align_ext_left" class="button _align_ext _align_ext_left">Left</a>
<a id="_align_ext_center" class="button _align_ext _align_ext_center">Center</a>
<a id="_align_ext_right" class="button _align_ext _align_ext_right">Right</a>
</div>
</div>
</div>
</div>
</div>
<!-- SITE SETTINGS -->
<div id="_menu_settings_site" class="suboption hidden">
<div class="row">
<span class="label">Options for this site:</span>
<div class="button-row">
<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>
<!-- things that are disabled if site is disabled -->
<div id="_site_only_when_site_enabled">
<div class="row">
<span class="label">Automatic detection:</span>
<div class="button-row">
<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>
<!-- TODO: default aspect ratio, default settings -->
<!-- STRETCH MODE -->
<div class="row">
<span class="label experimental">Default stretching mode</span>
<div class="button-row">
<a id="_stretch_site_none" class="button _stretch _ar_stretch_site _none w24">Never<br/><span id="_b_stretch_default_none_key" class="smallcaps small darker"></span></a>
<a id="_stretch_site_basic" class="button _stretch _ar_stretch_site _basic w24">Basic<br/><span id="_b_stretch_default_basic_key" class="smallcaps small darker"></span></a>
<a id="_stretch_site_hybrid" class="button _stretch _ar_stretch_site _hybrid w24">Hybrid<br/><span id="_b_stretch_default_hybrid_key" class="smallcaps small darker"></span></a>
<a id="_stretch_site_conditional" class="button _stretch _ar_stretch_site _conditional w24">Thin borders<br/><span id="_b_stretch_default_conditional_key" class="smallcaps small darker"></span></a>
<a id="_stretch_site_default" class="button _stretch _ar_stretch_site _default w24">Default<br/><span id="_b_stretch_default_conditional_key" class="smallcaps small darker"></span></a>
</div>
</div>
<div id="aspect-ratio-settings" class="suboption hidden">
<div id="no-videos-warning"></div>
<!-- <div id="no-videos-warning" class="warning">No videos were detected on this page. The buttons may not work at all. Check that this site is not blacklisted and reload the page.</div> -->
<!-- VIDEO ALIGNMENT -->
<div class="row">
<span class="label">Video alignment:</span>
<div class="button-row">
<a id="_align_site_left" class="button _align_site _align_site_left">Left</a>
<a id="_align_site_center" class="button _align_site _align_site_center">Center</a>
<a id="_align_site_right" class="button _align_site _align_site_right">Right</a>
<a id="_align_site_default"class="button _align_site _align_site_default">Default</a>
</div>
</div>
</div>
</div>
<!-- VIDEO SETTINGS -->
<div id="_menu_settings_video" class="suboption">
<!-- CROP STUFF -->
<div class="row">
<span class="label">Cropping mode</span>
<div class="button-row">
@ -191,8 +151,14 @@
<a class="button _changeAr _ar_169 w24">16:9<br/><span id="_b_changeAr_169_key" class="smallcaps small darker">&nbsp;</span></a>
<a class="button _changeAr _ar_custom w24">Custom<br/><span id="_b_changeAr_custom_key" class="smallcaps small darker">&nbsp;</span></a>
</div>
<div style="overflow: auto">
<div class="float-right medium-small">
<a id="_changeAr_b_show_customAr" class="_changeAr_show_customAr x-pad-1em">Set custom aspect ratio</a>
<a id="_changeAr_b_hide_customAr" class="_changeAr_hide_customAr hidden x-pad-1em">Hide custom aspect ratio settings</a>
</div>
<div class="row">
</div>
</div>
<div id="_changeAr_customAr" class="row hidden">
<span class="label">Custom aspect ratio</span>
<div>
<input id="_input_custom_ar" class="_changeAr _custom" onblur="validateCustomAr()"> &nbsp; &nbsp; <span id="_b_changeAr_save_custom_ar" class="button _ar_save_custom_ar _changeAr">Save</span>
@ -203,43 +169,67 @@
</ul></small>
</div>
</div>
<!-- ZOOM STUFF -->
<span class="label experimental">Manual zooming and panning</span>
<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>
<!--
min, max and value need to be implemented in js as this slider
should use logarithmic scale
-->
<input id="_input_zoom_slider" class="w100"
type="range"
step="any"
/>
<div style="overflow: auto">
<div class="inline-block float-left medium-small x-pad-1em">
Zoom: <span id="_label_zoom_level">100</span>%
</div>
<div class="inline-block float-right medium-small">
<a id="_zoom_b_show_shortcuts" class="_zoom_show_shortcuts x-pad-1em">show shortcuts</a>
<a id="_zoom_b_hide_shortcuts" class="_zoom_hide_shortcuts hidden x-pad-1em">hide shortcuts</a>
<a class="_zoom_reset x-pad-1em">reset</a>
</div>
</div>
<!-- <div class="m-t-0-33em w100 display-block">
<input id="_input_zoom_site_allow_pan"
type="checkbox"
/>
Pan with mouse
</div> -->
<div id="_zoom_shortcuts" class="row hidden">
<small>Keyboard shortcuts:<ul>
<li>Z: zoom</li>
<li>U: unzoom</li>
<li>P: toggle pan</li>
<li>shift: hold to enable/prevent pan</li>
</ul></small>
</div>
</div>
<div id="stretch-settings" class="suboption hidden">
<p class="warning">
<b>Video stretching options are currently experimental.</b> If you find any bugs, please consider reporting the problem. See 'About ultrawidify' tab for details.
</p>
<span class="label">Default stretching mode<br><small>You may need to reload for this option to take effect. NOTE: Stretching is independent of crop mode. Crop gets applied before stretching.</small></span>
<!-- STRETCH STUFF -->
<span class="label experimental">Stretching mode</span>
<div class="button-row">
<a id="_stretch_global_none" class="button _stretch _ar_stretch_global _none w24">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 w24">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 w24">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 w24">Thin borders<br/><span id="_b_stretch_default_conditional_key" class="smallcaps small darker"></span></a>
</div>
<span class="label">Temporary stretching mode<br><small>Temporarily overrides default stretching mode.</small></span>
<div class="button-row">
<a class="button _stretch _ar_stretch_none w24">Never<br/><span id="_b_stretch_none_key" class="smallcaps small darker"></span></a>
<a class="button _stretch _ar_stretch_none w24">Normal<br/><span id="_b_stretch_none_key" class="smallcaps small darker"></span></a>
<a class="button _stretch _ar_stretch_basic w24">Basic<br/><span id="_b_stretch_basic_key" class="smallcaps small darker"></span></a>
<a class="button _stretch _ar_stretch_hybrid w24">Hybrid<br/><span id="_b_stretch_hybrid_key" class="smallcaps small darker"></span></a>
<a class="button _stretch _ar_stretch_conditional w24">Thin borders<br/><span id="_b_stretch_conditional_key" class="smallcaps small darker"></span></a>
</div>
<!-- VIDEO ALIGNMENT -->
<div class="row">
<span class="label">Video alignment:</span>
<div class="button-row">
<a id="_align_video_left" class="button _align _align_video_left">Left</a>
<a id="_align_video_center" class="button _align _align_video_center">Center</a>
<a id="_align_video_right" class="button _align _align_video_right">Right</a>
</div>
</div>
</div>
<div id="css-hacks-settings" class="suboption hidden">
<p>If zoomed in video doesn't align properly, try enabling or disabling certain CSS rules below:</p>
</div>
<div id="panel-about" class="suboption hidden">
<!-- ABOUTR -->
<div id="_menu_about" class="suboption hidden">
<div class="row">
<span class="label">Ultrawidify version:</span><br/> <span id="uw-version"></span>
</div>