Merge branch 'master' into stable
This commit is contained in:
commit
ce6a22d31b
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -16,6 +16,7 @@
|
||||
"resizer",
|
||||
"textbox",
|
||||
"videodata",
|
||||
"vuex",
|
||||
"youtube"
|
||||
],
|
||||
"cSpell.ignoreWords": [
|
||||
|
@ -13,7 +13,14 @@ QoL improvements for me:
|
||||
|
||||
* logging: allow to enable logging at will and export said logs to a file
|
||||
|
||||
### v4.4.5 (current)
|
||||
### v4.4.6 (current)
|
||||
|
||||
* Ensured that Vue part of the content script (logger UI) only loads when necessary in order to fix breakage on certain sites (#96).
|
||||
* Disabling (or enabling, if running in whitelist-only mode) specific sites used to not work (#91). This issue appears to have been fixed.
|
||||
* Default stretch mode for sites is now probably being observed, too (#94).
|
||||
* It's been almost a month and Chrome Web Store still hasn't finished the review of the 4.4.4.1 (and 4.4.4.2) revisions because when it comes to incompetence, it's hard to expect anything less from Google. I've did some proverbial yelling at the support in hopes that Chrome version will finally see an update (disclaimer: when I said yelling I really mean a polite request, because support staff doesn't deserve abuse because a different department is utter shite at doing their jobs).
|
||||
|
||||
### v4.4.5
|
||||
|
||||
* Extension no longer requires `allTabs` and `webNavigation` permissions
|
||||
* Some CSS on the debugger popup was not scoped, causing issues with some sites.
|
||||
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ultravidify",
|
||||
"version": "4.4.5",
|
||||
"version": "4.4.6",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ultravidify",
|
||||
"version": "4.4.5",
|
||||
"version": "4.4.6",
|
||||
"description": "Aspect ratio fixer for youtube and other sites, with automatic aspect ratio detection. Supports ultrawide and other ratios.",
|
||||
"author": "Tamius Han <tamius.han@gmail.com>",
|
||||
"scripts": {
|
||||
|
@ -156,7 +156,6 @@ class Settings {
|
||||
try {
|
||||
updateFn(this.active, this.getDefaultSettings());
|
||||
} catch (e) {
|
||||
console.log("!!!!", e)
|
||||
this.logger.log('error', 'settings', '[Settings::applySettingsPatches] Failed to execute update function. Keeping settings object as-is. Error:', e);
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import EdgeStatus from './edge-detect/enums/EdgeStatusEnum';
|
||||
import EdgeDetectPrimaryDirection from './edge-detect/enums/EdgeDetectPrimaryDirectionEnum';
|
||||
import EdgeDetectQuality from './edge-detect/enums/EdgeDetectQualityEnum';
|
||||
import GuardLine from './GuardLine';
|
||||
import DebugCanvas from './DebugCanvas';
|
||||
// import DebugCanvas from './DebugCanvas';
|
||||
import VideoAlignment from '../../../common/enums/video-alignment.enum';
|
||||
import AspectRatio from '../../../common/enums/aspect-ratio.enum';
|
||||
|
||||
|
@ -2,15 +2,13 @@ import Debug from '../../conf/Debug';
|
||||
import BrowserDetect from '../../conf/BrowserDetect';
|
||||
|
||||
class CommsClient {
|
||||
constructor(name, settings, logger) {
|
||||
constructor(name, logger, commands) {
|
||||
this.logger = logger;
|
||||
|
||||
if (BrowserDetect.firefox) {
|
||||
this.port = browser.runtime.connect({name: name});
|
||||
} else if (BrowserDetect.chrome) {
|
||||
this.port = chrome.runtime.connect({name: name});
|
||||
} else if (BrowserDetect.edge) {
|
||||
this.port = browser.runtime.connect({name: name})
|
||||
}
|
||||
|
||||
this.logger.onLogEnd(
|
||||
@ -24,46 +22,15 @@ class CommsClient {
|
||||
}
|
||||
);
|
||||
|
||||
var ths = this;
|
||||
this._listener = m => ths.processReceivedMessage(m);
|
||||
this._listener = m => this.processReceivedMessage(m);
|
||||
this.port.onMessage.addListener(this._listener);
|
||||
|
||||
this.settings = settings;
|
||||
this.pageInfo = undefined;
|
||||
this.commsId = (Math.random() * 20).toFixed(0);
|
||||
|
||||
this.commands = {
|
||||
'get-current-zoom': [() => this.pageInfo.requestCurrentZoom()],
|
||||
'set-ar': [(message) => this.pageInfo.setAr({type: message.arg, ratio: message.customArg}, message.playing)],
|
||||
'set-alignment': [(message) => {
|
||||
this.pageInfo.setVideoAlignment(message.arg, message.playing);
|
||||
this.pageInfo.restoreAr();
|
||||
}],
|
||||
'set-stretch': [(message) => this.pageInfo.setStretchMode(message.arg, message.playing, message.customArg)],
|
||||
'set-keyboard': [(message) => this.pageInfo.setKeyboardShortcutsEnabled(message.arg)],
|
||||
'autoar-start': [(message) => {
|
||||
if (message.enabled !== false) {
|
||||
this.pageInfo.initArDetection(message.playing);
|
||||
this.pageInfo.startArDetection(message.playing);
|
||||
} else {
|
||||
this.pageInfo.stopArDetection(message.playing);
|
||||
}
|
||||
}],
|
||||
'pause-processing': [(message) => this.pageInfo.pauseProcessing(message.playing)],
|
||||
'resume-processing': [(message) => this.pageInfo.resumeProcessing(message.autoArStatus, message.playing)],
|
||||
'set-zoom': [(message) => this.pageInfo.setZoom(message.arg, true, message.playing)],
|
||||
'change-zoom': [(message) => this.pageInfo.zoomStep(message.arg, message.playing)],
|
||||
'mark-player': [(message) => this.pageInfo.markPlayer(message.name, message.color)],
|
||||
'unmark-player': [() => this.pageInfo.unmarkPlayer()],
|
||||
'autoar-set-manual-tick': [(message) => this.pageInfo.setManualTick(message.arg)],
|
||||
'autoar-tick': [() => this.pageInfo.tick()],
|
||||
'set-ar-persistence': [() => this.pageInfo.setArPersistence(message.arg)],
|
||||
};
|
||||
this.commands = commands;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.pageInfo = null;
|
||||
this.settings = null;
|
||||
if (!BrowserDetect.edge) { // edge is a very special browser made by outright morons.
|
||||
this.port.onMessage.removeListener(this._listener);
|
||||
}
|
||||
@ -77,32 +44,9 @@ class CommsClient {
|
||||
}
|
||||
}
|
||||
|
||||
setPageInfo(pageInfo){
|
||||
|
||||
this.pageInfo = pageInfo;
|
||||
|
||||
this.logger.log('info', 'debug', `[CommsClient::setPageInfo] <${this.commsId}>`, "setting pageinfo");
|
||||
|
||||
var ths = this;
|
||||
this._listener = m => ths.processReceivedMessage(m);
|
||||
if (!BrowserDetect.edge) {
|
||||
this.port.onMessage.removeListener(this._listener);
|
||||
}
|
||||
this.port.onMessage.addListener(this._listener);
|
||||
|
||||
}
|
||||
|
||||
processReceivedMessage(message){
|
||||
this.logger.log('info', 'comms', `[CommsClient.js::processMessage] <${this.commsId}> Received message from background script!`, message);
|
||||
|
||||
if (!this.pageInfo || !this.settings.active) {
|
||||
this.logger.log('info', 'comms', `[CommsClient.js::processMessage] <${this.commsId}> this.pageInfo (or settings) not defined. Extension is probably disabled for this site.\npageInfo:`, this.pageInfo,
|
||||
"\nsettings.active:", this.settings.active,
|
||||
"\nnobj:", this
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.commands[message.cmd]) {
|
||||
for (const c of this.commands[message.cmd]) {
|
||||
c(message);
|
||||
@ -110,10 +54,6 @@ class CommsClient {
|
||||
}
|
||||
}
|
||||
|
||||
async sleep(n){
|
||||
return new Promise( (resolve, reject) => setTimeout(resolve, n) );
|
||||
}
|
||||
|
||||
async sendMessage_nonpersistent(message){
|
||||
message = JSON.parse(JSON.stringify(message)); // vue quirk. We should really use vue store instead
|
||||
|
||||
@ -165,13 +105,7 @@ class CommsClient {
|
||||
|
||||
registerVideo(){
|
||||
this.logger.log('info', 'comms', `[CommsClient::registerVideo] <${this.commsId}>`, "Registering video for current page.");
|
||||
if (this.pageInfo) {
|
||||
if (this.pageInfo.hasVideo()) {
|
||||
this.port.postMessage({cmd: "has-video"});
|
||||
}
|
||||
} else {
|
||||
// this.port.postMessage({cmd: "has-video"});
|
||||
}
|
||||
this.port.postMessage({cmd: "has-video"});
|
||||
}
|
||||
|
||||
sendPerformanceUpdate(message){
|
||||
@ -185,7 +119,7 @@ class CommsClient {
|
||||
|
||||
announceZoom(scale){
|
||||
this.port.postMessage({cmd: "announce-zoom", zoom: scale});
|
||||
this.registerVideo()
|
||||
this.registerVideo();
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,14 +9,12 @@ class CommsServer {
|
||||
this.ports = [];
|
||||
this.popupPort = null;
|
||||
|
||||
var ths = this;
|
||||
|
||||
if (BrowserDetect.firefox) {
|
||||
browser.runtime.onConnect.addListener(p => ths.onConnect(p));
|
||||
browser.runtime.onMessage.addListener((m, sender) => ths.processReceivedMessage_nonpersistent(m, sender));
|
||||
browser.runtime.onConnect.addListener(p => this.onConnect(p));
|
||||
browser.runtime.onMessage.addListener((m, sender) => this.processReceivedMessage_nonpersistent(m, sender));
|
||||
} else {
|
||||
chrome.runtime.onConnect.addListener(p => ths.onConnect(p));
|
||||
chrome.runtime.onMessage.addListener((m, sender, callback) => ths.processReceivedMessage_nonpersistent(m, sender, callback));
|
||||
chrome.runtime.onConnect.addListener(p => this.onConnect(p));
|
||||
chrome.runtime.onMessage.addListener((m, sender, callback) => this.processReceivedMessage_nonpersistent(m, sender, callback));
|
||||
}
|
||||
|
||||
// commands — functions that handle incoming messages
|
||||
@ -133,6 +131,14 @@ class CommsServer {
|
||||
}
|
||||
}
|
||||
|
||||
subscribe(command, callback) {
|
||||
if (!this.commands[command]) {
|
||||
this.commands[command] = [callback];
|
||||
} else {
|
||||
this.commands[command].push(callback);
|
||||
}
|
||||
}
|
||||
|
||||
async getCurrentTabHostname() {
|
||||
const activeTab = await this._getActiveTab();
|
||||
|
||||
@ -158,9 +164,11 @@ class CommsServer {
|
||||
}
|
||||
|
||||
sendToAll(message){
|
||||
for(var p of this.ports){
|
||||
for(var frame in p){
|
||||
p[frame].postMessage(message);
|
||||
for(const tab of this.ports){
|
||||
for(const frame in tab){
|
||||
for (const port in tab[frame]) {
|
||||
tab[frame][port].postMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -178,6 +186,12 @@ class CommsServer {
|
||||
}
|
||||
}
|
||||
|
||||
async sendToContentScripts(message, tab, frame) {
|
||||
for (const port in this.ports[tab][frame]) {
|
||||
this.ports[tab][frame][port].postMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
async sendToFrame(message, tab, frame) {
|
||||
this.logger.log('info', 'comms', `%c[CommsServer::sendToFrame] attempting to send message to tab ${tab}, frame ${frame}`, "background: #dda; color: #11D", message);
|
||||
|
||||
@ -196,7 +210,7 @@ class CommsServer {
|
||||
this.logger.log('info', 'comms', `%c[CommsServer::sendToFrame] attempting to send message to tab ${tab}, frame ${frame}`, "background: #dda; color: #11D", message);
|
||||
|
||||
try {
|
||||
this.ports[tab][frame].postMessage(message);
|
||||
this.sendToContentScripts(message, tab, frame);
|
||||
} catch (e) {
|
||||
this.logger.log('error', 'comms', `%c[CommsServer::sendToFrame] Sending message failed. Reason:`, "background: #dda; color: #11D", e);
|
||||
}
|
||||
@ -205,73 +219,85 @@ class CommsServer {
|
||||
async sendToActive(message) {
|
||||
this.logger.log('info', 'comms', "%c[CommsServer::sendToActive] trying to send a message to active tab. Message:", "background: #dda; color: #11D", message);
|
||||
|
||||
var tabs = await this._getActiveTab();
|
||||
const tabs = await this._getActiveTab();
|
||||
|
||||
this.logger.log('info', 'comms', "[CommsServer::_sendToActive] currently active tab(s)?", tabs);
|
||||
for (var key in this.ports[tabs[0].id]) {
|
||||
this.logger.log('info', 'comms', "key?", key, this.ports[tabs[0].id]);
|
||||
for (const frame in this.ports[tabs[0].id]) {
|
||||
this.logger.log('info', 'comms', "key?", frame, this.ports[tabs[0].id]);
|
||||
}
|
||||
|
||||
for (var key in this.ports[tabs[0].id]) {
|
||||
this.ports[tabs[0].id][key].postMessage(message);
|
||||
for (const frame in this.ports[tabs[0].id]) {
|
||||
this.sendToContentScripts(message, tabs[0].id, frame);
|
||||
}
|
||||
}
|
||||
|
||||
onConnect(port){
|
||||
var ths = this;
|
||||
|
||||
// poseben primer | special case
|
||||
if (port.name === 'popup-port') {
|
||||
this.popupPort = port;
|
||||
this.popupPort.onMessage.addListener( (m,p) => ths.processReceivedMessage(m,p));
|
||||
this.popupPort.onMessage.addListener( (m,p) => this.processReceivedMessage(m,p));
|
||||
return;
|
||||
}
|
||||
|
||||
var tabId = port.sender.tab.id;
|
||||
var frameId = port.sender.frameId;
|
||||
if(! this.ports[tabId]){
|
||||
if (! this.ports[tabId]){
|
||||
this.ports[tabId] = {};
|
||||
}
|
||||
this.ports[tabId][frameId] = port;
|
||||
this.ports[tabId][frameId].onMessage.addListener( (m,p) => ths.processReceivedMessage(m, p));
|
||||
this.ports[tabId][frameId].onDisconnect.addListener( (p) => {
|
||||
delete ths.ports[p.sender.tab.id][p.sender.frameId];
|
||||
if(Object.keys(ths.ports[p.sender.tab.id]).length === 0){
|
||||
ths.ports[tabId] = undefined;
|
||||
if (! this.ports[tabId][frameId]) {
|
||||
this.ports[tabId][frameId] = {};
|
||||
}
|
||||
this.ports[tabId][frameId][port.name] = port;
|
||||
this.ports[tabId][frameId][port.name].onMessage.addListener( (m,p) => this.processReceivedMessage(m, p));
|
||||
|
||||
this.ports[tabId][frameId][port.name].onDisconnect.addListener( (p) => {
|
||||
try {
|
||||
delete this.ports[p.sender.tab.id][p.sender.frameId][port.name];
|
||||
} catch (e) {
|
||||
// no biggie if the thing above doesn't exist.
|
||||
}
|
||||
if (Object.keys(this.ports[tabId][frameId].length === 0)) {
|
||||
delete this.ports[tabId][frameId];
|
||||
if(Object.keys(this.ports[p.sender.tab.id]).length === 0) {
|
||||
delete this.ports[tabId];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
execCmd(message, portOrSender, sendResponse) {
|
||||
async execCmd(message, portOrSender, sendResponse) {
|
||||
this.logger.log(
|
||||
'info', 'comms', '[CommsServer.js::execCmd] Received message', message,
|
||||
". Port/sender:", portOrSender, "sendResponse:", sendResponse, "\nThere is ", this.commands[message.cmd]?.length ?? 0,
|
||||
" command(s) for action", message.cmd
|
||||
);
|
||||
for (const c of this.commands[message.cmd]) {
|
||||
c(message, portOrSender, sendResponse);
|
||||
if (this.commands[message.cmd]) {
|
||||
for (const c of this.commands[message.cmd]) {
|
||||
try {
|
||||
await c(message, portOrSender, sendResponse);
|
||||
} catch (e) {
|
||||
this.logger.log('error', 'debug', "[CommsServer.js::execCmd] failed to execute command.", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleMessage(message, portOrSender, sendResponse) {
|
||||
async handleMessage(message, portOrSender, sendResponse) {
|
||||
await this.execCmd(message, portOrSender, sendResponse);
|
||||
|
||||
if (message.forwardToContentScript) {
|
||||
this.logger.log('info', 'comms', "[CommsServer.js::processReceivedMessage] Message has 'forward to content script' flag set. Forwarding message as is. Message:", message);
|
||||
this.sendToFrame(message, message.targetTab, message.targetFrame);
|
||||
return;
|
||||
}
|
||||
if (message.forwardToAll) {
|
||||
this.logger.log('info', 'comms', "[CommsServer.js::processReceivedMessage] Message has 'forward to all' flag set. Forwarding message as is. Message:", message);
|
||||
this.sendToAll(message);
|
||||
return;
|
||||
}
|
||||
if (message.forwardToActive) {
|
||||
this.logger.log('info', 'comms', "[CommsServer.js::processReceivedMessage] Message has 'forward to active' flag set. Forwarding message as is. Message:", message);
|
||||
this.sendToActive(message);
|
||||
return;
|
||||
}
|
||||
|
||||
this.execCmd(message, portOrSender, sendResponse);
|
||||
}
|
||||
|
||||
async processReceivedMessage(message, port){
|
||||
|
@ -40,7 +40,7 @@ class PageInfo {
|
||||
}
|
||||
|
||||
// try getting default crop immediately.
|
||||
const cropModePersistence = this.settings.getDefaultCropPersistenceMode(window.location.host);
|
||||
// const cropModePersistence = this.settings.getDefaultCropPersistenceMode(window.location.host);
|
||||
|
||||
// try {
|
||||
// if (cropModePersistence === CropModePersistence.Forever) {
|
||||
|
@ -4,6 +4,16 @@ import CommsServer from './lib/comms/CommsServer';
|
||||
import Settings from './lib/Settings';
|
||||
import Logger from './lib/Logger';
|
||||
|
||||
import { sleep } from '../common/js/utils';
|
||||
|
||||
// we need vue in bg script, so we can get vuex.
|
||||
// and we need vuex so popup will be initialized
|
||||
// after the first click without resorting to ugly,
|
||||
// dirty hacks
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import VuexWebExtensions from 'vuex-webextensions';
|
||||
|
||||
var BgVars = {
|
||||
arIsActive: true,
|
||||
hasVideos: false,
|
||||
@ -27,6 +37,8 @@ class UWServer {
|
||||
'siteSettings': undefined,
|
||||
'videoSettings': undefined,
|
||||
}
|
||||
|
||||
this.uiLoggerInitialized = false;
|
||||
}
|
||||
|
||||
async setup() {
|
||||
@ -49,12 +61,15 @@ class UWServer {
|
||||
this.settings = new Settings({logger: this.logger});
|
||||
await this.settings.init();
|
||||
this.comms = new CommsServer(this);
|
||||
this.comms.subscribe('show-logger', async () => await this.initUiAndShowLogger());
|
||||
this.comms.subscribe('init-vue', async () => await this.initUi());
|
||||
this.comms.subscribe('uwui-vue-initialized', () => this.uiLoggerInitialized = true);
|
||||
|
||||
|
||||
var ths = this;
|
||||
if(BrowserDetect.firefox) {
|
||||
browser.tabs.onActivated.addListener(function(m) {ths.onTabSwitched(m)});
|
||||
browser.tabs.onActivated.addListener(function(m) {this.onTabSwitched(m)});
|
||||
} else if (BrowserDetect.chrome) {
|
||||
chrome.tabs.onActivated.addListener(function(m) {ths.onTabSwitched(m)});
|
||||
chrome.tabs.onActivated.addListener(function(m) {this.onTabSwitched(m)});
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,6 +113,10 @@ class UWServer {
|
||||
extractHostname(url){
|
||||
var hostname;
|
||||
|
||||
if (!url) {
|
||||
return "<no url>";
|
||||
}
|
||||
|
||||
// extract hostname
|
||||
if (url.indexOf("://") > -1) { //find & remove protocol (http, ftp, etc.) and get hostname
|
||||
hostname = url.split('/')[2];
|
||||
@ -198,6 +217,56 @@ class UWServer {
|
||||
this.selectedSubitem[menu] = subitem;
|
||||
}
|
||||
|
||||
async initUi() {
|
||||
try {
|
||||
if (BrowserDetect.firefox) {
|
||||
await browser.tabs.executeScript({
|
||||
file: '/ext/uw-ui.js',
|
||||
allFrames: true,
|
||||
});
|
||||
} else if (BrowserDetect.chrome) {
|
||||
await new Promise( resolve =>
|
||||
chrome.tabs.executeScript({
|
||||
file: '/ext/uw-ui.js',
|
||||
allFrames: true,
|
||||
}, () => resolve())
|
||||
);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
this.logger.log('ERROR', 'uwbg', 'UI initialization failed. Reason:', e);
|
||||
}
|
||||
}
|
||||
|
||||
async initUiAndShowLogger() {
|
||||
// this implementation is less than optimal and very hacky, but it should work
|
||||
// just fine for our use case.
|
||||
this.uiLoggerInitialized = false;
|
||||
|
||||
await this.initUi();
|
||||
|
||||
await new Promise( async (resolve, reject) => {
|
||||
// if content script doesn't give us a response within 5 seconds, something is
|
||||
// obviously wrong and we stop waiting,
|
||||
|
||||
// oh and btw, resolve/reject do not break the loops, so we need to do that
|
||||
// ourselves:
|
||||
// https://stackoverflow.com/questions/55207256/will-resolve-in-promise-loop-break-loop-iteration
|
||||
let isRejected = false;
|
||||
setTimeout( async () => {isRejected = true; reject()}, 5000);
|
||||
|
||||
// check whether UI has been initiated on the FE. If it was, we resolve the
|
||||
// promise and off we go
|
||||
while (!isRejected) {
|
||||
if (this.uiLoggerInitialized) {
|
||||
resolve();
|
||||
return; // remember the bit about resolve() not breaking the loop?
|
||||
}
|
||||
await sleep(100);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async getCurrentTab() {
|
||||
if (BrowserDetect.firefox) {
|
||||
return (await browser.tabs.query({active: true, currentWindow: true}))[0];
|
||||
@ -212,8 +281,6 @@ class UWServer {
|
||||
|
||||
const ctab = await this.getCurrentTab();
|
||||
|
||||
console.log('Current tab:', ctab);
|
||||
|
||||
if (!ctab || !ctab.id) {
|
||||
return {
|
||||
host: 'INVALID SITE',
|
||||
|
233
src/ext/uw-ui.js
Normal file
233
src/ext/uw-ui.js
Normal file
@ -0,0 +1,233 @@
|
||||
// vue dependency imports
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import VuexWebExtensions from 'vuex-webextensions';
|
||||
import LoggerUi from '../csui/LoggerUi';
|
||||
|
||||
// extension classes
|
||||
import Logger from './lib/Logger';
|
||||
import Settings from './lib/Settings';
|
||||
import CommsClient from './lib/comms/CommsClient';
|
||||
import Comms from './lib/comms/Comms';
|
||||
|
||||
class UwUi {
|
||||
|
||||
constructor() {
|
||||
this.vueInitiated = false;
|
||||
this.loggerUiInitiated = false;
|
||||
this.playerUiInitiated = false;
|
||||
|
||||
this.vuexStore = null;
|
||||
|
||||
this.commsHandlers = {
|
||||
'show-logger': [() => this.showLogger()],
|
||||
'hide-logger': [() => this.hideLogger()],
|
||||
}
|
||||
}
|
||||
|
||||
async init() {
|
||||
// IMPORTANT NOTICE — we do not check for whether extension is enabled or not,
|
||||
// since this script only gets executed either:
|
||||
// * as a direct result of user action (logger UI)
|
||||
// * if video/player is detected (which can only happen if extension is enabled
|
||||
// for that particular site)
|
||||
|
||||
// NOTE: we need to setup logger and comms _before_ initializing vue (unless we're starting)
|
||||
// because logger settings say we should
|
||||
|
||||
// setup logger
|
||||
try {
|
||||
if (!this.logger) {
|
||||
const loggingOptions = {
|
||||
isContentScript: true,
|
||||
allowLogging: true,
|
||||
useConfFromStorage: true,
|
||||
fileOptions: {
|
||||
enabled: false
|
||||
},
|
||||
consoleOptions: {
|
||||
"enabled": true,
|
||||
"debug": true,
|
||||
"init": true,
|
||||
"settings": true,
|
||||
"keyboard": true,
|
||||
"mousemove": false,
|
||||
"actionHandler": true,
|
||||
"comms": true,
|
||||
"playerDetect": true,
|
||||
"resizer": true,
|
||||
"scaler": true,
|
||||
"stretcher": true,
|
||||
// "videoRescan": true,
|
||||
// "playerRescan": true,
|
||||
"arDetect": true,
|
||||
"arDetect_verbose": true
|
||||
},
|
||||
allowBlacklistedOrigins: {
|
||||
'periodicPlayerCheck': false,
|
||||
'periodicVideoStyleChangeCheck': false,
|
||||
'handleMouseMove': false
|
||||
}
|
||||
};
|
||||
this.logger = new Logger();
|
||||
await this.logger.init(loggingOptions);
|
||||
|
||||
if (this.logger.isLoggingAllowed()) {
|
||||
console.info("[uw::init] Logging is allowed! Initalizing vue and UI!");
|
||||
this.initVue();
|
||||
this.initLoggerUi();
|
||||
this.logger.setVuexStore(this.vuexStore);
|
||||
}
|
||||
|
||||
// show popup if logging to file is enabled
|
||||
if (this.logger.isLoggingToFile()) {
|
||||
console.info('[uw::init] Logging to file is enabled. Will show popup!');
|
||||
try {
|
||||
this.vuexStore.dispatch('uw-show-logger');
|
||||
} catch (e) {
|
||||
console.error('[uw::init] Failed to open popup!', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("logger initialization failed. Error:", e);
|
||||
}
|
||||
|
||||
// we also need to know settings (there's UI-related things in the settings — or rather, there will be UI-related things
|
||||
// in settings once in-player UI is implemented
|
||||
// If comms exist, we need to destroy it
|
||||
if (this.comms) {
|
||||
this.comms.destroy();
|
||||
}
|
||||
if (!this.settings) {
|
||||
this.settings = new Settings({
|
||||
onSettingsChanged: () => this.reloadSettings(),
|
||||
logger: this.logger
|
||||
});
|
||||
await this.settings.init();
|
||||
}
|
||||
|
||||
this.comms = new CommsClient('content-ui-port', this.logger, this.commsHandlers);
|
||||
|
||||
// initialize vuejs, but only once (check handled in initVue())
|
||||
// we need to initialize this _after_ initializing comms.
|
||||
this.initVue();
|
||||
}
|
||||
|
||||
initVue() {
|
||||
// never init twice
|
||||
if (this.vueInitiated) {
|
||||
// let background script know it can proceed with sending 'show-logger' command.
|
||||
Comms.sendMessage({cmd: 'uwui-vue-initialized'});
|
||||
return;
|
||||
}
|
||||
|
||||
Vue.prototype.$browser = global.browser;
|
||||
Vue.use(Vuex);
|
||||
this.vuexStore = new Vuex.Store({
|
||||
plugins: [VuexWebExtensions({
|
||||
persistentStates: [
|
||||
'uwLog',
|
||||
'showLogger',
|
||||
],
|
||||
})],
|
||||
state: {
|
||||
uwLog: '',
|
||||
showLogger: false,
|
||||
},
|
||||
mutations: {
|
||||
'uw-set-log'(state, payload) {
|
||||
state['uwLog'] = payload;
|
||||
},
|
||||
'uw-show-logger'(state) {
|
||||
state['showLogger'] = true;
|
||||
},
|
||||
'uw-hide-logger'(state) {
|
||||
state['showLogger'] = false;
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
'uw-set-log' ({commit}, payload) {
|
||||
commit('uw-set-log', payload);
|
||||
},
|
||||
'uw-show-logger'({commit}) {
|
||||
commit('uw-show-logger');
|
||||
},
|
||||
'uw-hide-logger'({commit}) {
|
||||
commit('uw-hide-logger');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// make sure we don't init twice
|
||||
this.vueInitiated = true;
|
||||
|
||||
// let background script know it can proceed with sending 'show-logger' command.
|
||||
Comms.sendMessage({cmd: 'uwui-vue-initialized'});
|
||||
}
|
||||
|
||||
async initLoggerUi() {
|
||||
const random = Math.round(Math.random() * 69420);
|
||||
const uwid = `uw-ui-root-${random}`;
|
||||
|
||||
const rootDiv = document.createElement('div');
|
||||
rootDiv.setAttribute("style", "position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; z-index: 999999; background-color: #ff0000;");
|
||||
rootDiv.setAttribute("id", uwid);
|
||||
|
||||
document.body.appendChild(rootDiv);
|
||||
|
||||
try {
|
||||
new Vue({
|
||||
el: `#${uwid}`,
|
||||
components: {
|
||||
LoggerUi: LoggerUi
|
||||
},
|
||||
store: this.vuexStore,
|
||||
render(h) {
|
||||
return h('logger-ui');
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("Error while initiating vue:", e)
|
||||
}
|
||||
|
||||
this.loggerUiInitiated = true;
|
||||
}
|
||||
|
||||
async showLogger() {
|
||||
if (!this.loggerUiInitiated) {
|
||||
await this.initLoggerUi();
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
this.vuexStore.dispatch('uw-show-logger');
|
||||
} catch (e) {
|
||||
console.error('Failed to dispatch vuex store', e)
|
||||
}
|
||||
}
|
||||
hideLogger() {
|
||||
if (this.vueInitiated && this.vuexStore !== undefined) {
|
||||
this.vuexStore.dispatch('uw-hide-logger');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// leave a mark, so this script won't get executed more than once on a given page
|
||||
const markerId = 'ultrawidify-marker-5aeaf521-7afe-447f-9a17-3428f62d0970';
|
||||
|
||||
// if this script has already been executed, don't execute it again.
|
||||
if (! document.getElementById(markerId)) {
|
||||
const markerDiv = document.createElement('div');
|
||||
markerDiv.setAttribute("style", "display: none");
|
||||
markerDiv.setAttribute('id', markerId);
|
||||
|
||||
document.body.appendChild(markerDiv);
|
||||
|
||||
const uwui = new UwUi();
|
||||
uwui.init();
|
||||
} else {
|
||||
// let background script know it can proceed with sending 'show-logger' command.
|
||||
Comms.sendMessage({cmd: 'uwui-vue-initialized'});
|
||||
}
|
||||
|
134
src/ext/uw.js
134
src/ext/uw.js
@ -7,13 +7,6 @@ import CommsClient from './lib/comms/CommsClient';
|
||||
import PageInfo from './lib/video-data/PageInfo';
|
||||
import Logger from './lib/Logger';
|
||||
|
||||
// vue dependency imports
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import VuexWebExtensions from 'vuex-webextensions';
|
||||
|
||||
global.browser = require('webextension-polyfill');
|
||||
import LoggerUi from '../csui/LoggerUi';
|
||||
|
||||
if(Debug.debug){
|
||||
console.log("\n\n\n\n\n\n ——— Sᴛλʀᴛɪɴɢ Uʟᴛʀᴀᴡɪᴅɪꜰʏ ———\n << ʟᴏᴀᴅɪɴɢ ᴍᴀɪɴ ꜰɪʟᴇ >>\n\n\n\n");
|
||||
@ -40,9 +33,35 @@ class UW {
|
||||
this.settings = undefined;
|
||||
this.actionHandler = undefined;
|
||||
this.logger = undefined;
|
||||
this.vuexStore = {};
|
||||
this.uiInitiated = false;
|
||||
this.vueInitiated = false;
|
||||
|
||||
this.commsHandlers = {
|
||||
'get-current-zoom': [() => this.pageInfo.requestCurrentZoom()],
|
||||
'set-ar': [(message) => this.pageInfo.setAr({type: message.arg, ratio: message.customArg}, message.playing)],
|
||||
'set-alignment': [(message) => {
|
||||
this.pageInfo.setVideoAlignment(message.arg, message.playing);
|
||||
this.pageInfo.restoreAr();
|
||||
}],
|
||||
'set-stretch': [(message) => this.pageInfo.setStretchMode(message.arg, message.playing, message.customArg)],
|
||||
'set-keyboard': [(message) => this.pageInfo.setKeyboardShortcutsEnabled(message.arg)],
|
||||
'autoar-start': [(message) => {
|
||||
if (message.enabled !== false) {
|
||||
this.pageInfo.initArDetection(message.playing);
|
||||
this.pageInfo.startArDetection(message.playing);
|
||||
} else {
|
||||
this.pageInfo.stopArDetection(message.playing);
|
||||
}
|
||||
}],
|
||||
'pause-processing': [(message) => this.pageInfo.pauseProcessing(message.playing)],
|
||||
'resume-processing': [(message) => this.pageInfo.resumeProcessing(message.autoArStatus, message.playing)],
|
||||
'set-zoom': [(message) => this.pageInfo.setZoom(message.arg, true, message.playing)],
|
||||
'change-zoom': [(message) => this.pageInfo.zoomStep(message.arg, message.playing)],
|
||||
'mark-player': [(message) => this.pageInfo.markPlayer(message.name, message.color)],
|
||||
'unmark-player': [() => this.pageInfo.unmarkPlayer()],
|
||||
'autoar-set-manual-tick': [(message) => this.pageInfo.setManualTick(message.arg)],
|
||||
'autoar-tick': [() => this.pageInfo.tick()],
|
||||
'set-ar-persistence': [() => this.pageInfo.setArPersistence(message.arg)],
|
||||
}
|
||||
}
|
||||
|
||||
reloadSettings() {
|
||||
@ -94,9 +113,6 @@ class UW {
|
||||
|
||||
if (this.logger.isLoggingAllowed()) {
|
||||
console.info("[uw::init] Logging is allowed! Initalizing vue and UI!");
|
||||
this.initVue();
|
||||
this.initUi();
|
||||
this.logger.setVuexStore(this.vuexStore);
|
||||
}
|
||||
|
||||
// show popup if logging to file is enabled
|
||||
@ -114,17 +130,10 @@ class UW {
|
||||
}
|
||||
|
||||
// init() is re-run any time settings change
|
||||
if (this.pageInfo) {
|
||||
// if this executes, logger must have been initiated at some point before this point
|
||||
this.logger.log('info', 'debug', "[uw::init] Destroying existing pageInfo", this.pageInfo);
|
||||
this.pageInfo.destroy();
|
||||
}
|
||||
if (this.comms) {
|
||||
this.comms.destroy();
|
||||
}
|
||||
|
||||
if (!this.settings) {
|
||||
var ths = this;
|
||||
this.settings = new Settings({
|
||||
onSettingsChanged: () => this.reloadSettings(),
|
||||
logger: this.logger
|
||||
@ -132,12 +141,8 @@ class UW {
|
||||
await this.settings.init();
|
||||
}
|
||||
|
||||
this.comms = new CommsClient('content-client-port', this.settings, this.logger);
|
||||
this.comms = new CommsClient('content-main-port', this.logger, this.commsHandlers);
|
||||
|
||||
// add showPopup, hidePopup listener to comms
|
||||
this.comms.subscribe('show-logger', () => this.showLogger());
|
||||
this.comms.subscribe('hide-logger', () => this.hideLogger());
|
||||
|
||||
// če smo razširitev onemogočili v nastavitvah, ne naredimo ničesar
|
||||
// If extension is soft-disabled, don't do shit
|
||||
|
||||
@ -157,7 +162,6 @@ class UW {
|
||||
try {
|
||||
this.pageInfo = new PageInfo(this.comms, this.settings, this.logger, extensionMode, isSiteDisabled);
|
||||
this.logger.log('info', 'debug', "[uw.js::setup] pageInfo initialized.");
|
||||
this.comms.setPageInfo(this.pageInfo);
|
||||
|
||||
this.logger.log('info', 'debug', "[uw.js::setup] will try to initate ActionHandler.");
|
||||
|
||||
@ -174,85 +178,7 @@ class UW {
|
||||
}
|
||||
}
|
||||
|
||||
initVue() {
|
||||
Vue.prototype.$browser = global.browser;
|
||||
Vue.use(Vuex);
|
||||
this.vuexStore = new Vuex.Store({
|
||||
plugins: [VuexWebExtensions({
|
||||
persistentStates: [
|
||||
'uwLog',
|
||||
'showLogger',
|
||||
],
|
||||
})],
|
||||
state: {
|
||||
uwLog: '',
|
||||
showLogger: false,
|
||||
},
|
||||
mutations: {
|
||||
'uw-set-log'(state, payload) {
|
||||
state['uwLog'] = payload;
|
||||
},
|
||||
'uw-show-logger'(state) {
|
||||
state['showLogger'] = true;
|
||||
},
|
||||
'uw-hide-logger'(state) {
|
||||
state['showLogger'] = false;
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
'uw-set-log' ({commit}, payload) {
|
||||
commit('uw-set-log', payload);
|
||||
},
|
||||
'uw-show-logger'({commit}) {
|
||||
commit('uw-show-logger');
|
||||
},
|
||||
'uw-hide-logger'({commit}) {
|
||||
commit('uw-hide-logger');
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
initUi() {
|
||||
console.log("CREATING UI");
|
||||
const random = Math.round(Math.random() * 69420);
|
||||
const uwid = `uw-ui-root-${random}`;
|
||||
|
||||
const rootDiv = document.createElement('div');
|
||||
rootDiv.setAttribute("style", "position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; z-index: 999999; background-color: #ff0000;");
|
||||
rootDiv.setAttribute("id", uwid);
|
||||
|
||||
document.body.appendChild(rootDiv);
|
||||
|
||||
new Vue({
|
||||
el: `#${uwid}`,
|
||||
components: {
|
||||
LoggerUi
|
||||
},
|
||||
store: this.vuexStore,
|
||||
render(h) {
|
||||
return h('logger-ui');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
showLogger() {
|
||||
if (! this.vueInitiated) {
|
||||
this.initVue();
|
||||
}
|
||||
if (!this.uiInitiated) {
|
||||
this.initUi();
|
||||
}
|
||||
|
||||
this.vuexStore.dispatch('uw-show-logger');
|
||||
}
|
||||
hideLogger() {
|
||||
// if either of these two is false, then we know that UI doesn't exist
|
||||
// since UI doesn't exist, we don't need to dispatch uw-hide-logger
|
||||
if (this.vueInitiated && this.uiInitiated) {
|
||||
this.vuexStore.dispatch('uw-hide-logger');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var main = new UW();
|
||||
|
@ -2,7 +2,7 @@
|
||||
"manifest_version": 2,
|
||||
"name": "Ultrawidify",
|
||||
"description": "Removes black bars on ultrawide videos and offers advanced options to fix aspect ratio.",
|
||||
"version": "4.4.5",
|
||||
"version": "4.4.6",
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "{cf02b1a7-a01a-4e37-a609-516a283f1ed3}"
|
||||
|
@ -157,7 +157,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
async openOptionsPage() {
|
||||
browser.runtime.openOptionsPage();
|
||||
(browser ?? chrome).runtime.openOptionsPage();
|
||||
},
|
||||
execAction(action) {
|
||||
this.exec.exec(action, 'page', this.frame);
|
||||
|
@ -2,12 +2,31 @@
|
||||
<div>
|
||||
<h2>What's new</h2>
|
||||
<p>Full changelog for older versions <a href="https://github.com/tamius-han/ultrawidify/blob/master/CHANGELOG.md">is available here</a>.</p>
|
||||
<p class="label">4.4.5</p>
|
||||
<p class="label">4.4.6</p>
|
||||
<ul>
|
||||
<li>Extension no longer requires <code>allTabs</code> and <code>webNavigation</code> permissions</li>
|
||||
<li>Some CSS on the logger popup was not scoped, causing display issues with some sites (<a href="https://github.com/tamius-han/ultrawidify/issues/92">#92</a>)</li>
|
||||
<li>Fix some additional issues with video alignment when changing videos on autoplay</li>
|
||||
<li>Ensured that Vue part of the content script (logger UI) only loads when necessary in order to fix breakage on certain sites (<a href="https://github.com/tamius-han/ultrawidify/issues/96">#96</a>).</li>
|
||||
<li>Disabling (or enabling, if running in whitelist-only mode) specific sites used to not work (<a href="https://github.com/tamius-han/ultrawidify/issues/91">#91</a>). This issue appears to have been fixed.</li>
|
||||
<li>Default stretch mode for sites is now probably being observed, too (<a href="https://github.com/tamius-han/ultrawidify/issues/94">#94</a>).
|
||||
</ul>
|
||||
|
||||
<template v-if="BrowserDetect.chrome">
|
||||
<p>Due to factors beyond my control, Chrome version of this extension has missed the last three patches.</p>
|
||||
|
||||
<ul>
|
||||
<li><b>4.4.5</b>
|
||||
<ul>
|
||||
<li>Extension no longer requires <code>allTabs</code> and <code>webNavigation</code> permissions</li>
|
||||
<li>Some CSS on the logger popup was not scoped, causing display issues with some sites (<a href="https://github.com/tamius-han/ultrawidify/issues/92">#92</a>)</li>
|
||||
<li>Fix some additional issues with video alignment when changing videos on autoplay</li>
|
||||
</ul></li>
|
||||
<li><b>4.4.4<small>.1, .2</small></b>
|
||||
<ul>
|
||||
<li><b>[4.4.4.1]</b> There were multiple reports about popup being broken. This issue should be resolved.</li>
|
||||
<li><b>[4.4.4.1]</b> Setting global/site defaults should no longer require page reloads.</li>
|
||||
<li><b>[4.4.4.2]</b> Fix problem with video being offset while switching between full screen and non-fullscreen non-theater mode on Youtube</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
@ -12,6 +12,7 @@ const config = {
|
||||
context: __dirname + '/src',
|
||||
entry: {
|
||||
'ext/uw': './ext/uw.js',
|
||||
'ext/uw-ui': './ext/uw-ui.js',
|
||||
'ext/uw-bg': './ext/uw-bg.js',
|
||||
'popup/popup': './popup/popup.js',
|
||||
'options/options': './options/options.js',
|
||||
|
Loading…
Reference in New Issue
Block a user