🍘 Refactor bugfix

This commit is contained in:
Shiba 2022-01-09 22:03:31 +00:00
parent 2b91436900
commit 610b47d1e4
3 changed files with 57 additions and 45 deletions

View file

@ -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
} }

View file

@ -20,3 +20,5 @@ chrome.runtime.onMessage.addListener(({ videoId }: { videoId: string }, sender,
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, { }));

View file

@ -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', parseYouTubeURLTimeString(time)) if (time) url.searchParams.set('t', time.toFixed(0))
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()
if (settings.redirect) return await updateByURL(new URL(location.href))
const [buttonMountPoint, videoElement] = await Promise.all([findButtonMountPoint(), findVideoElement()]) const [buttonMountPoint, videoElement] = await Promise.all([findButtonMountPoint(), findVideoElement()])
// Listen Settings Change // Listen Settings Change
chrome.storage.onChanged.addListener(async (changes, areaName) => { chrome.storage.onChanged.addListener(async (changes, areaName) =>
if (areaName !== 'local') return;
Object.assign(settings, changes)
});
// Listen History.pushState
{ {
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))
} }