mirror of
https://github.com/LBRYFoundation/Watch-on-LBRY.git
synced 2025-08-23 17:47:26 +00:00
🍘 Refactor bugfix
This commit is contained in:
parent
2b91436900
commit
610b47d1e4
3 changed files with 57 additions and 45 deletions
|
@ -92,7 +92,7 @@ export function getChannelId(channelURL: string)
|
||||||
export function parseYouTubeURLTimeString(timeString: string)
|
export function parseYouTubeURLTimeString(timeString: string)
|
||||||
{
|
{
|
||||||
const signs = timeString.replace(/[0-9]/g, '')
|
const signs = timeString.replace(/[0-9]/g, '')
|
||||||
if (signs.length === 0) return timeString
|
if (signs.length === 0) return 0
|
||||||
const numbers = timeString.replace(/[^0-9]/g, '-').split('-')
|
const numbers = timeString.replace(/[^0-9]/g, '-').split('-')
|
||||||
let total = 0
|
let total = 0
|
||||||
for (let i = 0; i < signs.length; i++)
|
for (let i = 0; i < signs.length; i++)
|
||||||
|
@ -104,9 +104,9 @@ export function parseYouTubeURLTimeString(timeString: string)
|
||||||
case 'h': t *= 60
|
case 'h': t *= 60
|
||||||
case 'm': t *= 60
|
case 'm': t *= 60
|
||||||
case 's': break
|
case 's': break
|
||||||
default: return '0'
|
default: return 0
|
||||||
}
|
}
|
||||||
total += t
|
total += t
|
||||||
}
|
}
|
||||||
return total.toString()
|
return total
|
||||||
}
|
}
|
|
@ -19,4 +19,6 @@ async function lbryPathnameFromVideoId(videoId: string): Promise<string | void>
|
||||||
chrome.runtime.onMessage.addListener(({ videoId }: { videoId: string }, sender, sendResponse) => {
|
chrome.runtime.onMessage.addListener(({ videoId }: { videoId: string }, sender, sendResponse) => {
|
||||||
lbryPathnameFromVideoId(videoId).then((lbryPathname) => sendResponse(lbryPathname))
|
lbryPathnameFromVideoId(videoId).then((lbryPathname) => sendResponse(lbryPathname))
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
chrome.tabs.onUpdated.addListener((tabId, changeInfo) => changeInfo.url && chrome.tabs.sendMessage(tabId, { }));
|
|
@ -2,9 +2,9 @@ import { h, render } from 'preact'
|
||||||
import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, TargetPlatform, targetPlatformSettings } from '../common/settings'
|
import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, TargetPlatform, targetPlatformSettings } from '../common/settings'
|
||||||
import { parseYouTubeURLTimeString } from '../common/yt'
|
import { parseYouTubeURLTimeString } from '../common/yt'
|
||||||
|
|
||||||
const sleep = (t: number) => new Promise(resolve => setTimeout(resolve, t));
|
const sleep = (t: number) => new Promise(resolve => setTimeout(resolve, t))
|
||||||
|
|
||||||
function pauseAllVideos() { document.querySelectorAll<HTMLVideoElement>('video').forEach(v => v.pause()); }
|
function pauseAllVideos() { document.querySelectorAll<HTMLVideoElement>('video').forEach(v => v.pause()) }
|
||||||
|
|
||||||
interface WatchOnLbryButtonParameters
|
interface WatchOnLbryButtonParameters
|
||||||
{
|
{
|
||||||
|
@ -20,8 +20,9 @@ interface Target
|
||||||
time: number | null
|
time: number | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export function WatchOnLbryButton({ targetPlatform, lbryPathname, time }: WatchOnLbryButtonParameters) {
|
export function WatchOnLbryButton({ targetPlatform, lbryPathname, time }: WatchOnLbryButtonParameters)
|
||||||
if (!lbryPathname || !targetPlatform) return null;
|
{
|
||||||
|
if (!lbryPathname || !targetPlatform) return null
|
||||||
|
|
||||||
const url = new URL(`${targetPlatform.domainPrefix}${lbryPathname}`)
|
const url = new URL(`${targetPlatform.domainPrefix}${lbryPathname}`)
|
||||||
if (time) url.searchParams.set('t', time.toFixed(0))
|
if (time) url.searchParams.set('t', time.toFixed(0))
|
||||||
|
@ -43,56 +44,59 @@ export function WatchOnLbryButton({ targetPlatform, lbryPathname, time }: WatchO
|
||||||
textDecoration: 'none',
|
textDecoration: 'none',
|
||||||
...targetPlatform.button.style?.button,
|
...targetPlatform.button.style?.button,
|
||||||
}}>
|
}}>
|
||||||
<img src={targetPlatform.button.icon} height={16}
|
<img src={targetPlatform.button.icon} height={16}
|
||||||
style={{ transform: 'scale(1.5)', ...targetPlatform.button.style?.icon }} />
|
style={{ transform: 'scale(1.5)', ...targetPlatform.button.style?.icon }} />
|
||||||
<span>{targetPlatform.button.text}</span>
|
<span>{targetPlatform.button.text}</span>
|
||||||
</a>
|
</a>
|
||||||
</div>;
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateButton(mountPoint: HTMLDivElement, target: Target | null): void {
|
function updateButton(mountPoint: HTMLDivElement, target: Target | null): void
|
||||||
|
{
|
||||||
if (!target) return render(<WatchOnLbryButton />, mountPoint)
|
if (!target) return render(<WatchOnLbryButton />, mountPoint)
|
||||||
render(<WatchOnLbryButton targetPlatform={target.platfrom} lbryPathname={target.lbryPathname} time={target.time ?? undefined} />, mountPoint)
|
const time = target.time && target.time > 3 ? target.time : null
|
||||||
|
render(<WatchOnLbryButton targetPlatform={target.platfrom} lbryPathname={target.lbryPathname} time={time ?? undefined} />, mountPoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
function redirectTo({ lbryPathname, platfrom }: Target)
|
function redirectTo({ lbryPathname, platfrom, time }: Target)
|
||||||
{
|
{
|
||||||
const url = new URL(`${platfrom.domainPrefix}${lbryPathname}`)
|
const url = new URL(`${platfrom.domainPrefix}${lbryPathname}`)
|
||||||
const time = new URL(location.href).searchParams.get('t')
|
|
||||||
|
if (time) url.searchParams.set('t', time.toFixed(0))
|
||||||
if (time) url.searchParams.set('t', parseYouTubeURLTimeString(time))
|
|
||||||
|
|
||||||
if (platfrom === targetPlatformSettings.app)
|
if (platfrom === targetPlatformSettings.app)
|
||||||
{
|
{
|
||||||
pauseAllVideos();
|
pauseAllVideos()
|
||||||
location.assign(url);
|
location.assign(url)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
location.replace(url.toString());
|
location.replace(url.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a mount point for the button */
|
/** Returns a mount point for the button */
|
||||||
async function findButtonMountPoint(): Promise<HTMLDivElement> {
|
async function findButtonMountPoint(): Promise<HTMLDivElement>
|
||||||
|
{
|
||||||
let mountBefore: HTMLDivElement | null = null
|
let mountBefore: HTMLDivElement | null = null
|
||||||
const sourcePlatform = getSourcePlatfromSettingsFromHostname(new URL(location.href).hostname)
|
const sourcePlatform = getSourcePlatfromSettingsFromHostname(new URL(location.href).hostname)
|
||||||
if (!sourcePlatform) throw new Error(`Unknown source of: ${location.href}`)
|
if (!sourcePlatform) throw new Error(`Unknown source of: ${location.href}`)
|
||||||
|
|
||||||
while (!(mountBefore = document.querySelector(sourcePlatform.htmlQueries.mountButtonBefore))) await sleep(200);
|
while (!(mountBefore = document.querySelector(sourcePlatform.htmlQueries.mountButtonBefore))) await sleep(200)
|
||||||
|
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div')
|
||||||
div.style.display = 'flex';
|
div.style.display = 'flex'
|
||||||
div.style.alignItems = 'center'
|
div.style.alignItems = 'center'
|
||||||
mountBefore.parentElement?.insertBefore(div, mountBefore)
|
mountBefore.parentElement?.insertBefore(div, mountBefore)
|
||||||
|
|
||||||
return div
|
return div
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findVideoElement() {
|
async function findVideoElement()
|
||||||
|
{
|
||||||
const sourcePlatform = getSourcePlatfromSettingsFromHostname(new URL(location.href).hostname)
|
const sourcePlatform = getSourcePlatfromSettingsFromHostname(new URL(location.href).hostname)
|
||||||
if (!sourcePlatform) throw new Error(`Unknown source of: ${location.href}`)
|
if (!sourcePlatform) throw new Error(`Unknown source of: ${location.href}`)
|
||||||
let videoElement: HTMLVideoElement | null = null;
|
let videoElement: HTMLVideoElement | null = null
|
||||||
|
|
||||||
while(!(videoElement = document.querySelector(sourcePlatform.htmlQueries.videoPlayer))) await sleep(200)
|
while (!(videoElement = document.querySelector(sourcePlatform.htmlQueries.videoPlayer))) await sleep(200)
|
||||||
|
|
||||||
return videoElement
|
return videoElement
|
||||||
}
|
}
|
||||||
|
@ -100,19 +104,24 @@ async function findVideoElement() {
|
||||||
window.addEventListener('load', async () =>
|
window.addEventListener('load', async () =>
|
||||||
{
|
{
|
||||||
const settings = await getExtensionSettingsAsync()
|
const settings = await getExtensionSettingsAsync()
|
||||||
const [buttonMountPoint, videoElement] = await Promise.all([findButtonMountPoint(), findVideoElement()])
|
if (settings.redirect) return await updateByURL(new URL(location.href))
|
||||||
|
|
||||||
// Listen Settings Change
|
|
||||||
chrome.storage.onChanged.addListener(async (changes, areaName) => {
|
|
||||||
if (areaName !== 'local') return;
|
|
||||||
Object.assign(settings, changes)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Listen History.pushState
|
const [buttonMountPoint, videoElement] = await Promise.all([findButtonMountPoint(), findVideoElement()])
|
||||||
|
|
||||||
|
// Listen Settings Change
|
||||||
|
chrome.storage.onChanged.addListener(async (changes, areaName) =>
|
||||||
{
|
{
|
||||||
const originalPushState = history.pushState
|
if (areaName !== 'local') return
|
||||||
history.pushState = function(...params) { originalPushState(...params); afterPushState(); }
|
Object.assign(settings, changes)
|
||||||
}
|
updateByURL(new URL(location.href))
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets messages from background script which relays tab update events. This is because there's no sensible way to detect
|
||||||
|
* history.pushState changes from a content script
|
||||||
|
*/
|
||||||
|
chrome.runtime.onMessage.addListener(onUrlChange)
|
||||||
|
|
||||||
|
|
||||||
// Request Lbry pathname from background
|
// Request Lbry pathname from background
|
||||||
// We should get this from background, so the caching works and we don't get erros in the future if yt decides to impliment CORS
|
// We should get this from background, so the caching works and we don't get erros in the future if yt decides to impliment CORS
|
||||||
|
@ -127,16 +136,17 @@ window.addEventListener('load', async () =>
|
||||||
if (!videoId) return
|
if (!videoId) return
|
||||||
const lbryPathname = await requestLbryPathname(videoId)
|
const lbryPathname = await requestLbryPathname(videoId)
|
||||||
if (!lbryPathname) return
|
if (!lbryPathname) return
|
||||||
const time = videoElement.currentTime > 3 && videoElement.currentTime < videoElement.duration - 1 ? videoElement.currentTime : null
|
const time = settings.redirect ? parseYouTubeURLTimeString(url.searchParams.get('t') ?? '0') : videoElement.currentTime
|
||||||
target = { lbryPathname, platfrom: targetPlatformSettings[settings.targetPlatform], time }
|
target = { lbryPathname, platfrom: targetPlatformSettings[settings.targetPlatform], time }
|
||||||
|
|
||||||
if (settings.redirect) redirectTo(target)
|
if (settings.redirect) redirectTo(target)
|
||||||
else updateButton(buttonMountPoint, target)
|
else updateButton(buttonMountPoint, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
videoElement.addEventListener('timeupdate', () => updateButton(buttonMountPoint, target))
|
videoElement.addEventListener('timeupdate', () => target && updateButton(buttonMountPoint, Object.assign(target, { time: videoElement.currentTime })))
|
||||||
|
videoElement.addEventListener('ended', () => target && updateButton(buttonMountPoint, Object.assign(target, { time: null })))
|
||||||
|
|
||||||
async function afterPushState()
|
async function onUrlChange()
|
||||||
{
|
{
|
||||||
await updateByURL(new URL(location.href))
|
await updateByURL(new URL(location.href))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue