Compare commits
5 Commits
42cde0a2b3
...
d322c0909a
Author | SHA1 | Date | |
---|---|---|---|
d322c0909a | |||
0bfe84d73d | |||
244e8227e7 | |||
5da8073235 | |||
5479b7ee95 |
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -16,7 +16,6 @@
|
|||||||
"decycle",
|
"decycle",
|
||||||
"dinked",
|
"dinked",
|
||||||
"dinks",
|
"dinks",
|
||||||
"Discardable",
|
|
||||||
"disneyplus",
|
"disneyplus",
|
||||||
"endregion",
|
"endregion",
|
||||||
"equalish",
|
"equalish",
|
||||||
|
43
package-lock.json
generated
43
package-lock.json
generated
@ -3243,7 +3243,8 @@
|
|||||||
"asynckit": {
|
"asynckit": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"at-least-node": {
|
"at-least-node": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@ -3374,28 +3375,6 @@
|
|||||||
"integrity": "sha512-3AungXC4I8kKsS9PuS4JH2nc+0bVY/mjgrephHTIi8fpEeGsTHBUJeosp0Wc1myYMElmD0B3Oc4XL/HVJ4PV2g==",
|
"integrity": "sha512-3AungXC4I8kKsS9PuS4JH2nc+0bVY/mjgrephHTIi8fpEeGsTHBUJeosp0Wc1myYMElmD0B3Oc4XL/HVJ4PV2g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"axios": {
|
|
||||||
"version": "1.7.9",
|
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz",
|
|
||||||
"integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
|
|
||||||
"requires": {
|
|
||||||
"follow-redirects": "^1.15.6",
|
|
||||||
"form-data": "^4.0.0",
|
|
||||||
"proxy-from-env": "^1.1.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"form-data": {
|
|
||||||
"version": "4.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
|
|
||||||
"integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
|
|
||||||
"requires": {
|
|
||||||
"asynckit": "^0.4.0",
|
|
||||||
"combined-stream": "^1.0.8",
|
|
||||||
"mime-types": "^2.1.12"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"babel-code-frame": {
|
"babel-code-frame": {
|
||||||
"version": "6.26.0",
|
"version": "6.26.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
|
||||||
@ -4870,6 +4849,7 @@
|
|||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"delayed-stream": "~1.0.0"
|
"delayed-stream": "~1.0.0"
|
||||||
}
|
}
|
||||||
@ -5977,7 +5957,8 @@
|
|||||||
"delayed-stream": {
|
"delayed-stream": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"delegates": {
|
"delegates": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@ -7016,11 +6997,6 @@
|
|||||||
"readable-stream": "^2.3.6"
|
"readable-stream": "^2.3.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"follow-redirects": {
|
|
||||||
"version": "1.15.9",
|
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
|
||||||
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="
|
|
||||||
},
|
|
||||||
"for-each": {
|
"for-each": {
|
||||||
"version": "0.3.3",
|
"version": "0.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
|
||||||
@ -9399,12 +9375,14 @@
|
|||||||
"mime-db": {
|
"mime-db": {
|
||||||
"version": "1.52.0",
|
"version": "1.52.0",
|
||||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"mime-types": {
|
"mime-types": {
|
||||||
"version": "2.1.35",
|
"version": "2.1.35",
|
||||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"mime-db": "1.52.0"
|
"mime-db": "1.52.0"
|
||||||
}
|
}
|
||||||
@ -12832,11 +12810,6 @@
|
|||||||
"ipaddr.js": "1.9.1"
|
"ipaddr.js": "1.9.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"proxy-from-env": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
|
||||||
},
|
|
||||||
"prr": {
|
"prr": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
"@mdi/font": "^6.5.95",
|
"@mdi/font": "^6.5.95",
|
||||||
"@mdi/js": "^6.4.95",
|
"@mdi/js": "^6.4.95",
|
||||||
"@types/resize-observer-browser": "^0.1.6",
|
"@types/resize-observer-browser": "^0.1.6",
|
||||||
"axios": "^1.7.9",
|
|
||||||
"concurrently": "^5.3.0",
|
"concurrently": "^5.3.0",
|
||||||
"fs-extra": "^7.0.1",
|
"fs-extra": "^7.0.1",
|
||||||
"gl-matrix": "^3.4.3",
|
"gl-matrix": "^3.4.3",
|
||||||
|
@ -164,7 +164,20 @@ interface SettingsInterface {
|
|||||||
arDetect: AardSettings,
|
arDetect: AardSettings,
|
||||||
|
|
||||||
ui: {
|
ui: {
|
||||||
inPlayer: InPlayerUISettingsInterface
|
inPlayer: {
|
||||||
|
enabled: boolean,
|
||||||
|
enabledFullscreenOnly: boolean,
|
||||||
|
popupAlignment: 'left' | 'right',
|
||||||
|
minEnabledWidth: number, // don't show UI if player is narrower than % of screen width
|
||||||
|
minEnabledHeight: number, // don't show UI if player is narrower than % of screen height
|
||||||
|
activation: 'trigger-zone' | 'player', // what needs to be hovered in order for UI to be visible
|
||||||
|
triggerZoneDimensions: { // how large the trigger zone is (relative to player size)
|
||||||
|
width: number
|
||||||
|
height: number,
|
||||||
|
offsetX: number, // fed to translateX(offsetX + '%'). Valid range [-100, 0]
|
||||||
|
offsetY: number // fed to translateY(offsetY + '%'). Valid range [-100, 100]
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
restrictions?: RestrictionsSettings;
|
restrictions?: RestrictionsSettings;
|
||||||
@ -292,16 +305,13 @@ interface SettingsInterface {
|
|||||||
//
|
//
|
||||||
sites: {
|
sites: {
|
||||||
[x: string]: SiteSettingsInterface,
|
[x: string]: SiteSettingsInterface,
|
||||||
},
|
}
|
||||||
|
|
||||||
telemetry?: UwTelemetryInterface
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SiteSettingsInterface {
|
export interface SiteSettingsInterface {
|
||||||
enable: ExtensionEnvironmentSettingsInterface;
|
enable: ExtensionEnvironmentSettingsInterface;
|
||||||
enableAard: ExtensionEnvironmentSettingsInterface;
|
enableAard: ExtensionEnvironmentSettingsInterface;
|
||||||
enableKeyboard: ExtensionEnvironmentSettingsInterface;
|
enableKeyboard: ExtensionEnvironmentSettingsInterface;
|
||||||
ui?: InPlayerUISettingsInterface,
|
|
||||||
|
|
||||||
type?: 'official' | 'community' | 'user-defined' | 'testing' | 'officially-disabled' | 'unknown' | 'modified';
|
type?: 'official' | 'community' | 'user-defined' | 'testing' | 'officially-disabled' | 'unknown' | 'modified';
|
||||||
defaultType: 'official' | 'community' | 'user-defined' | 'testing' | 'officially-disabled' | 'unknown' | 'modified';
|
defaultType: 'official' | 'community' | 'user-defined' | 'testing' | 'officially-disabled' | 'unknown' | 'modified';
|
||||||
@ -330,13 +340,6 @@ export interface SiteSettingsInterface {
|
|||||||
|
|
||||||
// the following fields are for use with extension update script
|
// the following fields are for use with extension update script
|
||||||
override?: boolean; // whether settings for this site will be overwritten by extension upgrade script
|
override?: boolean; // whether settings for this site will be overwritten by extension upgrade script
|
||||||
|
|
||||||
workarounds?: {
|
|
||||||
iframeTransparencyWarningDismissed?: boolean;
|
|
||||||
disableColorSchemeAwareness?: boolean;
|
|
||||||
forceColorScheme?: 'normal' | 'light' | 'dark',
|
|
||||||
lastColorSchemeAwarenessCheck?: Date;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PlayerAutoConfigInterface {
|
export interface PlayerAutoConfigInterface {
|
||||||
@ -369,28 +372,4 @@ export interface SiteDOMElementSettingsInterface {
|
|||||||
nodeCss?: {[x: string]: string};
|
nodeCss?: {[x: string]: string};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InPlayerUISettingsInterface {
|
|
||||||
enabled: boolean,
|
|
||||||
enabledFullscreenOnly: boolean,
|
|
||||||
popupAlignment: 'left' | 'right',
|
|
||||||
minEnabledWidth: number, // don't show UI if player is narrower than % of screen width
|
|
||||||
minEnabledHeight: number, // don't show UI if player is narrower than % of screen height
|
|
||||||
activation: 'trigger-zone' | 'player', // what needs to be hovered in order for UI to be visible
|
|
||||||
triggerZoneDimensions: { // how large the trigger zone is (relative to player size)
|
|
||||||
width: number
|
|
||||||
height: number,
|
|
||||||
offsetX: number, // fed to translateX(offsetX + '%'). Valid range [-100, 0]
|
|
||||||
offsetY: number // fed to translateY(offsetY + '%'). Valid range [-100, 100]
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UwTelemetryInterface {
|
|
||||||
iframeTransparency?: {
|
|
||||||
[siteName: string]: {
|
|
||||||
reportedWithColorSchemeAllowed?: boolean;
|
|
||||||
reportedWithColorSchemeDisabled?: boolean;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default SettingsInterface;
|
export default SettingsInterface;
|
||||||
|
@ -36,17 +36,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
Ultrawidify
|
Ultrawidify
|
||||||
|
|
||||||
<div
|
|
||||||
v-if="!siteSettings?.data.workarounds?.iframeTransparencyWarningDismissed"
|
|
||||||
class="absolute ui-warning small uw-clickable">
|
|
||||||
If all you see is white or black screen,<br/>disable UI and report your GPU to github.<br/>Open.<br/>
|
|
||||||
|
|
||||||
<br />
|
|
||||||
<br /> You can also <a href="" @click="iframeAutofix()">click here to attempt a fix</a>.
|
|
||||||
<br />
|
|
||||||
<br /> If you experience no issues, <a href="" @click="iframeDismiss()">click here to hide this warning.</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
@ -463,7 +452,6 @@ export default {
|
|||||||
this.sendToParentLowLevel('uw-bus-tunnel', {
|
this.sendToParentLowLevel('uw-bus-tunnel', {
|
||||||
action: 'get-player-dimensions'
|
action: 'get-player-dimensions'
|
||||||
});
|
});
|
||||||
this.sendToParentLowLevel('uw-get-page-stats', null);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
destroyed() {
|
destroyed() {
|
||||||
@ -597,22 +585,6 @@ export default {
|
|||||||
|
|
||||||
handleBusTunnelIn(payload) {
|
handleBusTunnelIn(payload) {
|
||||||
this.eventBus.send(payload.action, payload.config, payload.routingData);
|
this.eventBus.send(payload.action, payload.config, payload.routingData);
|
||||||
},
|
|
||||||
|
|
||||||
async iframeAutofix() {
|
|
||||||
console.log('site:', this.site, this.siteSettings);
|
|
||||||
if (this.siteSettings?.data.workarounds?.disableColorSchemeAwareness === false) {
|
|
||||||
await this.settings.setProp(['sites', this.site, 'workarounds', 'disableColorSchemeAwareness'], true);
|
|
||||||
} else {
|
|
||||||
await this.settings.setProp(['sites', this.site, 'workarounds', 'disableColorSchemeAwareness'], false);
|
|
||||||
}
|
|
||||||
await this.settings.saveWithoutReload();
|
|
||||||
this.eventBus.sendToTunnel('uw-reload-window');
|
|
||||||
},
|
|
||||||
async iframeDismiss() {
|
|
||||||
await this.settings.setProp(['sites', this.site, 'workarounds', 'iframeTransparencyWarningDismissed'], true);
|
|
||||||
await this.settings.save();
|
|
||||||
this.eventBus.sendToTunnel('uw-reload-window');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -684,14 +656,10 @@ export default {
|
|||||||
.ui-warning {
|
.ui-warning {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
|
||||||
transform: translateY(-100%);
|
transform: translateY(-100%);
|
||||||
|
|
||||||
max-width: 20rem;
|
max-width: 16rem;
|
||||||
width: 20rem;
|
width: 16rem;
|
||||||
|
|
||||||
padding: 1rem;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
@ -699,17 +667,6 @@ export default {
|
|||||||
white-space: normal;
|
white-space: normal;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
|
||||||
&.small {
|
|
||||||
font-size: 0.85rem;
|
|
||||||
color: #888;
|
|
||||||
background-color: rgba(0,0,0,0.69);
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #fa6;
|
|
||||||
opacity: 0.69;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,27 +16,6 @@
|
|||||||
<li> <a target="_blank" href="https://github.com/tamius-han/ultrawidify/issues"><b>Github (preferred)</b></a><br/></li>
|
<li> <a target="_blank" href="https://github.com/tamius-han/ultrawidify/issues"><b>Github (preferred)</b></a><br/></li>
|
||||||
<li>Email: <a target="_blank" :href="mailtoLink">tamius.han@gmail.com</a></li>
|
<li>Email: <a target="_blank" :href="mailtoLink">tamius.han@gmail.com</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<b>Is your screen entirely white or entirely black?</b>
|
|
||||||
|
|
||||||
<p>This appears to be a rare issue that happens to some people. If you're experiencing this issue, please consider contacting me and sharing the following data:</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Which sites this problem appears on and whether it happens on youtube. If you use youtube premium, please try signing out of youtube (or use a new profile in Google Chrome) in order to see whether youtube premium is required.</li>
|
|
||||||
<li>your browser (get full version from <code>chrome://settings/help</code>). if using browsers other than Chrome, please try to reproduce this issue in Chrome</li>
|
|
||||||
<li>your operating system</li>
|
|
||||||
<li>your graphics card</li>
|
|
||||||
<li>whether you're using dark theme in your OS, and whether you're using website's built-in dark/light theme.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>Please post this info to <a href="https://github.com/tamius-han/ultrawidify/issues/262" target="_blank">this thread</a>, or message me via e-mail.</p>
|
|
||||||
|
|
||||||
<p>Then, disable the in-player UI.</p>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
When reporting bugs, please include the following information:
|
When reporting bugs, please include the following information:
|
||||||
</p>
|
</p>
|
||||||
@ -88,7 +67,6 @@ export default {
|
|||||||
mailtoLink: '',
|
mailtoLink: '',
|
||||||
redditLink: '',
|
redditLink: '',
|
||||||
showEasterEgg: false,
|
showEasterEgg: false,
|
||||||
pageData: {}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
<li>Half-fixed in-player UI on sites where player is not detected correctly</li>
|
<li>Half-fixed in-player UI on sites where player is not detected correctly</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3>6.2.3 (current)</h3>
|
<h3>6.2.3</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Fixed default persistent mode</li>
|
<li>Fixed default persistent mode</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -62,9 +62,7 @@ export default {
|
|||||||
'uw-page-stats': {
|
'uw-page-stats': {
|
||||||
function: (data) => {
|
function: (data) => {
|
||||||
console.log('got page statss:', data);
|
console.log('got page statss:', data);
|
||||||
this.pageData = JSON.parse(JSON.stringify(data));
|
this.pageData = data;
|
||||||
|
|
||||||
this.$nextTick( () => this.$forceUpdate());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -111,7 +111,7 @@ export default class UWContent {
|
|||||||
|
|
||||||
this.logger.log('info', 'debug', "[uw.js::setup] KeyboardHandler initiated.");
|
this.logger.log('info', 'debug', "[uw.js::setup] KeyboardHandler initiated.");
|
||||||
|
|
||||||
this.globalUi = new UI('ultrawidify-global-ui', {eventBus: this.eventBus, isGlobal: true, siteSettings: this.siteSettings});
|
this.globalUi = new UI('ultrawidify-global-ui', {eventBus: this.eventBus, isGlobal: true});
|
||||||
this.globalUi.enable();
|
this.globalUi.enable();
|
||||||
this.globalUi.setUiVisibility(false);
|
this.globalUi.setUiVisibility(false);
|
||||||
|
|
||||||
|
@ -5,9 +5,6 @@ import Settings from './lib/Settings';
|
|||||||
import Logger, { baseLoggingOptions } from './lib/Logger';
|
import Logger, { baseLoggingOptions } from './lib/Logger';
|
||||||
import { sleep } from '../common/js/utils';
|
import { sleep } from '../common/js/utils';
|
||||||
import EventBus, { EventBusCommand } from './lib/EventBus';
|
import EventBus, { EventBusCommand } from './lib/EventBus';
|
||||||
import { IframeTransparencyVerifier, IframeVerificationPlayerData } from './lib/IframeTransparencyVerifier';
|
|
||||||
import { MessageSender } from './lib/comms/ChromeTabInterfaces';
|
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
export default class UWServer {
|
export default class UWServer {
|
||||||
settings: Settings;
|
settings: Settings;
|
||||||
@ -21,8 +18,6 @@ export default class UWServer {
|
|||||||
videoTabs: any = {};
|
videoTabs: any = {};
|
||||||
currentTabId: number = 0;
|
currentTabId: number = 0;
|
||||||
|
|
||||||
IframeTransparencyVerifier: IframeTransparencyVerifier = new IframeTransparencyVerifier()
|
|
||||||
|
|
||||||
selectedSubitem: any = {
|
selectedSubitem: any = {
|
||||||
'siteSettings': undefined,
|
'siteSettings': undefined,
|
||||||
'videoSettings': undefined,
|
'videoSettings': undefined,
|
||||||
@ -49,11 +44,6 @@ export default class UWServer {
|
|||||||
},
|
},
|
||||||
'get-current-site': {
|
'get-current-site': {
|
||||||
function: (message, context) => this.getCurrentSite()
|
function: (message, context) => this.getCurrentSite()
|
||||||
},
|
|
||||||
'verify-iframe-transparency': {
|
|
||||||
function: (message, context) => {
|
|
||||||
this.verifyUiTransparency(message.playerData, context.comms.sender, message.telemetryData);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -111,7 +101,7 @@ export default class UWServer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async injectCss(css, sender: MessageSender) {
|
async injectCss(css, sender) {
|
||||||
if (!css) {
|
if (!css) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -143,7 +133,7 @@ export default class UWServer {
|
|||||||
this.logger.log('error','debug', '[UwServer::injectCss] Error while injecting css:', {error: e, css, sender});
|
this.logger.log('error','debug', '[UwServer::injectCss] Error while injecting css:', {error: e, css, sender});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async removeCss(css, sender: MessageSender) {
|
async removeCss(css, sender) {
|
||||||
try {
|
try {
|
||||||
if (BrowserDetect.firefox) {
|
if (BrowserDetect.firefox) {
|
||||||
chrome.scripting.removeCSS({
|
chrome.scripting.removeCSS({
|
||||||
@ -377,39 +367,4 @@ export default class UWServer {
|
|||||||
|
|
||||||
return hostname;
|
return hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
async verifyUiTransparency(verificationData: IframeVerificationPlayerData, sender: MessageSender, telemetryData?: any) {
|
|
||||||
const transparencyVerificationResult = await this.IframeTransparencyVerifier.verifyUiTransparency(
|
|
||||||
sender.tab.windowId,
|
|
||||||
{
|
|
||||||
player: verificationData,
|
|
||||||
tab: {
|
|
||||||
width: sender.tab.width,
|
|
||||||
height: sender.tab.height,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log('Transparency confirmed.');
|
|
||||||
|
|
||||||
this.eventBus.send(
|
|
||||||
'iframe-transparency-results',
|
|
||||||
{
|
|
||||||
transparencyVerificationResult
|
|
||||||
},
|
|
||||||
{
|
|
||||||
comms: {
|
|
||||||
forwardTo: 'active'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// axios.post(
|
|
||||||
// 'https://uw-telemetry.tamius.net/iframe-transparency',
|
|
||||||
// {
|
|
||||||
// ...telemetryData,
|
|
||||||
// transparencyCheckResult: hasTransparency,
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1842,9 +1842,6 @@ const ExtensionConf: SettingsInterface = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
|
||||||
|
|
||||||
telemetry: {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,233 +0,0 @@
|
|||||||
export enum TransparencyVerificationResult {
|
|
||||||
Ok = 0,
|
|
||||||
Fail = 1,
|
|
||||||
NoVisibleElements = 2,
|
|
||||||
Error = 3
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IframeVerificationData {
|
|
||||||
tab: {
|
|
||||||
width: number,
|
|
||||||
height: number,
|
|
||||||
},
|
|
||||||
player: IframeVerificationPlayerData
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IframeVerificationPlayerData {
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
width: number,
|
|
||||||
height: number,
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IframeCheckItem {
|
|
||||||
position: 'top' | 'center' | 'bottom' | 'left' | 'right';
|
|
||||||
offset: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IframeCheckPosition {
|
|
||||||
positionX: 'top' | 'center' | 'bottom';
|
|
||||||
positionY: 'left' | 'center' | 'right';
|
|
||||||
offsetX: number;
|
|
||||||
offsetY: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class IframeTransparencyVerifier {
|
|
||||||
|
|
||||||
async verifyUiTransparency(windowId: number, tabDimensions: IframeVerificationData): Promise<{result: TransparencyVerificationResult, dataUrl?: string}> { console.info('Verifying UI transparency:', tabDimensions);
|
|
||||||
|
|
||||||
// const {visibleX, visibleY} = this.getVisibleMarkers(tabDimensions);
|
|
||||||
// if (!visibleX.length || !visibleY.length) {
|
|
||||||
// console.warn('[transparency check] No visible elements.');
|
|
||||||
return {result: TransparencyVerificationResult.NoVisibleElements};
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const checkPositions = this.processMarkers(visibleX, visibleY);
|
|
||||||
|
|
||||||
// const dataUrl = await chrome.tabs.captureVisibleTab(
|
|
||||||
// undefined, // windowId,
|
|
||||||
// {
|
|
||||||
// format: "png"
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
|
|
||||||
// try {
|
|
||||||
// const canvas = new OffscreenCanvas(tabDimensions.tab.width, tabDimensions.tab.height);
|
|
||||||
// const ctx = canvas.getContext('2d')!;
|
|
||||||
|
|
||||||
// const res = await fetch(dataUrl);
|
|
||||||
// const blob = await res.blob();
|
|
||||||
|
|
||||||
// const bitmap = createImageBitmap(blob);
|
|
||||||
|
|
||||||
// (ctx as any).drawImage(bitmap, 0, 0);
|
|
||||||
|
|
||||||
// const imageData = (ctx as any).getImageData(0, 0, tabDimensions.tab.width, tabDimensions.tab.height).data;
|
|
||||||
|
|
||||||
// if (this.detectMarkers(checkPositions, tabDimensions.tab.width, imageData)) {
|
|
||||||
// console.info('Verified transparency');
|
|
||||||
// return {
|
|
||||||
// result: TransparencyVerificationResult.Ok,
|
|
||||||
// dataUrl: dataUrl
|
|
||||||
// };
|
|
||||||
// } else {
|
|
||||||
// console.info('Transparency checks came back negative');
|
|
||||||
// return {
|
|
||||||
// result: TransparencyVerificationResult.Fail,
|
|
||||||
// dataUrl: dataUrl
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// } catch (e) {
|
|
||||||
// console.error('[transparency check] Error while checking for transparency:', e);
|
|
||||||
// return {result: TransparencyVerificationResult.Error};
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
private getVisibleMarkers({tab, player}: IframeVerificationData) {
|
|
||||||
const visibleX: IframeCheckItem[] = [];
|
|
||||||
const visibleY: IframeCheckItem[] = [];
|
|
||||||
|
|
||||||
// Determine which markers should be visible.
|
|
||||||
|
|
||||||
// Visibility: TOP ROW
|
|
||||||
console.log('player:', player.y, tab.height);
|
|
||||||
|
|
||||||
if (player.y >= 0 && player.y < tab.height) {
|
|
||||||
visibleY.push({
|
|
||||||
position: 'top',
|
|
||||||
offset: player.y,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Visibility: CENTER
|
|
||||||
const yHalfPosition = Math.floor(player.y + player.height / 2);
|
|
||||||
if (player.y + yHalfPosition - 2 > 0 && player.y + yHalfPosition + 2 < tab.height) {
|
|
||||||
visibleY.push({
|
|
||||||
position: 'center',
|
|
||||||
offset: player.y + yHalfPosition,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Visibility: BOTTOM ROW
|
|
||||||
if (player.y + player.height - 1 > 0 && player.y + player.height + 1 < tab.height) {
|
|
||||||
visibleY.push({
|
|
||||||
position: 'bottom',
|
|
||||||
offset: player.y + player.height - 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Visibility: LEFT SIDE
|
|
||||||
if (player.x >= 0 && player.x < tab.width) {
|
|
||||||
visibleX.push({
|
|
||||||
position: 'left',
|
|
||||||
offset: player.x,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Visibility: X CENTER
|
|
||||||
const xHalfPosition = Math.floor(player.x + player.width / 2);
|
|
||||||
if (player.x + xHalfPosition - 2 > 0 && player.x + xHalfPosition + 2 < tab.width) {
|
|
||||||
visibleX.push({
|
|
||||||
position: 'center',
|
|
||||||
offset: player.x + xHalfPosition,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Visibility: RIGHT SIDE
|
|
||||||
if (player.x + player.width - 1 > 0 && player.x + player.width + 1 < tab.width) {
|
|
||||||
visibleX.push({
|
|
||||||
position: 'right',
|
|
||||||
offset: player.x + player.width - 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('visible candidates', visibleX, visibleY);
|
|
||||||
|
|
||||||
return {
|
|
||||||
visibleX,
|
|
||||||
visibleY,
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private processMarkers(candidatesX: IframeCheckItem[], candidatesY: IframeCheckItem[]): IframeCheckPosition[] {
|
|
||||||
if (!candidatesX.length || !candidatesY.length) {
|
|
||||||
return [] as IframeCheckPosition[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const checkPositions: IframeCheckPosition[] = [];
|
|
||||||
|
|
||||||
for (const row of candidatesY) {
|
|
||||||
for (const col of candidatesX) {
|
|
||||||
// 'center center' is not valid position.
|
|
||||||
if (row.position !== col.position) {
|
|
||||||
checkPositions.push({
|
|
||||||
positionX: row.position as 'top' | 'center' | 'bottom',
|
|
||||||
positionY: col.position as 'left' | 'center' | 'right',
|
|
||||||
offsetX: col.offset,
|
|
||||||
offsetY: row.offset,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return checkPositions;
|
|
||||||
}
|
|
||||||
|
|
||||||
private detectMarkers(checkPositions: IframeCheckPosition[], rowLength: number, imageData: Uint8ClampedArray): boolean {
|
|
||||||
for (const position of checkPositions) {
|
|
||||||
if (position.positionY === 'center') {
|
|
||||||
if (this.detectColumnMarker(position.offsetX, position.offsetY, rowLength, imageData)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.detectRowMarker(position.offsetX, position.offsetY, rowLength, imageData)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks if our magic sequence is present in a row configuration
|
|
||||||
private detectRowMarker(x, y, rowLength, imageData): boolean {
|
|
||||||
const start = (y * rowLength + x) * 4;
|
|
||||||
|
|
||||||
return imageData[start] === 0
|
|
||||||
&& imageData[start + 1] === 1
|
|
||||||
&& imageData[start + 2] === 2
|
|
||||||
&& imageData[start + 4] === 3
|
|
||||||
&& imageData[start + 5] === 4
|
|
||||||
&& imageData[start + 6] === 5
|
|
||||||
&& imageData[start + 8] === 5
|
|
||||||
&& imageData[start + 9] === 4
|
|
||||||
&& imageData[start + 10] === 3
|
|
||||||
&& imageData[start + 12] === 2
|
|
||||||
&& imageData[start + 13] === 1
|
|
||||||
&& imageData[start + 15] === 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks if our magic sequence is present in a column configuration
|
|
||||||
private detectColumnMarker(x, y, rowLength, imageData) {
|
|
||||||
const rowOffset = rowLength * 4;
|
|
||||||
|
|
||||||
const r1 = (y * rowLength + x) * 4;
|
|
||||||
const r2 = r1 + rowOffset;
|
|
||||||
const r3 = r2 + rowOffset;
|
|
||||||
const r4 = r3 + rowOffset;
|
|
||||||
|
|
||||||
return imageData[r1] === 0
|
|
||||||
&& imageData[r1 + 1] === 1
|
|
||||||
&& imageData[r1 + 2] === 2
|
|
||||||
&& imageData[r2 ] === 3
|
|
||||||
&& imageData[r2 + 1] === 4
|
|
||||||
&& imageData[r2 + 2] === 5
|
|
||||||
&& imageData[r3 ] === 5
|
|
||||||
&& imageData[r3 + 1] === 4
|
|
||||||
&& imageData[r3 + 2] === 3
|
|
||||||
&& imageData[r4 ] === 2
|
|
||||||
&& imageData[r4 + 1] === 1
|
|
||||||
&& imageData[r4 + 2] === 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
export interface MessageSender {
|
|
||||||
documentId?: string,
|
|
||||||
frameId?: number,
|
|
||||||
id: string,
|
|
||||||
origin: string,
|
|
||||||
tab: Tab,
|
|
||||||
url: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Tab {
|
|
||||||
active: boolean,
|
|
||||||
audible?: boolean,
|
|
||||||
autoDiscardable: boolean,
|
|
||||||
discarded: boolean,
|
|
||||||
favIconUrl?: string,
|
|
||||||
frozen?: boolean,
|
|
||||||
groupId: number,
|
|
||||||
height: number,
|
|
||||||
highlighted: boolean,
|
|
||||||
id?: number,
|
|
||||||
incognito: boolean,
|
|
||||||
index: number,
|
|
||||||
lastAccessed: number,
|
|
||||||
openerTabId?: number,
|
|
||||||
pendingUrl?: string,
|
|
||||||
pinned: boolean,
|
|
||||||
sessionId: string,
|
|
||||||
url?: string;
|
|
||||||
width: number;
|
|
||||||
windowId?: number;
|
|
||||||
}
|
|
@ -117,29 +117,6 @@ class CommsClient {
|
|||||||
|
|
||||||
this.commsId = (Math.random() * 20).toFixed(0);
|
this.commsId = (Math.random() * 20).toFixed(0);
|
||||||
|
|
||||||
this.eventBus.subscribeMulti(
|
|
||||||
{
|
|
||||||
'uw-get-page-stats': {
|
|
||||||
function: (config, routingData) => {
|
|
||||||
this.eventBus.send(
|
|
||||||
'uw-page-stats',
|
|
||||||
{
|
|
||||||
pcsDark: window.matchMedia('(prefers-color-scheme: dark)').matches,
|
|
||||||
pcsLight: window.matchMedia('(prefers-color-scheme: light)').matches,
|
|
||||||
colorScheme: window.getComputedStyle( document.body ,null).getPropertyValue('color-scheme')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
comms: {
|
|
||||||
forwardTo: 'popup'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
this
|
|
||||||
);
|
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("CONSTRUCOTR FAILED:", e)
|
console.error("CONSTRUCOTR FAILED:", e)
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,6 @@ if (process.env.CHANNEL !== 'stable'){
|
|||||||
console.info("Loading: UI");
|
console.info("Loading: UI");
|
||||||
}
|
}
|
||||||
|
|
||||||
// When this was first coded in summer of 2024, websites using color-scheme other than 'normal'
|
|
||||||
// displayed a black square over the video instead of a transparent iframe that we expect.
|
|
||||||
// StackOverflow said that this was a workaround for the issue, and it worked just fine. However,
|
|
||||||
// 6 months later, this fix is no longer working. Using csui-overlay-normal even on dark mode websites
|
|
||||||
// appears to give us a transparent iframe, as we require.
|
|
||||||
// Twitter is an example of a site using this color-scheme=dark property, so any changes to this code
|
|
||||||
// should be tested on this video:
|
|
||||||
// https://x.com/TheKhelIndia/status/1874019989357027511?mx=2
|
|
||||||
// As of 1. 1. 2025, 'light' and 'dark' are commented out in order to force 'csui-overlay-normal' everywhere.
|
|
||||||
const csuiVersions = {
|
const csuiVersions = {
|
||||||
'normal': 'csui', // csui-overlay-normal.html, maps to csui.html
|
'normal': 'csui', // csui-overlay-normal.html, maps to csui.html
|
||||||
'light': 'csui-light', // csui-overlay-light.html, maps to csui-light.html
|
'light': 'csui-light', // csui-overlay-light.html, maps to csui-light.html
|
||||||
@ -29,8 +20,6 @@ class UI {
|
|||||||
this.interfaceId = interfaceId;
|
this.interfaceId = interfaceId;
|
||||||
this.uiConfig = uiConfig;
|
this.uiConfig = uiConfig;
|
||||||
this.lastProbeResponseTs = null;
|
this.lastProbeResponseTs = null;
|
||||||
this.isVisible = false;
|
|
||||||
this.isOpaque = false;
|
|
||||||
|
|
||||||
this.isGlobal = uiConfig.isGlobal ?? false;
|
this.isGlobal = uiConfig.isGlobal ?? false;
|
||||||
|
|
||||||
@ -40,43 +29,44 @@ class UI {
|
|||||||
this.saveState = undefined;
|
this.saveState = undefined;
|
||||||
this.playerData = uiConfig.playerData;
|
this.playerData = uiConfig.playerData;
|
||||||
this.uiSettings = uiConfig.uiSettings;
|
this.uiSettings = uiConfig.uiSettings;
|
||||||
this.siteSettings = uiConfig.siteSettings;
|
|
||||||
this.settings = uiConfig.settings;
|
|
||||||
|
|
||||||
this.iframeErrorCount = 0;
|
this.iframeErrorCount = 0;
|
||||||
this.iframeConfirmed = false;
|
this.iframeConfirmed = false;
|
||||||
this.iframeRejected = false;
|
this.iframeRejected = false;
|
||||||
|
|
||||||
this.preventHiding = false;
|
|
||||||
this.wantsToHide = false;
|
|
||||||
this.wantsToTransparent = false;
|
|
||||||
this.performedTransparencyCheck = false;
|
|
||||||
|
|
||||||
// TODO: at some point, UI should be different for global popup and in-player UI
|
// TODO: at some point, UI should be different for global popup and in-player UI
|
||||||
const csuiVersion = this.getCsuiVersion();
|
this.csuiScheme = this.getCsuiScheme();
|
||||||
|
const csuiVersion = this.getCsuiVersion(this.csuiScheme.contentScheme);
|
||||||
this.uiURI = chrome.runtime.getURL(`/csui/${csuiVersion}.html`);
|
this.uiURI = chrome.runtime.getURL(`/csui/${csuiVersion}.html`);
|
||||||
this.extensionBase = chrome.runtime.getURL('').replace(/\/$/, "");
|
this.extensionBase = chrome.runtime.getURL('').replace(/\/$/, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
try {
|
|
||||||
this.initIframes();
|
this.initIframes();
|
||||||
this.initMessaging();
|
this.initMessaging();
|
||||||
} catch (e) {
|
|
||||||
console.error('failed to init ui:', e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getCsuiVersion() {
|
/**
|
||||||
if (this.siteSettings?.workarounds?.forceColorScheme) {
|
* Returns color scheme we need to use.
|
||||||
return csuiVersions[this.siteSettings.workarounds.forceColorScheme];
|
*
|
||||||
}
|
* contentScheme is used to select the correct HTML template.
|
||||||
if (this.siteSettings?.data?.workarounds?.disableColorSchemeAwareness !== false) {
|
* iframeScheme gets applied to the iframe as style
|
||||||
return csuiVersions.normal;
|
* @returns {contentScheme: string, iframeScheme: string}
|
||||||
}
|
*/
|
||||||
|
getCsuiScheme() {
|
||||||
|
return {
|
||||||
|
contentScheme: window.getComputedStyle( document.body ,null).getPropertyValue('color-scheme'),
|
||||||
|
iframeScheme: document.documentElement.style.colorScheme || document.body.style.colorScheme || undefined
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const preferredScheme = window.getComputedStyle( document.body ,null).getPropertyValue('color-scheme');
|
/**
|
||||||
|
* Returns correct template for given preferredScheme parameter
|
||||||
|
* @param {*} preferredScheme
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
getCsuiVersion(preferredScheme) {
|
||||||
return csuiVersions[preferredScheme] ?? csuiVersions.normal;
|
return csuiVersions[preferredScheme] ?? csuiVersions.normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,10 +109,16 @@ class UI {
|
|||||||
iframe.style.position = "absolute";
|
iframe.style.position = "absolute";
|
||||||
iframe.style.zIndex = this.isGlobal ? '90009' : '90000';
|
iframe.style.zIndex = this.isGlobal ? '90009' : '90000';
|
||||||
iframe.style.border = 0;
|
iframe.style.border = 0;
|
||||||
iframe.style.opacity = 0;
|
|
||||||
iframe.style.pointerEvents = 'none';
|
iframe.style.pointerEvents = 'none';
|
||||||
|
iframe.style.opacity = 0;
|
||||||
iframe.style.backgroundColor = 'transparent !important';
|
iframe.style.backgroundColor = 'transparent !important';
|
||||||
|
|
||||||
|
// If colorScheme is defined via CSS on the HTML or BODY elements, then we need to also
|
||||||
|
// put a matching style to the iframe itself. Using the correct UI template is not enough.
|
||||||
|
if (this.csuiScheme.iframeScheme) {
|
||||||
|
iframe.style.colorScheme = this.csuiScheme.iframeScheme;
|
||||||
|
}
|
||||||
|
|
||||||
/* so we have a problem: we want iframe to be clickthrough everywhere except
|
/* so we have a problem: we want iframe to be clickthrough everywhere except
|
||||||
* on our actual overlay. There's no nice way of doing that, so we need some
|
* on our actual overlay. There's no nice way of doing that, so we need some
|
||||||
* extra javascript to deal with this.
|
* extra javascript to deal with this.
|
||||||
@ -132,7 +128,6 @@ class UI {
|
|||||||
* that iframe also needs to run its own instance of onMouseMove.
|
* that iframe also needs to run its own instance of onMouseMove.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// set uiIframe for handleMessage
|
// set uiIframe for handleMessage
|
||||||
this.uiIframe = iframe;
|
this.uiIframe = iframe;
|
||||||
|
|
||||||
@ -183,18 +178,6 @@ class UI {
|
|||||||
document.addEventListener('mousemove', fn, true);
|
document.addEventListener('mousemove', fn, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add some squares to the page.
|
|
||||||
// Sets up checks for conditions that cause these two mutually exclusive issues:
|
|
||||||
// * https://github.com/tamius-han/ultrawidify/issues/262
|
|
||||||
// * https://github.com/tamius-han/ultrawidify/issues/259
|
|
||||||
for (const x of ['left', 'center', 'right']) {
|
|
||||||
for (const y of ['top', 'center', 'bottom']) {
|
|
||||||
if (x !== y) {
|
|
||||||
rootDiv.appendChild(this.generateDebugMarker(x, y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rootDiv.appendChild(iframe);
|
rootDiv.appendChild(iframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,11 +193,6 @@ class UI {
|
|||||||
|
|
||||||
this.eventBus.subscribeMulti(
|
this.eventBus.subscribeMulti(
|
||||||
{
|
{
|
||||||
'uw-reload-window': {
|
|
||||||
function: () => {
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'uw-config-broadcast': {
|
'uw-config-broadcast': {
|
||||||
function: (config, routingData) => {
|
function: (config, routingData) => {
|
||||||
this.sendToIframe('uw-config-broadcast', config, routingData);
|
this.sendToIframe('uw-config-broadcast', config, routingData);
|
||||||
@ -232,6 +210,24 @@ class UI {
|
|||||||
this.sendToIframe('uw-set-ui-state', {...config, isGlobal: this.isGlobal}, routingData);
|
this.sendToIframe('uw-set-ui-state', {...config, isGlobal: this.isGlobal}, routingData);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'uw-get-page-stats': {
|
||||||
|
function: (config, routingData) => {
|
||||||
|
console.log('got get page stats!');
|
||||||
|
this.eventBus.send(
|
||||||
|
'uw-page-stats',
|
||||||
|
{
|
||||||
|
pcsDark: window.matchMedia('(prefers-color-scheme: dark)').matches,
|
||||||
|
pcsLight: window.matchMedia('(prefers-color-scheme: light)').matches,
|
||||||
|
colorScheme: window.getComputedStyle( document.body ,null).getPropertyValue('color-scheme')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
comms: {
|
||||||
|
forwardTo: 'popup'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
'uw-restore-ui-state': {
|
'uw-restore-ui-state': {
|
||||||
function: (config, routingData) => {
|
function: (config, routingData) => {
|
||||||
if (!this.isGlobal) {
|
if (!this.isGlobal) {
|
||||||
@ -239,25 +235,7 @@ class UI {
|
|||||||
this.sendToIframe('uw-restore-ui-state', config, routingData);
|
this.sendToIframe('uw-restore-ui-state', config, routingData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
'iframe-transparency-results': {
|
|
||||||
function: (data, routingData) => {
|
|
||||||
console.log('——————————— iframe transparency results are back!', data);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'uw-get-page-stats': {
|
|
||||||
function: (config, routingData) => {
|
|
||||||
console.log('uw:Č Got page stats request')
|
|
||||||
this.sendToIframeLowLevel(
|
|
||||||
'uw-page-stats',
|
|
||||||
{
|
|
||||||
pcsDark: window.matchMedia('(prefers-color-scheme: dark)').matches,
|
|
||||||
pcsLight: window.matchMedia('(prefers-color-scheme: light)').matches,
|
|
||||||
colorScheme: window.getComputedStyle( document.body ,null).getPropertyValue('color-scheme')
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
@ -271,151 +249,7 @@ class UI {
|
|||||||
this.handleMessage(message);
|
this.handleMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
verifyIframeTransparency() {
|
|
||||||
if (this.isGlobal) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this.siteSettings || !this.settings) {
|
|
||||||
console.warn('settings not provided, not verifying transparency');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.performedTransparencyCheck || !this.isOpaque || !this.uiConfig?.parentElement) {
|
|
||||||
// console.warn('transparency was already checked, opacity is zero, or parent element isnt a thing:', this.performedTransparencyCheck, 'is opaque:', this.isOpaque, this.uiConfig?.parentElement);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let reportTelemetry = true;
|
|
||||||
|
|
||||||
// if (this.siteSettings.data.workarounds?.disableSchemeAwareness) {
|
|
||||||
// if (this.settings.active.telemetry?.iframeTransparency?.[window.location.hostname]?.reportedWithColorSchemeDisabled) {
|
|
||||||
// reportTelemetry = false;
|
|
||||||
// } else {
|
|
||||||
// this.settings.setProp(['telemetry', window.location.hostname, 'reportedWithColorSchemaDisabled'], true)
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// if (this.settings.active.telemetry?.iframeTransparency?.[window.location.hostname]?.reportedWithColorSchemeAllowed) {
|
|
||||||
// reportTelemetry = false;
|
|
||||||
// } else {
|
|
||||||
// this.settings.setProp(['telemetry', window.location.hostname, 'reportedWithColorSchemeAllowed'], true)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
const rect = this.uiConfig.parentElement.getBoundingClientRect();
|
|
||||||
|
|
||||||
this.preventHiding = true;
|
|
||||||
setTimeout( () => {
|
|
||||||
this.eventBus.send(
|
|
||||||
'verify-iframe-transparency',
|
|
||||||
{
|
|
||||||
playerData: {
|
|
||||||
y: rect.top,
|
|
||||||
x: rect.left,
|
|
||||||
width: rect.width,
|
|
||||||
height: rect.height,
|
|
||||||
},
|
|
||||||
telemetryData: {
|
|
||||||
reportTelemetry,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}, 50);
|
|
||||||
this.performedTransparencyCheck = true;
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
this.preventHiding = false;
|
|
||||||
if (this.wantsToHide) {
|
|
||||||
this.setUiVisibility(false);
|
|
||||||
}
|
|
||||||
if (this.wantsToTransparent) {
|
|
||||||
this.setUiOpacity(false);
|
|
||||||
}
|
|
||||||
this.wantsToHide = false;
|
|
||||||
this.wantsToTransparent = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates marker positions for bug mitigations
|
|
||||||
*/
|
|
||||||
generateDebugMarker(x, y) {
|
|
||||||
const [parentMainDimension, parentCrossDimension] = y === 'center' ? ['height', 'width'] : ['width', 'height'];
|
|
||||||
|
|
||||||
let anchorStyle;
|
|
||||||
|
|
||||||
if (x === 'center' && x === y) {
|
|
||||||
anchorStyle = 'left: 50%; top: 50%; transform: translate(-50%, -50%);';
|
|
||||||
} else {
|
|
||||||
switch (x) {
|
|
||||||
case 'left':
|
|
||||||
anchorStyle = 'left: 0px;';
|
|
||||||
break;
|
|
||||||
case 'center':
|
|
||||||
anchorStyle = 'left: 50%; transform: translateX(-50%);';
|
|
||||||
break;
|
|
||||||
case 'right':
|
|
||||||
anchorStyle = 'right: 0px;';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
switch (y) {
|
|
||||||
case 'top':
|
|
||||||
anchorStyle = `${anchorStyle} top: 0px;`;
|
|
||||||
break;
|
|
||||||
case 'center':
|
|
||||||
anchorStyle = `${anchorStyle} top: 50%; transform: translateY(-50%);`;
|
|
||||||
break;
|
|
||||||
case 'bottom':
|
|
||||||
anchorStyle = `${anchorStyle} bottom: 0px;`;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let [mainAxis, crossAxis] = y === 'center' ? ['left', 'top'] : ['top', 'left'];
|
|
||||||
|
|
||||||
const template = document.createElement('template');
|
|
||||||
template.innerHTML = `
|
|
||||||
<div style="position: absolute; ${anchorStyle} ${parentMainDimension}: 4px; ${parentCrossDimension}: 1px; pointer-events: none;">
|
|
||||||
<div style="position: relative; width: 100%; height: 100%">
|
|
||||||
<div style="position: absolute; ${mainAxis}: 0px; ${crossAxis}: 0px; width: 1px; height: 1px; background-color: #000102"></div>
|
|
||||||
<div style="position: absolute; ${mainAxis}: 1px; ${crossAxis}: 0px; width: 1px; height: 1px; background-color: #030405"></div>
|
|
||||||
<div style="position: absolute; ${mainAxis}: 2px; ${crossAxis}: 0px; width: 1px; height: 1px; background-color: #050403"></div>
|
|
||||||
<div style="position: absolute; ${mainAxis}: 3px; ${crossAxis}: 0px; width: 1px; height: 1px; background-color: #020100"></div>
|
|
||||||
</div>
|
|
||||||
<div style="top: 5px; left: 5px; opacity: 0">
|
|
||||||
This marker is Chrome Shitiness Mitigation mechanism for Ultrawidify. It turns out that as of 2025-01, Chrome does not correctly respect
|
|
||||||
allowTransparency property on certain iframes, and will force white or black background across the entire element. It is unclear what's
|
|
||||||
causing the issue — so far, it seems to appear randomly.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`.replace(/\s+/g, ' ').trim();
|
|
||||||
|
|
||||||
return template.content.firstChild;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
setUiOpacity(visible) {
|
|
||||||
if (!visible && this.isVisible && this.preventHiding) {
|
|
||||||
this.wantsToTransparent = true;
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
this.uiIframe.style.opacity = visible ? '100' : '0';
|
|
||||||
this.isOpaque = visible;
|
|
||||||
|
|
||||||
if (visible) {
|
|
||||||
this.verifyIframeTransparency();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setUiVisibility(visible) {
|
setUiVisibility(visible) {
|
||||||
if (!visible && this.isVisible && this.preventHiding) {
|
|
||||||
this.wantsToHide = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isVisible = visible;
|
|
||||||
|
|
||||||
if (visible) {
|
if (visible) {
|
||||||
this.element.style.width = '100%';
|
this.element.style.width = '100%';
|
||||||
this.element.style.height = '100%';
|
this.element.style.height = '100%';
|
||||||
@ -427,7 +261,6 @@ class UI {
|
|||||||
this.uiIframe.style.width = '0px';
|
this.uiIframe.style.width = '0px';
|
||||||
this.uiIframe.style.height = '0px';
|
this.uiIframe.style.height = '0px';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async enable() {
|
async enable() {
|
||||||
@ -529,8 +362,7 @@ class UI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.uiIframe.style.pointerEvents = event.data.clickable ? 'auto' : 'none';
|
this.uiIframe.style.pointerEvents = event.data.clickable ? 'auto' : 'none';
|
||||||
this.setUiOpacity(event.data.opacity || this.isGlobal);
|
this.uiIframe.style.opacity = event.data.opacity || this.isGlobal ? '100' : '0';
|
||||||
// this.setUiVisibility( event.data.opacity || this.isGlobal );
|
|
||||||
break;
|
break;
|
||||||
case 'uw-bus-tunnel':
|
case 'uw-bus-tunnel':
|
||||||
const busCommand = event.data.payload;
|
const busCommand = event.data.payload;
|
||||||
@ -543,8 +375,7 @@ class UI {
|
|||||||
this.setUiVisibility(!this.isGlobal);
|
this.setUiVisibility(!this.isGlobal);
|
||||||
break;
|
break;
|
||||||
case 'uwui-hidden':
|
case 'uwui-hidden':
|
||||||
this.setUiOpacity(event.data.opacity || this.isGlobal);
|
this.uiIframe.style.opacity = event.data.opacity || this.isGlobal ? '100' : '0';
|
||||||
// this.setUiVisibility(event.data.opacity || this.isGlobal);
|
|
||||||
break;
|
break;
|
||||||
case 'uwui-global-window-hidden':
|
case 'uwui-global-window-hidden':
|
||||||
if (!this.isGlobal) {
|
if (!this.isGlobal) {
|
||||||
|
@ -248,11 +248,7 @@ class PlayerData {
|
|||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
deferredUiInitialization(playerDimensions) {
|
deferredUiInitialization(playerDimensions) {
|
||||||
if (
|
if (this.ui || ! this.videoData.settings.active.ui?.inPlayer?.enabled) {
|
||||||
this.ui
|
|
||||||
|| ! this.videoData.settings.active.ui?.inPlayer?.enabled
|
|
||||||
|| (this.siteSettings.data.ui && !this.siteSettings.data.ui.enabled)
|
|
||||||
) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,9 +265,7 @@ class PlayerData {
|
|||||||
parentElement: this.element,
|
parentElement: this.element,
|
||||||
eventBus: this.eventBus,
|
eventBus: this.eventBus,
|
||||||
playerData: this,
|
playerData: this,
|
||||||
uiSettings: this.videoData.settings.active.ui,
|
uiSettings: this.videoData.settings.active.ui
|
||||||
settings: this.videoData.settings,
|
|
||||||
siteSettings: this.siteSettings
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user