From 9c26d553f56317ae747f74dc8126a35199e8bebd Mon Sep 17 00:00:00 2001 From: Shiba <44804845+DeepDoge@users.noreply.github.com> Date: Tue, 9 Aug 2022 21:16:05 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=8D=A3=20major=20changes=20-=20modes=20ar?= =?UTF-8?q?e=20removed=20-=20added=20more=20options=20for=20redirect=20-?= =?UTF-8?q?=20extension=20badge=20removed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/popup/main.tsx | 187 +++++++++++++++++---------------- src/pages/popup/style.css | 5 + src/scripts/ytContent.tsx | 210 ++++++++++++++++++++----------------- src/settings/background.ts | 6 +- src/settings/index.ts | 22 ++-- 5 files changed, 234 insertions(+), 196 deletions(-) diff --git a/src/pages/popup/main.tsx b/src/pages/popup/main.tsx index abd0562..f1e8197 100644 --- a/src/pages/popup/main.tsx +++ b/src/pages/popup/main.tsx @@ -12,9 +12,9 @@ const targetPlatforms = getTargetPlatfromSettingsEntiries() const ytUrlResolverOptions = getYtUrlResolversSettingsEntiries() function WatchOnLbryPopup(params: { profile: Awaited> | null }) { - const { redirect, targetPlatform, urlResolver, videoSubButton, channelSubButton, videoPlayerButton, privateKey, publicKey } = useExtensionSettings() + const { targetPlatform, urlResolver, redirectChannel, redirectVideo, redirectVideoPlaylist, buttonVideoSub, buttonChannelSub, buttonVideoPlayer, privateKey, publicKey } = useExtensionSettings() let [loading, updateLoading] = useState(() => false) - let [route, updateRoute] = useState(() => null) + let [route, updateRoute] = useState(() => '') const dialogManager = createDialogManager() const nickname = params.profile ? params.profile.nickname ?? 'No Nickname' : '...' @@ -35,29 +35,30 @@ function WatchOnLbryPopup(params: { profile: Awaited { - publicKey - ?
+ +
+ { + publicKey &&

{friendlyPublicKey(publicKey)}

Score: {params.profile?.score ?? '...'} - 🔗Leaderboard {urlResolver !== 'madiatorFinder' && You need to use Madiator Finder API for scoring to work}
-
- { - route === 'profile' - ? updateRoute('')} className="filled">⇐ Back - : updateRoute('profile')} href="#profile">Profile Settings - } -
-
- :
- { - route === 'profile' - ? updateRoute('')} className="filled">⇐ Back - : updateRoute('profile')} href="#profile">Profile Settings - } -
+ } + + { + route !== '' + ? +
+ updateRoute('')} className="filled">⇐ Back +
+ : +
+ updateRoute('profile')}>Profile Settings +
+ } +
} { route === 'profile' ? @@ -138,80 +139,88 @@ function WatchOnLbryPopup(params: { profile: Awaited : -
-
- - -
- { - !redirect && + route === 'advanced' ? +
- - Video + - - Channel -
- } -
- - -
-
- - - loads(lbryUrlCache.clearAll().then(() => dialogManager.alert("Cleared Cache!")))} className={`button active`}> - Clear Resolver Cache - -
-
- - - Subscription Converter - -
-
+
+ + + loads(lbryUrlCache.clearAll().then(() => dialogManager.alert("Cleared Cache!")))} className={`button active`}> + Clear Resolver Cache + +
+
+ : +
+
+ + +
+
+ + +
+
+ + + Subscription Converter + + updateRoute('advanced')}>Advanced Settings +
+
} {loading &&
Loading... diff --git a/src/pages/popup/style.css b/src/pages/popup/style.css index 3b0bd64..987f35b 100644 --- a/src/pages/popup/style.css +++ b/src/pages/popup/style.css @@ -54,4 +54,9 @@ section>* { justify-items: start; align-items: center; text-align: left; +} + +.toggle-option { + display: grid; + gap: .5em; } \ No newline at end of file diff --git a/src/scripts/ytContent.tsx b/src/scripts/ytContent.tsx index 23abe2a..67455e4 100644 --- a/src/scripts/ytContent.tsx +++ b/src/scripts/ytContent.tsx @@ -17,6 +17,7 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa platform: SourcePlatform id: string type: ResolveUrlTypes + url: URL time: number | null } @@ -26,7 +27,6 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa chrome.storage.onChanged.addListener(async (changes, areaName) => { if (areaName !== 'local') return Object.assign(settings, Object.fromEntries(Object.entries(changes).map(([key, change]) => [key, change.newValue]))) - if (settings.redirect) updateButton(null) }) const buttonMountPoint = document.createElement('div') @@ -112,7 +112,7 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa
} - function updateButton(params: { source: Source, target: Target } | null): void { + function updateButtons(params: { source: Source, target: Target } | null): void { if (!params) { render(, buttonMountPoint) render(, playerButtonMountPoint) @@ -120,7 +120,7 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa } { - const mountPlayerButtonBefore = settings.videoPlayerButton ? + const mountPlayerButtonBefore = settings.buttonVideoPlayer ? document.querySelector(params.source.platform.htmlQueries.mountPoints.mountPlayerButtonBefore) : null if (!mountPlayerButtonBefore) render(, playerButtonMountPoint) @@ -134,7 +134,7 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa } { - const mountButtonBefore = settings[(`${params.source.type}SubButton`) as 'videoSubButton' | 'channelSubButton'] ? + const mountButtonBefore = settings[(`button${params.source.type[0].toUpperCase() + params.source.type.substring(1)}Sub`) as 'buttonVideoSub' | 'buttonChannelSub'] ? document.querySelector(params.source.platform.htmlQueries.mountPoints.mountButtonBefore[params.source.type]) : null if (!mountButtonBefore) render(, buttonMountPoint) @@ -163,7 +163,8 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa id: url.searchParams.get('v')!, platform, time: url.searchParams.has('t') ? parseYouTubeURLTimeString(url.searchParams.get('t')!) : null, - type: 'video' + type: 'video', + url } } else if (url.pathname.startsWith('/channel/')) { @@ -171,7 +172,8 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa id: url.pathname.substring("/channel/".length), platform, time: null, - type: 'channel' + type: 'channel', + url } } else if (url.pathname.startsWith('/c/') || url.pathname.startsWith('/user/')) { @@ -187,7 +189,8 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa id, platform, time: null, - type: 'channel' + type: 'channel', + url } } @@ -233,9 +236,47 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa } // Request new tab - async function openNewTab(url: URL, active: boolean) { + async function openNewTab(url: URL) { if (!open(url.href, '_blank')) - chrome.runtime.sendMessage({ method: 'openTab', data: JSON.stringify({ href: url.href, active }) }) + chrome.runtime.sendMessage({ method: 'openTab', data: JSON.stringify({ href: url.href, active: document.hasFocus() }) }) + } + + function findTargetFromSourcePage(source: Source): Target | null { + const linksContainer = + source.type === 'video' ? + document.querySelector(source.platform.htmlQueries.videoDescription) : + source.platform.htmlQueries.channelLinks ? document.querySelector(source.platform.htmlQueries.channelLinks) : null + + if (linksContainer) { + const anchors = Array.from(linksContainer.querySelectorAll('a')) + + for (const anchor of anchors) { + if (!anchor.href) continue + const url = new URL(anchor.href) + let lbryURL: URL | null = null + + // Extract real link from youtube's redirect link + if (source.platform === sourcePlatfromSettings['youtube.com']) { + if (!targetPlatforms.some(([key, platform]) => url.searchParams.get('q')?.startsWith(platform.domainPrefix))) continue + lbryURL = new URL(url.searchParams.get('q')!) + } + // Just directly use the link itself on other platforms + else { + if (!targetPlatforms.some(([key, platform]) => url.href.startsWith(platform.domainPrefix))) continue + lbryURL = new URL(url.href) + } + + if (lbryURL) { + return { + lbryPathname: lbryURL.pathname.substring(1), + time: null, + type: lbryURL.pathname.substring(1).includes('/') ? 'video' : 'channel', + platform: targetPlatformSettings[settings.targetPlatform] + } + } + } + } + return null } function getLbryUrlByTarget(target: Target) { @@ -245,104 +286,83 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa return url } - let urlHrefCache: string | null = null - while (true) { + + // Master Loop + for ( + let url = new URL(location.href), + urlHrefCache: string | null = null; + ; + urlHrefCache = url.href, + url = new URL(location.href) + ) { await sleep(500) - const url: URL = new URL(location.href) - - await (async () => { + try { const source = await getSourceByUrl(new URL(location.href)) - if (!source) return + if (!source) { + updateButtons(null) + continue + } + const target = (await getTargetsBySources(source))[source.id] ?? findTargetFromSourcePage(source) + if (!target) { + updateButtons(null) + continue + } - try { - if (settings.redirect) { - const target = (await getTargetsBySources(source))[source.id] - if (!target) return - if (url.href === urlHrefCache) return + // Update Buttons + if (urlHrefCache !== url.href) updateButtons(null) + // If target is a video target add timestampt to it + if (target.type === 'video') { + const videoElement = document.querySelector(source.platform.htmlQueries.videoPlayer) + if (videoElement) target.time = videoElement.currentTime > 3 && videoElement.currentTime < videoElement.duration - 1 ? videoElement.currentTime : null + } + updateButtons({ target, source }) - const lbryURL = getLbryUrlByTarget(target) + // Redirect + if ( + source.type === target.type && + ( + ( + settings.redirectVideo && + source.type === 'video' && !source.url.searchParams.has('list') + ) || + ( + settings.redirectVideoPlaylist && + source.type === 'video' && source.url.searchParams.has('list') + ) || + ( + settings.redirectChannel && + source.type === 'channel' + ) + ) + ) { + if (url.href === urlHrefCache) continue - if (source.type === 'video') { - // As soon as video play is ready and start playing, pause it. - findVideoElementAwait(source).then((videoElement) => { - videoElement.addEventListener('play', () => videoElement.pause(), { once: true }) - videoElement.pause() - }) - } + const lbryURL = getLbryUrlByTarget(target) - if (target.platform === targetPlatformSettings.app) { - if (document.hidden) await new Promise((resolve) => document.addEventListener('visibilitychange', resolve, { once: true })) - // Replace is being used so browser doesnt start an empty window - // Its not gonna be able to replace anyway, since its a LBRY Uri - location.replace(lbryURL) - } - else { - openNewTab(lbryURL, document.hasFocus()) + if (source.type === 'video') { + // As soon as video play is ready and start playing, pause it. + findVideoElementAwait(source).then((videoElement) => { + videoElement.addEventListener('play', () => videoElement.pause(), { once: true }) + videoElement.pause() + }) + } - if (window.history.length === 1) window.close() - else window.history.back() - } + if (target.platform === targetPlatformSettings.app) { + if (document.hidden) await new Promise((resolve) => document.addEventListener('visibilitychange', resolve, { once: true })) + // Replace is being used so browser doesnt start an empty window + // Its not gonna be able to replace anyway, since its a LBRY Uri + location.replace(lbryURL) } else { - if (urlHrefCache !== url.href) updateButton(null) - let target = (await getTargetsBySources(source))[source.id] + openNewTab(lbryURL) - // There is no target found via API try to check Video Description for LBRY links. - if (!target) { - const linksContainer = - source.type === 'video' ? - document.querySelector(source.platform.htmlQueries.videoDescription) : - source.platform.htmlQueries.channelLinks ? document.querySelector(source.platform.htmlQueries.channelLinks) : null - - if (linksContainer) { - const anchors = Array.from(linksContainer.querySelectorAll('a')) - - for (const anchor of anchors) { - if (!anchor.href) continue - const url = new URL(anchor.href) - let lbryURL: URL | null = null - - // Extract real link from youtube's redirect link - if (source.platform === sourcePlatfromSettings['youtube.com']) { - if (!targetPlatforms.some(([key, platform]) => url.searchParams.get('q')?.startsWith(platform.domainPrefix))) continue - lbryURL = new URL(url.searchParams.get('q')!) - } - // Just directly use the link itself on other platforms - else { - if (!targetPlatforms.some(([key, platform]) => url.href.startsWith(platform.domainPrefix))) continue - lbryURL = new URL(url.href) - } - - if (lbryURL) { - target = { - lbryPathname: lbryURL.pathname.substring(1), - time: null, - type: lbryURL.pathname.substring(1).includes('/') ? 'video' : 'channel', - platform: targetPlatformSettings[settings.targetPlatform] - } - break - } - } - } - } - - if (!target) updateButton(null) - else { - // If target is a video target add timestampt to it - if (target.type === 'video') { - const videoElement = document.querySelector(source.platform.htmlQueries.videoPlayer) - if (videoElement) target.time = videoElement.currentTime > 3 && videoElement.currentTime < videoElement.duration - 1 ? videoElement.currentTime : null - } - - updateButton({ target, source }) - } + if (window.history.length === 1) window.close() + else window.history.back() } - } catch (error) { - console.error(error) } - })() - - urlHrefCache = url.href + } catch (error) { + console.error(error) + } } })() \ No newline at end of file diff --git a/src/settings/background.ts b/src/settings/background.ts index 910c8ac..a522e1c 100644 --- a/src/settings/background.ts +++ b/src/settings/background.ts @@ -21,13 +21,13 @@ async function initSettings() { if (!Object.keys(targetPlatformSettings).includes(settings.targetPlatform)) setExtensionSetting('targetPlatform', DEFAULT_SETTINGS.targetPlatform) if (!Object.keys(ytUrlResolversSettings).includes(settings.urlResolver)) setExtensionSetting('urlResolver', DEFAULT_SETTINGS.urlResolver) - chromeAction.setBadgeText({ text: settings.redirect ? 'ON' : 'OFF' }) + // chromeAction.setBadgeText({ text: settings.redirect ? 'ON' : 'OFF' }) } -chrome.storage.onChanged.addListener((changes, areaName) => { +/* chrome.storage.onChanged.addListener((changes, areaName) => { if (areaName !== 'local' || !changes.redirect) return chromeAction.setBadgeText({ text: changes.redirect.newValue ? 'ON' : 'OFF' }) -}) +}) */ chrome.runtime.onStartup.addListener(initSettings) chrome.runtime.onInstalled.addListener(initSettings) \ No newline at end of file diff --git a/src/settings/index.ts b/src/settings/index.ts index e32e92c..69354ff 100644 --- a/src/settings/index.ts +++ b/src/settings/index.ts @@ -2,24 +2,28 @@ import type { JSX } from "preact" import { useEffect, useReducer } from "preact/hooks" import type { ResolveUrlTypes } from "../modules/yt/urlResolve" -export interface ExtensionSettings { - redirect: boolean +export interface ExtensionSettings extends Record{ targetPlatform: TargetPlatformName urlResolver: YTUrlResolverName, - videoSubButton: boolean - videoPlayerButton: boolean - channelSubButton: boolean + redirectVideo: boolean, + redirectChannel: boolean, + redirectVideoPlaylist: boolean, + buttonVideoSub: boolean + buttonVideoPlayer: boolean + buttonChannelSub: boolean publicKey: string | null, privateKey: string | null } export const DEFAULT_SETTINGS: ExtensionSettings = { - redirect: true, targetPlatform: 'odysee', urlResolver: 'odyseeApi', - videoSubButton: true, - videoPlayerButton: true, - channelSubButton: true, + redirectVideo: false, + redirectChannel: false, + redirectVideoPlaylist: false, + buttonVideoSub: true, + buttonVideoPlayer: true, + buttonChannelSub: true, privateKey: null, publicKey: null }