Compare commits

..

No commits in common. "60dd1193ab65035423923bd17a6e608ac5db2fb7" and "f7f046ea536f7fea38f4be603adb86cf47571314" have entirely different histories.

11 changed files with 84 additions and 259 deletions

View File

@ -86,7 +86,6 @@
:settings="settings" :settings="settings"
:eventBus="eventBus" :eventBus="eventBus"
:siteSettings="siteSettings" :siteSettings="siteSettings"
:hosts="activeHosts"
></PopupVideoSettings> ></PopupVideoSettings>
<BaseExtensionSettings <BaseExtensionSettings
v-if="selectedTab === 'extensionSettings'" v-if="selectedTab === 'extensionSettings'"
@ -94,7 +93,7 @@
:eventBus="eventBus" :eventBus="eventBus"
:siteSettings="siteSettings" :siteSettings="siteSettings"
:site="site.host" :site="site.host"
:hosts="activeHosts" :frames="activeFrames"
> >
</BaseExtensionSettings> </BaseExtensionSettings>
<ChangelogPanel <ChangelogPanel
@ -172,7 +171,6 @@ export default {
}, },
mounted() { mounted() {
this.tabs.find(x => x.id === 'changelog').highlight = !this.settings.active?.whatsNewChecked; this.tabs.find(x => x.id === 'changelog').highlight = !this.settings.active?.whatsNewChecked;
this.requestSite();
}, },
async created() { async created() {
try { try {
@ -193,8 +191,6 @@ export default {
{ {
source: this, source: this,
function: (config, context) => { function: (config, context) => {
console.log('set-current-site | this.site:', this.site, 'config.site:', config.site);
if (this.site) { if (this.site) {
if (!this.site.host) { if (!this.site.host) {
// dunno why this fix is needed, but sometimes it is // dunno why this fix is needed, but sometimes it is
@ -211,20 +207,10 @@ export default {
} }
}); });
this.loadHostnames(); this.loadFrames(this.site);
this.loadFrames();
} }
}, },
); );
this.eventBus.subscribe(
'open-popup-settings',
{
source: this,
function: (config) => {
this.selectTab(config.tab)
}
}
)
this.comms = new CommsClient('popup-port', this.logger, this.eventBus); this.comms = new CommsClient('popup-port', this.logger, this.eventBus);
this.eventBus.setComms(this.comms); this.eventBus.setComms(this.comms);
@ -288,6 +274,11 @@ export default {
try { try {
this.logger.log('info','popup', '[popup::getSite] Requesting current site ...') this.logger.log('info','popup', '[popup::getSite] Requesting current site ...')
// CSM.port.postMessage({command: 'get-current-site'}); // CSM.port.postMessage({command: 'get-current-site'});
this.eventBus.send(
'probe-video',
{},
{ comms: {forwardTo: 'active'} }
);
this.eventBus.send( this.eventBus.send(
'get-current-site', 'get-current-site',
{}, {},
@ -308,15 +299,13 @@ export default {
isDefaultFrame(frameId) { isDefaultFrame(frameId) {
return frameId === '__playing' || frameId === '__all'; return frameId === '__playing' || frameId === '__all';
}, },
loadHostnames() {
this.activeHosts = this.site.hostnames;
},
loadFrames() { loadFrames() {
this.activeFrames = [{ this.activeFrames = [{
host: this.site.host, host: this.site.host,
isIFrame: false, // not used tho. Maybe one day isIFrame: false, // not used tho. Maybe one day
}]; }];
for (const frame in this.site.frames) { for (const frame in this.site.frames) {
if (!this.activeFrames.find(x => x.host === this.site.frames[frame].host)) { if (!this.activeFrames.find(x => x.host === this.site.frames[frame].host)) {
this.activeFrames.push({ this.activeFrames.push({

View File

@ -367,10 +367,6 @@ button,
padding-right: 10px; padding-right: 10px;
} }
.info-button {
color: $info-color;
border: 1px solid $info-color;
}
.info { .info {
color: $info-color; color: $info-color;
padding-left: 35px; padding-left: 35px;

View File

@ -13,12 +13,12 @@
<small>{{ site }}</small> <small>{{ site }}</small>
</div> </div>
<div <div
v-if="hosts" v-if="frames"
class="tab" class="tab"
:class="{'active': tab === 'embeddedSites'}" :class="{'active': tab === 'embeddedSites'}"
@click="setTab(tab = 'embeddedSites')" @click="setTab(tab = 'embeddedSites')"
> >
Embedded content ({{hosts?.length}} {{hosts?.length === 1 ? 'site' : 'sites'}}) Embedded content
</div> </div>
<div <div
class="tab" class="tab"
@ -38,10 +38,10 @@
></SiteExtensionSettings> ></SiteExtensionSettings>
</template> </template>
<template v-if="hosts && tab === 'embeddedSites' && globalSettings"> <template v-if="frames && tab === 'embeddedSites' && globalSettings">
<FrameSiteSettings <FrameSiteSettings
v-if="settings" v-if="settings"
:hosts="hosts" :frames="frames"
:settings="settings" :settings="settings"
></FrameSiteSettings> ></FrameSiteSettings>
</template> </template>
@ -178,7 +178,7 @@ export default {
'settings', 'settings',
'site', 'site',
'enableSettingsEditor', 'enableSettingsEditor',
'hosts', 'frames',
], ],
data() { data() {
return { return {

View File

@ -9,9 +9,9 @@
</div> </div>
</div> </div>
</div> </div>
<div v-for="host of hosts" :key="host" @click="selectedSite = host" class="flex flex-col container pointer hoverable" style="margin-top: 4px; padding: 0.5rem 1rem;"> <div v-for="frame of frames" :key="frame.host" @click="selectedSite = frame.host" class="flex flex-col container pointer hoverable" style="margin-top: 4px; padding: 0.5rem 1rem;">
<SiteListItem <SiteListItem
:host="host" :frame="frame"
:settings="settings" :settings="settings"
></SiteListItem> ></SiteListItem>
</div> </div>
@ -48,7 +48,7 @@ export default {
}, },
props: [ props: [
'settings', 'settings',
'hosts', 'frames',
], ],
data() { data() {
return { return {

View File

@ -27,9 +27,7 @@
<b>NOTE:</b> Sites not on this list use default extension settings. <b>NOTE:</b> Sites not on this list use default extension settings.
</div> </div>
</div> </div>
<div class="w-full text-center" style="margin-bottom: -1.25rem"> <b>Other sites:</b>
<b>Other sites</b>
</div>
<div style="margin: 1rem 0rem" class="w-full"> <div style="margin: 1rem 0rem" class="w-full">
<div class="flex flex-row items-baseline"> <div class="flex flex-row items-baseline">
<div style="margin-right: 1rem">Search for site:</div> <div style="margin-right: 1rem">Search for site:</div>

View File

@ -2,9 +2,9 @@
<div> <div>
<div class="flex flex-row"> <div class="flex flex-row">
<div class="flex-grow pointer"> <div class="flex-grow pointer">
<b>{{ host }}</b> <b>{{ frame.host ?? frame.key }}</b>
<span :style="getSiteTypeColor(siteSettings?.data?.type)"> <span :style="getSiteTypeColor(frame.type)">
(config: {{siteSettings?.data?.type ?? 'unknown'}}) (config: {{frame.type ?? 'unknown'}})
</span> </span>
</div> </div>
<div>Edit</div> <div>Edit</div>
@ -15,10 +15,10 @@
</div> </div>
<div class="flex flex-row"> <div class="flex flex-row">
<small> <small>
Enabled: <span :style="getSiteEnabledColor(host, 'enable')"><small>{{ getSiteEnabledModes(host, 'enable') }}</small></span>;&nbsp; Enabled: <span :style="getSiteEnabledColor(frame.host, 'enable')"><small>{{ getSiteEnabledModes(frame.host, 'enable') }}</small></span>;&nbsp;
Aard <span :style="getSiteEnabledColor(host, 'enableAard')"><small>{{ getSiteEnabledModes(host, 'enableAard') }}</small></span>;&nbsp; Aard <span :style="getSiteEnabledColor(frame.host, 'enableAard')"><small>{{ getSiteEnabledModes(frame.host, 'enableAard') }}</small></span>;&nbsp;
kbd: <span :style="getSiteEnabledColor(host, 'enableKeyboard')"><small>{{ getSiteEnabledModes(host, 'enableKeyboard') }}</small></span> kbd: <span :style="getSiteEnabledColor(frame.host, 'enableKeyboard')"><small>{{ getSiteEnabledModes(frame.host, 'enableKeyboard') }}</small></span>
UI: <span :style="getSiteEnabledColor(host, 'enableUI')"><small>{{ getSiteEnabledModes(host, 'enableUI') }}</small></span> UI: <span :style="getSiteEnabledColor(frame.host, 'enableUI')"><small>{{ getSiteEnabledModes(frame.host, 'enableUI') }}</small></span>
</small> </small>
</div> </div>
</div> </div>
@ -29,16 +29,15 @@ import ExtensionMode from '../../../../../common/enums/ExtensionMode.enum';
export default { export default {
data() { data() {
return { return {
siteSettings: undefined, siteSettings: undefined
supportType: undefined
} }
}, },
props: [ props: [
'settings', 'settings',
'host', 'frame',
], ],
created() { created() {
this.siteSettings = this.settings.getSiteSettings(this.host); this.siteSettings = this.settings.getSiteSettings(this.frame.host ?? this.frame.key);
}, },
methods: { methods: {
getSiteTypeColor(siteType) { getSiteTypeColor(siteType) {

View File

@ -1,54 +1,21 @@
<template> <template>
<div class="flex flex-col relative h-full" style="padding-bottom: 20px"> <div class="flex flex-col relative h-full" style="padding-bottom: 20px">
<!-- <!--
Extension is disabled for a given site when it's disabled in full screen, since Extension is disabled for a given site when it's disabled in full screen, since
current settings do not allow the extension to only be disabled while in full screen current settings do not allow the extension to only be disabled while in full screen
--> -->
<template v-if="siteSettings.isEnabledForEnvironment(false, true) === ExtensionMode.Disabled && !enabledHosts?.length"> <template v-if="siteSettings.isEnabledForEnvironment(false, true) === ExtensionMode.Disabled">
<div class="h-full flex flex-col items-center justify-center" style="margin-top: 8rem"> <div class="h-full flex flex-col items-center justify-center">
<div class="info"> <div class="info">
Extension is not enabled for this site. Extension is not enabled for this site.
</div> </div>
<div> <div>
Please enable extension for this site. Please enable extension for this site.
</div> </div>
<div>
<button
class="flex flex-row items-center"
style="background-color: transparent; padding: 0.25rem 0.5rem; margin-top: 1rem;"
@click="openSettings()"
>
Open settings <mdicon style="margin-left: 0.5rem;" name="open-in-new" size="16"></mdicon>
</button>
</div>
</div> </div>
</template> </template>
<template v-else> <template v-else>
<div
v-if="siteSettings.isEnabledForEnvironment(false, true) === ExtensionMode.Disabled"
class="warning-compact"
>
<div class="w-full flex flex-row">
<div class="grow">
<b>Extension is disabled for this site.</b>
</div>
<div>
<button
class="flex flex-row items-center"
style="border: 1px solid black; background-color: transparent; color: black; padding: 0.25rem 0.5rem; margin-top: -0.25rem; margin-right: -0.5rem;"
@click="openSettings()"
>
Open settings <mdicon style="margin-left: 0.5rem;" name="open-in-new" size="16"></mdicon>
</button>
</div>
</div>
<small>Controls will only work on content embedded from the following sites:</small><br/>
<div class="w-full flex flex-row justify-center">
<span v-for="host of enabledHosts" :key="host" class="website-name">{{host}}</span>
</div>
</div>
<div class="flex flex-row"> <div class="flex flex-row">
<mdicon name="crop" :size="16" />&nbsp;&nbsp; <mdicon name="crop" :size="16" />&nbsp;&nbsp;
<span>CROP</span> <span>CROP</span>
@ -123,7 +90,6 @@ import StretchOptionsPanel from '@csui/src/PlayerUiPanels/PanelComponents/VideoS
import ZoomOptionsPanel from '@csui/src/PlayerUiPanels/PanelComponents/VideoSettings/ZoomOptionsPanel.vue'; import ZoomOptionsPanel from '@csui/src/PlayerUiPanels/PanelComponents/VideoSettings/ZoomOptionsPanel.vue';
import ExtensionMode from '@src/common/enums/ExtensionMode.enum.ts'; import ExtensionMode from '@src/common/enums/ExtensionMode.enum.ts';
import AlignmentOptionsControlComponent from '@csui/src/PlayerUiPanels/AlignmentOptionsControlComponent.vue'; import AlignmentOptionsControlComponent from '@csui/src/PlayerUiPanels/AlignmentOptionsControlComponent.vue';
import { SiteSettings } from '../../../../ext/lib/settings/SiteSettings';
export default { export default {
components: { components: {
@ -136,24 +102,16 @@ export default {
], ],
props: [ props: [
'site',
'settings', 'settings',
'siteSettings', 'siteSettings',
'eventBus', 'eventBus',
'hosts'
], ],
data() { data() {
return { return {
exec: null, exec: null,
ExtensionMode: ExtensionMode, ExtensionMode: ExtensionMode,
enabledHosts: [],
}; };
}, },
watch: {
hosts(val) {
this.filterActiveSites(val);
}
},
created() { created() {
this.eventBus.subscribe( this.eventBus.subscribe(
'uw-config-broadcast', 'uw-config-broadcast',
@ -162,7 +120,6 @@ export default {
function: (config) => this.handleConfigBroadcast(config) function: (config) => this.handleConfigBroadcast(config)
} }
); );
this.filterActiveSites(this.hosts);
}, },
mounted() { mounted() {
this.eventBus.sendToTunnel('get-ar'); this.eventBus.sendToTunnel('get-ar');
@ -171,37 +128,8 @@ export default {
this.eventBus.unsubscribeAll(this); this.eventBus.unsubscribeAll(this);
}, },
methods: { methods: {
filterActiveSites(val) {
this.enabledHosts = [];
for (const host of val) {
const siteSettings = new SiteSettings(this.settings, host);
if (siteSettings.isEnabledForEnvironment(false, true) === ExtensionMode.Enabled) {
this.enabledHosts.push(host);
}
}
},
openSettings() {
this.eventBus.send('open-popup-settings', {tab: 'extensionSettings'})
}
} }
} }
</script> </script>
<style lang="scss" scoped>
.warning-compact {
background-color: #d6ba4a;
color: #000;
padding: 0.5rem 1rem;
margin-top: -0.5rem;
margin-bottom: 0.5rem;
.website-name {
font-size: 0.85rem;
&:not(:last-of-type)::after {
content: ','
}
}
}
</style>

View File

@ -93,16 +93,12 @@ export default class UWServer {
} }
} }
async _promisifyTabsGet(browserObj, tabId){ async _promisifyTabsGet(browserObj, tabId){
return new Promise( (resolve, reject) => { return new Promise( (resolve, reject) => {
browserObj.tabs.get(tabId, (tab) => resolve(tab)); browserObj.tabs.get(tabId, (tab) => resolve(tab));
}); });
} }
//#region CSS managemeent
async injectCss(css, sender) { async injectCss(css, sender) {
if (!css) { if (!css) {
return; return;
@ -171,7 +167,6 @@ export default class UWServer {
this.injectCss(newCss, sender); this.injectCss(newCss, sender);
} }
} }
//#endregion
extractHostname(url){ extractHostname(url){
var hostname; var hostname;
@ -219,6 +214,7 @@ export default class UWServer {
} }
//TODO: change extension icon based on whether there's any videos on current page //TODO: change extension icon based on whether there's any videos on current page
} }
registerVideo(sender) { registerVideo(sender) {
@ -292,6 +288,7 @@ export default class UWServer {
const tabHostname = await this.getCurrentTabHostname(); const tabHostname = await this.getCurrentTabHostname();
this.logger.info('getCurrentSite', 'Returning data:', {site, tabHostname}); this.logger.info('getCurrentSite', 'Returning data:', {site, tabHostname});
this.eventBus.send( this.eventBus.send(
'set-current-site', 'set-current-site',
{ {
@ -321,12 +318,9 @@ export default class UWServer {
return { return {
host: 'INVALID SITE', host: 'INVALID SITE',
frames: [], frames: [],
hostnames: [],
} }
} }
const hostnames = await this.comms.listUniqueFrameHosts();
if (this.videoTabs[ctab.id]) { if (this.videoTabs[ctab.id]) {
// if video is older than PageInfo's video rescan period (+ 4000ms of grace), // if video is older than PageInfo's video rescan period (+ 4000ms of grace),
// we clean it up from videoTabs[tabId].frames array. // we clean it up from videoTabs[tabId].frames array.
@ -349,7 +343,6 @@ export default class UWServer {
return { return {
...this.videoTabs[ctab.id], ...this.videoTabs[ctab.id],
host: this.extractHostname(ctab.url), host: this.extractHostname(ctab.url),
hostnames,
selected: this.selectedSubitem selected: this.selectedSubitem
}; };
} }
@ -359,8 +352,7 @@ export default class UWServer {
return { return {
host: this.extractHostname(ctab.url), host: this.extractHostname(ctab.url),
frames: [], frames: [],
hostnames, selected: this.selectedSubitem
selected: this.selectedSubitem,
} }
} }

View File

@ -122,36 +122,6 @@ class CommsServer {
//#endregion //#endregion
/**
* Lists all unique hosts that are present in all the frames of a given tab.
* This includes both hostname of the tab, as well as of all iframes embedded in it.
* @returns
*/
async listUniqueFrameHosts() {
const aTab = await this.activeTab;
const tabPort = this.ports[aTab.id];
const hosts = [];
for (const frame in tabPort) {
for (const portName in tabPort[frame]) {
const port = tabPort[frame][portName];
const host = port.sender.origin.split('://')[1];
// if host is invalid or already exists in our list, skip adding it
if (!host || hosts.includes(host)) {
continue;
}
hosts.push(host);
}
}
console.log('uniq hosts:', hosts)
return hosts;
}
sendMessage(message, context?) { sendMessage(message, context?) {
this.logger.debug('sendMessage', `preparing to send message ${message.command ?? ''} ...`, {message, context}); this.logger.debug('sendMessage', `preparing to send message ${message.command ?? ''} ...`, {message, context});
// stop messages from returning where they came from, and prevent // stop messages from returning where they came from, and prevent

View File

@ -69,7 +69,6 @@ class PageInfo {
keyboardHandler: any; keyboardHandler: any;
fsStatus = {fullscreen: true}; // fsStatus needs to be passed to VideoData, so fullScreen property is shared between videoData instances fsStatus = {fullscreen: true}; // fsStatus needs to be passed to VideoData, so fullScreen property is shared between videoData instances
isIframe: boolean = false;
//#endregion //#endregion
fsEventListener = { fsEventListener = {
@ -79,9 +78,7 @@ class PageInfo {
} }
}; };
constructor(eventBus: EventBus, siteSettings: SiteSettings, settings: Settings, logAggregator: LogAggregator, readOnly = false) { constructor(eventBus: EventBus, siteSettings: SiteSettings, settings: Settings, logAggregator: LogAggregator, readOnly = false){
this.isIframe = window.self !== window.top;
this.logAggregator = logAggregator; this.logAggregator = logAggregator;
this.logger = new ComponentLogger(logAggregator, 'PageInfo', {}); this.logger = new ComponentLogger(logAggregator, 'PageInfo', {});
this.settings = settings; this.settings = settings;
@ -115,11 +112,10 @@ class PageInfo {
this.eventBus.subscribeMulti({ this.eventBus.subscribeMulti({
'probe-video': { 'probe-video': {
function: () => { function: () => {
console.log(`[${window.location}] probe-video received.`) console.warn('[uw] probe-video event received..');
this.rescan();
} }
} }
}); })
} }
destroy() { destroy() {
@ -190,62 +186,106 @@ class PageInfo {
} }
} }
/** getVideos(): HTMLVideoElement[] {
* Returns all videos on the page.
*
* If minSize is provided, it only returns <video> elements that are
* equal or bigger than desired size:
*
* * sm: 320 x 180
* * md: 720 x 400
* * lg: 1280 x 720
*
* If minSize is omitted, it returns all <video> elements.
* @param minSize
* @returns
*/
getAllVideos(minSize?: 'sm' | 'md' | 'lg') {
const videoQs = this.siteSettings.getCustomDOMQuerySelector('video'); const videoQs = this.siteSettings.getCustomDOMQuerySelector('video');
let videos: HTMLVideoElement[] = []; let videos: HTMLVideoElement[] = [];
if (videoQs){ if (videoQs){
videos = Array.from(document.querySelectorAll(videoQs) as NodeListOf<HTMLVideoElement> ?? []); videos = Array.from(document.querySelectorAll(videoQs) as NodeListOf<HTMLVideoElement> ?? []);
} else { } else{
videos = Array.from(document.getElementsByTagName('video') ?? []); videos = Array.from(document.getElementsByTagName('video') ?? []);
} }
if (!minSize) {
return videos;
}
return this.filterVideos(videos, minSize);
}
filterVideos(videos: HTMLVideoElement[], minSize: 'sm' | 'md' | 'lg') {
// minimums are determined by vibes and shit.
// 'sm' is based on "slightly smaller than embeds on old.reddit"
const minX = { sm: 320, md: 720, lg: 1280 };
const minY = { sm: 180, md: 400, lg: 720 };
// filter out videos that aren't big enough // filter out videos that aren't big enough
return videos.filter( videos = videos.filter(
(v: HTMLVideoElement) => v.clientHeight >= minY[minSize] && v.clientWidth >= minX[minSize] (v: HTMLVideoElement) => v.clientHeight > 720 && v.clientWidth > 1208
); );
}
/** return videos;
* Gets videos on the page that are big enough for extension to trigger
* @returns
*/
getVideos(): HTMLVideoElement[] {
return this.getAllVideos('lg');
} }
hasVideo() { hasVideo() {
return this.readOnly ? this.hasVideos : this.videos.length; return this.readOnly ? this.hasVideos : this.videos.length;
} }
private emitVideoStatus(videosDetected?: boolean) { /**
* Re-scans the page for videos. Removes any videos that no longer exist from our list
* of videos. Destroys all videoData objects for all the videos that don't have their
* own <video> html element on the page.
* @param rescanReason Why was the rescan triggered. Mostly used for logging.
* @returns
*/
rescan(rescanReason?: RescanReason){
// is there any video data objects that had their HTML elements removed but not yet
// destroyed? We clean that up here.
const orphans = this.videos.filter(x => !document.body.contains(x.element));
for (const orphan of orphans) {
orphan.videoData.destroy();
}
// remove all destroyed videos.
this.videos = this.videos.filter(x => !x.videoData.destroyed);
// add new videos
try{
let vids = this.getVideos();
if(!vids || vids.length == 0){
this.hasVideos = false;
if(rescanReason == RescanReason.PERIODIC){
this.logger.info({src: 'rescan', origin: 'videoRescan'}, "Scheduling normal rescan.")
this.scheduleRescan(RescanReason.PERIODIC);
}
return;
}
// add new videos
this.hasVideos = false;
let videoExists = false;
for (const videoElement of vids) {
// do not re-add videos that we already track:
if (this.videos.find(x => x.element.isEqualNode(videoElement))) {
continue;
}
// if we find even a single video with width and height, that means the page has valid videos
// if video lacks either of the two properties, we skip all further checks cos pointless
if(!videoElement.offsetWidth || !videoElement.offsetHeight) {
continue;
}
// at this point, we're certain that we found new videos. Let's update some properties:
this.hasVideos = true;
// if PageInfo is marked as "readOnly", we actually aren't adding any videos to anything because
// that's super haram. We're only interested in whether
if (this.readOnly) {
// in lite mode, we're done. This is all the info we want, but we want to actually start doing
// things that interfere with the website. We still want to be running a rescan, tho.
if(rescanReason == RescanReason.PERIODIC){
this.scheduleRescan(RescanReason.PERIODIC);
}
return;
}
this.logger.info({src: 'rescan', origin: 'videoRescan'}, "found new video candidate:", videoElement, "NOTE:: Video initialization starts here:\n--------------------------------\n")
try {
const newVideo = new VideoData(videoElement, this.settings, this.siteSettings, this);
this.videos.push({videoData: newVideo, element: videoElement});
} catch (e) {
this.logger.error('rescan', "rescan error: failed to initialize videoData. Skipping this video.",e);
}
this.logger.info({src: 'rescan', origin: 'videoRescan'}, "END VIDEO INITIALIZATION\n\n\n-------------------------------------\nvideos[] is now this:", this.videos,"\n\n\n\n\n\n\n\n")
}
this.removeDestroyed();
// if we're left without videos on the current page, we unregister the page. // if we're left without videos on the current page, we unregister the page.
// if we have videos, we call register. // if we have videos, we call register.
if (this.eventBus) { if (this.eventBus) {
@ -263,105 +303,19 @@ class PageInfo {
// things in the less-than-optimal. more-than-retarded way. // things in the less-than-optimal. more-than-retarded way.
// //
// no but honestly fuck Chrome. // no but honestly fuck Chrome.
if (videosDetected || this.hasVideo()) {
// if (this.videos.length != oldVideoCount) {
// }
if (this.videos.length > 0) {
// this.comms.registerVideo({host: window.location.hostname, location: window.location});
this.eventBus.send('has-video', null); this.eventBus.send('has-video', null);
} else { } else {
// this.comms.unregisterVideo({host: window.location.hostname, location: window.location});
this.eventBus.send('noVideo', null); this.eventBus.send('noVideo', null);
} }
} }
}
/**
* Re-scans the page for videos. Removes any videos that no longer exist from our list
* of videos. Destroys all videoData objects for all the videos that don't have their
* own <video> html element on the page.
* @param rescanReason Why was the rescan triggered. Mostly used for logging.
* @returns
*/
rescan(rescanReason?: RescanReason){
let videosDetected = false;
// is there any video data objects that had their HTML elements removed but not yet
// destroyed? We clean that up here.
const orphans = this.videos.filter(x => !document.body.contains(x.element));
for (const orphan of orphans) {
orphan.videoData.destroy();
}
// remove all destroyed videos.
this.videos = this.videos.filter(x => !x.videoData.destroyed);
// add new videos
try {
// in iframes, emit registerIframe even if video is smaller than required
let vids = this.getAllVideos('sm');
if (this.isIframe && this.eventBus) {
videosDetected ||= vids?.length > 0;
};
// for normal operations, use standard size limits
vids = this.filterVideos(vids, 'lg');
if(!vids || vids.length == 0){
this.hasVideos = false;
if(rescanReason == RescanReason.PERIODIC){
this.logger.info({src: 'rescan', origin: 'videoRescan'}, "Scheduling normal rescan.")
this.scheduleRescan(RescanReason.PERIODIC);
}
this.emitVideoStatus(videosDetected);
return;
}
// add new videos
this.hasVideos = false;
for (const videoElement of vids) {
// do not re-add videos that we already track:
if (this.videos.find(x => x.element.isEqualNode(videoElement))) {
continue;
}
// if we find even a single video with width and height, that means the page has valid videos
// if video lacks either of the two properties, we skip all further checks cos pointless
if(!videoElement.offsetWidth || !videoElement.offsetHeight) {
continue;
}
// at this point, we're certain that we found new videos. Let's update some properties:
this.hasVideos = true;
videosDetected ||= true;
// if PageInfo is marked as "readOnly", we actually aren't adding any videos to anything because
// that's super haram. We're only interested in whether
if (this.readOnly) {
// in lite mode, we're done. This is all the info we want, but we want to actually start doing
// things that interfere with the website. We still want to be running a rescan, tho.
if(rescanReason == RescanReason.PERIODIC){
this.scheduleRescan(RescanReason.PERIODIC);
}
this.emitVideoStatus(videosDetected);
return;
}
this.logger.info({src: 'rescan', origin: 'videoRescan'}, "found new video candidate:", videoElement, "NOTE:: Video initialization starts here:\n--------------------------------\n")
try {
const newVideo = new VideoData(videoElement, this.settings, this.siteSettings, this);
this.videos.push({videoData: newVideo, element: videoElement});
} catch (e) {
this.logger.error('rescan', "rescan error: failed to initialize videoData. Skipping this video.",e);
}
this.logger.info({src: 'rescan', origin: 'videoRescan'}, "END VIDEO INITIALIZATION\n\n\n-------------------------------------\nvideos[] is now this:", this.videos,"\n\n\n\n\n\n\n\n")
}
this.removeDestroyed();
this.emitVideoStatus(videosDetected);
} catch(e) { } catch(e) {
// if we encounter a fuckup, we can assume that no videos were found on the page. We destroy all videoData // if we encounter a fuckup, we can assume that no videos were found on the page. We destroy all videoData
// objects to prevent multiple initialization (which happened, but I don't know why). No biggie if we destroyed // objects to prevent multiple initialization (which happened, but I don't know why). No biggie if we destroyed

View File

@ -5,18 +5,17 @@
import UWContent from './UWContent'; import UWContent from './UWContent';
if(process.env.CHANNEL !== 'stable'){ if(process.env.CHANNEL !== 'stable'){
console.warn("\n\n\n\n\n\n ——— Sᴛλʀᴛɪɴɢ Uʟᴛʀᴀɪɪʏ ———\n << ʟᴏᴀᴅɪɴɢ ᴍᴀɪɴ ꜰɪʟᴇ >>\n\n\n\n");
let isIframe;
try { try {
isIframe = window.self !== window.top; if(window.self !== window.top){
} catch (e) { console.info("%cWe aren't in an iframe.", "color: #afc, background: #174");
isIframe = true; }
else{
console.info("%cWe are in an iframe!", "color: #fea, background: #d31", window.self, window.top);
}
} catch (e) {
console.info("%cWe are in an iframe!", "color: #fea, background: #d31");
} }
console.warn(
"\n\n\n\n\n\n ——— Sᴛλʀᴛɪɴɢ Uʟᴛʀᴀɪɪʏ ———\n << ʟᴏᴀᴅɪɴɢ ᴍᴀɪɴ ꜰɪʟᴇ >>\n\n\n\n",
"\n - are we in iframe?", isIframe
);
} }
const main = new UWContent(); const main = new UWContent();