mirror of
https://github.com/LBRYFoundation/Watch-on-LBRY.git
synced 2025-08-23 17:47:26 +00:00
🍣 major changes
- modes are removed - added more options for redirect - extension badge removed
This commit is contained in:
parent
9ed962df96
commit
9c26d553f5
5 changed files with 234 additions and 196 deletions
|
@ -12,9 +12,9 @@ const targetPlatforms = getTargetPlatfromSettingsEntiries()
|
||||||
const ytUrlResolverOptions = getYtUrlResolversSettingsEntiries()
|
const ytUrlResolverOptions = getYtUrlResolversSettingsEntiries()
|
||||||
|
|
||||||
function WatchOnLbryPopup(params: { profile: Awaited<ReturnType<typeof getProfile>> | null }) {
|
function WatchOnLbryPopup(params: { profile: Awaited<ReturnType<typeof getProfile>> | 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 [loading, updateLoading] = useState(() => false)
|
||||||
let [route, updateRoute] = useState<string | null>(() => null)
|
let [route, updateRoute] = useState<string>(() => '')
|
||||||
|
|
||||||
const dialogManager = createDialogManager()
|
const dialogManager = createDialogManager()
|
||||||
const nickname = params.profile ? params.profile.nickname ?? 'No Nickname' : '...'
|
const nickname = params.profile ? params.profile.nickname ?? 'No Nickname' : '...'
|
||||||
|
@ -35,29 +35,30 @@ function WatchOnLbryPopup(params: { profile: Awaited<ReturnType<typeof getProfil
|
||||||
return <div id='popup'>
|
return <div id='popup'>
|
||||||
<Dialogs manager={dialogManager} />
|
<Dialogs manager={dialogManager} />
|
||||||
{
|
{
|
||||||
publicKey
|
|
||||||
? <header>
|
<header>
|
||||||
|
{
|
||||||
|
publicKey &&
|
||||||
<section>
|
<section>
|
||||||
<label>{nickname}</label>
|
<label>{nickname}</label>
|
||||||
<p>{friendlyPublicKey(publicKey)}</p>
|
<p>{friendlyPublicKey(publicKey)}</p>
|
||||||
<span><b>Score: {params.profile?.score ?? '...'}</b> - <a target='_blank' href="https://finder.madiator.com/leaderboard" class="filled">🔗Leaderboard</a></span>
|
<span><b>Score: {params.profile?.score ?? '...'}</b> - <a target='_blank' href="https://finder.madiator.com/leaderboard" class="filled">🔗Leaderboard</a></span>
|
||||||
{urlResolver !== 'madiatorFinder' && <span class="error">You need to use Madiator Finder API for scoring to work</span>}
|
{urlResolver !== 'madiatorFinder' && <span class="error">You need to use Madiator Finder API for scoring to work</span>}
|
||||||
</section>
|
</section>
|
||||||
<section>
|
}
|
||||||
{
|
|
||||||
route === 'profile'
|
{
|
||||||
? <a onClick={() => updateRoute('')} className="filled">⇐ Back</a>
|
route !== ''
|
||||||
: <a className='filled' onClick={() => updateRoute('profile')} href="#profile">Profile Settings</a>
|
?
|
||||||
}
|
<section>
|
||||||
</section>
|
<a onClick={() => updateRoute('')} className="filled">⇐ Back</a>
|
||||||
</header>
|
</section>
|
||||||
: <header>
|
:
|
||||||
{
|
<section>
|
||||||
route === 'profile'
|
<a className='filled' onClick={() => updateRoute('profile')}>Profile Settings</a>
|
||||||
? <a onClick={() => updateRoute('')} className="filled">⇐ Back</a>
|
</section>
|
||||||
: <a className='filled' onClick={() => updateRoute('profile')} href="#profile">Profile Settings</a>
|
}
|
||||||
}
|
</header>
|
||||||
</header>
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
route === 'profile' ?
|
route === 'profile' ?
|
||||||
|
@ -138,80 +139,88 @@ function WatchOnLbryPopup(params: { profile: Awaited<ReturnType<typeof getProfil
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
:
|
:
|
||||||
<main>
|
route === 'advanced' ?
|
||||||
<section>
|
<main>
|
||||||
<label>Pick a mode</label>
|
|
||||||
<div className='options'>
|
|
||||||
<a onClick={() => setExtensionSetting('redirect', true)} className={`button ${redirect ? 'active' : ''}`}>
|
|
||||||
Redirect
|
|
||||||
</a>
|
|
||||||
<a onClick={() => setExtensionSetting('redirect', false)} className={`button ${redirect ? '' : 'active'}`}>
|
|
||||||
Show a button
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{
|
|
||||||
!redirect &&
|
|
||||||
<section>
|
<section>
|
||||||
<label>Show button at:</label>
|
<label>Which platform you would like to redirect to?</label>
|
||||||
<b className='filled'>Video</b>
|
|
||||||
<div className='options'>
|
<div className='options'>
|
||||||
<div className="left">
|
{targetPlatforms.map(([name, value]) =>
|
||||||
<span>Subscribe Button:</span>
|
<a onClick={() => setExtensionSetting('targetPlatform', name)} className={`button ${targetPlatform === name ? 'active' : ''}`}>
|
||||||
</div>
|
{value.displayName}
|
||||||
<a onClick={() => setExtensionSetting('videoSubButton', !videoSubButton)} className={`button ${videoSubButton ? 'active' : ''}`}>
|
</a>
|
||||||
{videoSubButton ? 'Active' : 'Deactive'}
|
)}
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div className='options'>
|
|
||||||
<div className="left">
|
|
||||||
<span>Video Player:</span>
|
|
||||||
</div>
|
|
||||||
<a onClick={() => setExtensionSetting('videoPlayerButton', !videoPlayerButton)} className={`button ${videoPlayerButton ? 'active' : ''}`}>
|
|
||||||
{videoPlayerButton ? 'Active' : 'Deactive'}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<b className='filled'>Channel</b>
|
|
||||||
<div className='options'>
|
|
||||||
<div className="left">
|
|
||||||
<span>Subscribe Button:</span>
|
|
||||||
</div>
|
|
||||||
<a onClick={() => setExtensionSetting('channelSubButton', !channelSubButton)} className={`button ${channelSubButton ? 'active' : ''}`}>
|
|
||||||
{channelSubButton ? 'Active' : 'Deactive'}
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
}
|
<section>
|
||||||
<section>
|
<label>Which resolver API you want to use?</label>
|
||||||
<label>Which platform you would like to redirect?</label>
|
<div className='options'>
|
||||||
<div className='options'>
|
{ytUrlResolverOptions.map(([name, value]) =>
|
||||||
{targetPlatforms.map(([name, value]) =>
|
<a onClick={() => setExtensionSetting('urlResolver', name)} className={`button ${urlResolver === name ? 'active' : ''}`}>
|
||||||
<a onClick={() => setExtensionSetting('targetPlatform', name)} className={`button ${targetPlatform === name ? 'active' : ''}`}>
|
{value.name}
|
||||||
{value.displayName}
|
</a>
|
||||||
</a>
|
)}
|
||||||
)}
|
</div>
|
||||||
</div>
|
<a onClick={() => loads(lbryUrlCache.clearAll().then(() => dialogManager.alert("Cleared Cache!")))} className={`button active`}>
|
||||||
</section>
|
Clear Resolver Cache
|
||||||
<section>
|
</a>
|
||||||
<label>Which resolver API you want to use?</label>
|
</section>
|
||||||
<div className='options'>
|
</main>
|
||||||
{ytUrlResolverOptions.map(([name, value]) =>
|
:
|
||||||
<a onClick={() => setExtensionSetting('urlResolver', name)} className={`button ${urlResolver === name ? 'active' : ''}`}>
|
<main>
|
||||||
{value.name}
|
<section>
|
||||||
</a>
|
<label>Auto redirect when:</label>
|
||||||
)}
|
<div className='options'>
|
||||||
</div>
|
<div class="toggle-option">
|
||||||
<a onClick={() => loads(lbryUrlCache.clearAll().then(() => dialogManager.alert("Cleared Cache!")))} className={`button active`}>
|
<span>Playing a video</span>
|
||||||
Clear Resolver Cache
|
<a onClick={() => setExtensionSetting('redirectVideo', !redirectVideo)} className={`button ${redirectVideo ? 'active' : ''}`}>
|
||||||
</a>
|
{redirectVideo ? 'Active' : 'Deactive'}
|
||||||
</section>
|
</a>
|
||||||
<section>
|
</div>
|
||||||
<label>Tools</label>
|
<div class="toggle-option">
|
||||||
<a target='_blank' href='/pages/YTtoLBRY/index.html' className={`filled`}>
|
<span>Playing a playlist</span>
|
||||||
Subscription Converter
|
<a onClick={() => setExtensionSetting('redirectVideoPlaylist', !redirectVideoPlaylist)} className={`button ${redirectVideoPlaylist ? 'active' : ''}`}>
|
||||||
</a>
|
{redirectVideoPlaylist ? 'Active' : 'Deactive'}
|
||||||
</section>
|
</a>
|
||||||
</main>
|
</div>
|
||||||
|
<div class="toggle-option">
|
||||||
|
<span>Viewing a channel</span>
|
||||||
|
<a onClick={() => setExtensionSetting('redirectChannel', !redirectChannel)} className={`button ${redirectChannel ? 'active' : ''}`}>
|
||||||
|
{redirectChannel ? 'Active' : 'Deactive'}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<label>Show redirect button on:</label>
|
||||||
|
<div className='options'>
|
||||||
|
<div className="toggle-option">
|
||||||
|
<span>Video Page</span>
|
||||||
|
<a onClick={() => setExtensionSetting('buttonVideoSub', !buttonVideoSub)} className={`button ${buttonVideoSub ? 'active' : ''}`}>
|
||||||
|
{buttonVideoSub ? 'Active' : 'Deactive'}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div className="toggle-option">
|
||||||
|
<span>Channel Page</span>
|
||||||
|
<a onClick={() => setExtensionSetting('buttonChannelSub', !buttonChannelSub)} className={`button ${buttonChannelSub ? 'active' : ''}`}>
|
||||||
|
{buttonChannelSub ? 'Active' : 'Deactive'}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div className="toggle-option">
|
||||||
|
<span>Video Player</span>
|
||||||
|
<a onClick={() => setExtensionSetting('buttonVideoPlayer', !buttonVideoPlayer)} className={`button ${buttonVideoPlayer ? 'active' : ''}`}>
|
||||||
|
{buttonVideoPlayer ? 'Active' : 'Deactive'}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<label>Tools</label>
|
||||||
|
<a target='_blank' href='/pages/YTtoLBRY/index.html' className={`filled`}>
|
||||||
|
Subscription Converter
|
||||||
|
</a>
|
||||||
|
<a className='filled' onClick={() => updateRoute('advanced')}>Advanced Settings</a>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
}
|
}
|
||||||
{loading && <div class="overlay">
|
{loading && <div class="overlay">
|
||||||
<span>Loading...</span>
|
<span>Loading...</span>
|
||||||
|
|
|
@ -54,4 +54,9 @@ section>* {
|
||||||
justify-items: start;
|
justify-items: start;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-option {
|
||||||
|
display: grid;
|
||||||
|
gap: .5em;
|
||||||
}
|
}
|
|
@ -17,6 +17,7 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa
|
||||||
platform: SourcePlatform
|
platform: SourcePlatform
|
||||||
id: string
|
id: string
|
||||||
type: ResolveUrlTypes
|
type: ResolveUrlTypes
|
||||||
|
url: URL
|
||||||
time: number | null
|
time: number | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +27,6 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa
|
||||||
chrome.storage.onChanged.addListener(async (changes, areaName) => {
|
chrome.storage.onChanged.addListener(async (changes, areaName) => {
|
||||||
if (areaName !== 'local') return
|
if (areaName !== 'local') return
|
||||||
Object.assign(settings, Object.fromEntries(Object.entries(changes).map(([key, change]) => [key, change.newValue])))
|
Object.assign(settings, Object.fromEntries(Object.entries(changes).map(([key, change]) => [key, change.newValue])))
|
||||||
if (settings.redirect) updateButton(null)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const buttonMountPoint = document.createElement('div')
|
const buttonMountPoint = document.createElement('div')
|
||||||
|
@ -112,7 +112,7 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateButton(params: { source: Source, target: Target } | null): void {
|
function updateButtons(params: { source: Source, target: Target } | null): void {
|
||||||
if (!params) {
|
if (!params) {
|
||||||
render(<WatchOnLbryButton />, buttonMountPoint)
|
render(<WatchOnLbryButton />, buttonMountPoint)
|
||||||
render(<WatchOnLbryPlayerButton />, playerButtonMountPoint)
|
render(<WatchOnLbryPlayerButton />, 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) :
|
document.querySelector(params.source.platform.htmlQueries.mountPoints.mountPlayerButtonBefore) :
|
||||||
null
|
null
|
||||||
if (!mountPlayerButtonBefore) render(<WatchOnLbryPlayerButton />, playerButtonMountPoint)
|
if (!mountPlayerButtonBefore) render(<WatchOnLbryPlayerButton />, 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]) :
|
document.querySelector(params.source.platform.htmlQueries.mountPoints.mountButtonBefore[params.source.type]) :
|
||||||
null
|
null
|
||||||
if (!mountButtonBefore) render(<WatchOnLbryButton />, buttonMountPoint)
|
if (!mountButtonBefore) render(<WatchOnLbryButton />, buttonMountPoint)
|
||||||
|
@ -163,7 +163,8 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa
|
||||||
id: url.searchParams.get('v')!,
|
id: url.searchParams.get('v')!,
|
||||||
platform,
|
platform,
|
||||||
time: url.searchParams.has('t') ? parseYouTubeURLTimeString(url.searchParams.get('t')!) : null,
|
time: url.searchParams.has('t') ? parseYouTubeURLTimeString(url.searchParams.get('t')!) : null,
|
||||||
type: 'video'
|
type: 'video',
|
||||||
|
url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (url.pathname.startsWith('/channel/')) {
|
else if (url.pathname.startsWith('/channel/')) {
|
||||||
|
@ -171,7 +172,8 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa
|
||||||
id: url.pathname.substring("/channel/".length),
|
id: url.pathname.substring("/channel/".length),
|
||||||
platform,
|
platform,
|
||||||
time: null,
|
time: null,
|
||||||
type: 'channel'
|
type: 'channel',
|
||||||
|
url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (url.pathname.startsWith('/c/') || url.pathname.startsWith('/user/')) {
|
else if (url.pathname.startsWith('/c/') || url.pathname.startsWith('/user/')) {
|
||||||
|
@ -187,7 +189,8 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa
|
||||||
id,
|
id,
|
||||||
platform,
|
platform,
|
||||||
time: null,
|
time: null,
|
||||||
type: 'channel'
|
type: 'channel',
|
||||||
|
url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,9 +236,47 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request new tab
|
// Request new tab
|
||||||
async function openNewTab(url: URL, active: boolean) {
|
async function openNewTab(url: URL) {
|
||||||
if (!open(url.href, '_blank'))
|
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<HTMLAnchorElement>('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) {
|
function getLbryUrlByTarget(target: Target) {
|
||||||
|
@ -245,104 +286,83 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa
|
||||||
return url
|
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)
|
await sleep(500)
|
||||||
const url: URL = new URL(location.href)
|
try {
|
||||||
|
|
||||||
await (async () => {
|
|
||||||
const source = await getSourceByUrl(new URL(location.href))
|
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 {
|
// Update Buttons
|
||||||
if (settings.redirect) {
|
if (urlHrefCache !== url.href) updateButtons(null)
|
||||||
const target = (await getTargetsBySources(source))[source.id]
|
// If target is a video target add timestampt to it
|
||||||
if (!target) return
|
if (target.type === 'video') {
|
||||||
if (url.href === urlHrefCache) return
|
const videoElement = document.querySelector<HTMLVideoElement>(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') {
|
const lbryURL = getLbryUrlByTarget(target)
|
||||||
// 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 (target.platform === targetPlatformSettings.app) {
|
if (source.type === 'video') {
|
||||||
if (document.hidden) await new Promise((resolve) => document.addEventListener('visibilitychange', resolve, { once: true }))
|
// As soon as video play is ready and start playing, pause it.
|
||||||
// Replace is being used so browser doesnt start an empty window
|
findVideoElementAwait(source).then((videoElement) => {
|
||||||
// Its not gonna be able to replace anyway, since its a LBRY Uri
|
videoElement.addEventListener('play', () => videoElement.pause(), { once: true })
|
||||||
location.replace(lbryURL)
|
videoElement.pause()
|
||||||
}
|
})
|
||||||
else {
|
}
|
||||||
openNewTab(lbryURL, document.hasFocus())
|
|
||||||
|
|
||||||
if (window.history.length === 1) window.close()
|
if (target.platform === targetPlatformSettings.app) {
|
||||||
else window.history.back()
|
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 {
|
else {
|
||||||
if (urlHrefCache !== url.href) updateButton(null)
|
openNewTab(lbryURL)
|
||||||
let target = (await getTargetsBySources(source))[source.id]
|
|
||||||
|
|
||||||
// There is no target found via API try to check Video Description for LBRY links.
|
if (window.history.length === 1) window.close()
|
||||||
if (!target) {
|
else window.history.back()
|
||||||
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<HTMLAnchorElement>('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<HTMLVideoElement>(source.platform.htmlQueries.videoPlayer)
|
|
||||||
if (videoElement) target.time = videoElement.currentTime > 3 && videoElement.currentTime < videoElement.duration - 1 ? videoElement.currentTime : null
|
|
||||||
}
|
|
||||||
|
|
||||||
updateButton({ target, source })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
}
|
}
|
||||||
})()
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
urlHrefCache = url.href
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
})()
|
})()
|
|
@ -21,13 +21,13 @@ async function initSettings() {
|
||||||
if (!Object.keys(targetPlatformSettings).includes(settings.targetPlatform)) setExtensionSetting('targetPlatform', DEFAULT_SETTINGS.targetPlatform)
|
if (!Object.keys(targetPlatformSettings).includes(settings.targetPlatform)) setExtensionSetting('targetPlatform', DEFAULT_SETTINGS.targetPlatform)
|
||||||
if (!Object.keys(ytUrlResolversSettings).includes(settings.urlResolver)) setExtensionSetting('urlResolver', DEFAULT_SETTINGS.urlResolver)
|
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
|
if (areaName !== 'local' || !changes.redirect) return
|
||||||
chromeAction.setBadgeText({ text: changes.redirect.newValue ? 'ON' : 'OFF' })
|
chromeAction.setBadgeText({ text: changes.redirect.newValue ? 'ON' : 'OFF' })
|
||||||
})
|
}) */
|
||||||
|
|
||||||
chrome.runtime.onStartup.addListener(initSettings)
|
chrome.runtime.onStartup.addListener(initSettings)
|
||||||
chrome.runtime.onInstalled.addListener(initSettings)
|
chrome.runtime.onInstalled.addListener(initSettings)
|
|
@ -2,24 +2,28 @@ import type { JSX } from "preact"
|
||||||
import { useEffect, useReducer } from "preact/hooks"
|
import { useEffect, useReducer } from "preact/hooks"
|
||||||
import type { ResolveUrlTypes } from "../modules/yt/urlResolve"
|
import type { ResolveUrlTypes } from "../modules/yt/urlResolve"
|
||||||
|
|
||||||
export interface ExtensionSettings {
|
export interface ExtensionSettings extends Record<string, string | number | boolean | null | undefined>{
|
||||||
redirect: boolean
|
|
||||||
targetPlatform: TargetPlatformName
|
targetPlatform: TargetPlatformName
|
||||||
urlResolver: YTUrlResolverName,
|
urlResolver: YTUrlResolverName,
|
||||||
videoSubButton: boolean
|
redirectVideo: boolean,
|
||||||
videoPlayerButton: boolean
|
redirectChannel: boolean,
|
||||||
channelSubButton: boolean
|
redirectVideoPlaylist: boolean,
|
||||||
|
buttonVideoSub: boolean
|
||||||
|
buttonVideoPlayer: boolean
|
||||||
|
buttonChannelSub: boolean
|
||||||
publicKey: string | null,
|
publicKey: string | null,
|
||||||
privateKey: string | null
|
privateKey: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_SETTINGS: ExtensionSettings = {
|
export const DEFAULT_SETTINGS: ExtensionSettings = {
|
||||||
redirect: true,
|
|
||||||
targetPlatform: 'odysee',
|
targetPlatform: 'odysee',
|
||||||
urlResolver: 'odyseeApi',
|
urlResolver: 'odyseeApi',
|
||||||
videoSubButton: true,
|
redirectVideo: false,
|
||||||
videoPlayerButton: true,
|
redirectChannel: false,
|
||||||
channelSubButton: true,
|
redirectVideoPlaylist: false,
|
||||||
|
buttonVideoSub: true,
|
||||||
|
buttonVideoPlayer: true,
|
||||||
|
buttonChannelSub: true,
|
||||||
privateKey: null,
|
privateKey: null,
|
||||||
publicKey: null
|
publicKey: null
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue