mirror of
https://github.com/LBRYFoundation/Watch-on-LBRY.git
synced 2025-08-23 17:47:26 +00:00
Merge pull request #132 from DeepDoge/master
Opening new tabs handled by the background now
This commit is contained in:
commit
64570b83bf
4 changed files with 126 additions and 99 deletions
|
@ -18,6 +18,7 @@
|
|||
"https://odysee.com/",
|
||||
"https://madiator.com/",
|
||||
"https://finder.madiator.com/",
|
||||
"tabs",
|
||||
"storage"
|
||||
],
|
||||
"web_accessible_resources": [
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
"128": "assets/icons/wol/icon128.png"
|
||||
},
|
||||
"permissions": [
|
||||
"storage"
|
||||
"storage",
|
||||
"tabs"
|
||||
],
|
||||
"host_permissions": [
|
||||
"https://www.youtube.com/",
|
||||
|
|
|
@ -2,23 +2,34 @@ import { resolveById } from "../modules/yt/urlResolve"
|
|||
|
||||
const onGoingLbryPathnameRequest: Record<string, ReturnType<typeof resolveById>> = {}
|
||||
|
||||
chrome.runtime.onMessage.addListener(({ json }, sender, sendResponse) => {
|
||||
chrome.runtime.onMessage.addListener(({ method, data }, sender, sendResponse) => {
|
||||
function resolve(result: Awaited<ReturnType<typeof resolveById>>) {
|
||||
sendResponse(JSON.stringify(result))
|
||||
}
|
||||
(async () => {
|
||||
try {
|
||||
const params: Parameters<typeof resolveById> = JSON.parse(json)
|
||||
// Don't create a new Promise for same ID until on going one is over.
|
||||
const promise = onGoingLbryPathnameRequest[json] ?? (onGoingLbryPathnameRequest[json] = resolveById(...params))
|
||||
console.log('lbrypathname request', params, await promise)
|
||||
resolve(await promise)
|
||||
} catch (error) {
|
||||
sendResponse('error')
|
||||
console.error(error)
|
||||
}
|
||||
finally {
|
||||
delete onGoingLbryPathnameRequest[json]
|
||||
|
||||
switch (method) {
|
||||
case 'openTab':
|
||||
{
|
||||
const { href, active }: { href: string, active: boolean } = JSON.parse(data)
|
||||
chrome.tabs.create({ url: href, active })
|
||||
}
|
||||
break
|
||||
case 'resolveUrl':
|
||||
try {
|
||||
const params: Parameters<typeof resolveById> = JSON.parse(data)
|
||||
// Don't create a new Promise for same ID until on going one is over.
|
||||
const promise = onGoingLbryPathnameRequest[data] ?? (onGoingLbryPathnameRequest[data] = resolveById(...params))
|
||||
console.log('lbrypathname request', params, await promise)
|
||||
resolve(await promise)
|
||||
} catch (error) {
|
||||
sendResponse(`error:${(error as any).toString()}`)
|
||||
console.error(error)
|
||||
}
|
||||
finally {
|
||||
delete onGoingLbryPathnameRequest[data]
|
||||
}
|
||||
break
|
||||
}
|
||||
})()
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ 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')
|
||||
|
@ -222,12 +223,17 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa
|
|||
}
|
||||
// We should get this from background, so the caching works and we don't get errors in the future if yt decides to impliment CORS
|
||||
async function requestResolveById(...params: Parameters<typeof resolveById>): ReturnType<typeof resolveById> {
|
||||
const json = await new Promise<string | null | 'error'>((resolve) => chrome.runtime.sendMessage({ json: JSON.stringify(params) }, resolve))
|
||||
if (json === 'error') {
|
||||
const response = await new Promise<string | null | 'error'>((resolve) => chrome.runtime.sendMessage({ method: 'resolveUrl', data: JSON.stringify(params) }, resolve))
|
||||
if (response?.startsWith('error:')) {
|
||||
console.error("Background error on:", params)
|
||||
throw new Error("Background error.")
|
||||
throw new Error(`Background error.${response ?? ''}`)
|
||||
}
|
||||
return json ? JSON.parse(json) : null
|
||||
return response ? JSON.parse(response) : null
|
||||
}
|
||||
|
||||
// Request new tab
|
||||
async function openNewTab(url: URL, active: boolean) {
|
||||
chrome.runtime.sendMessage({ method: 'openTab', data: JSON.stringify({ href: url.href, active }) })
|
||||
}
|
||||
|
||||
function getLbryUrlByTarget(target: Target) {
|
||||
|
@ -237,98 +243,106 @@ import { getExtensionSettingsAsync, getSourcePlatfromSettingsFromHostname, getTa
|
|||
return url
|
||||
}
|
||||
|
||||
let urlCache: URL | null = null
|
||||
let urlHrefCache: string | null = null
|
||||
while (true) {
|
||||
await sleep(500)
|
||||
|
||||
const url: URL = (urlCache?.href === location.href) ? urlCache : new URL(location.href)
|
||||
const source = await getSourceByUrl(new URL(location.href))
|
||||
if (!source) continue
|
||||
|
||||
try {
|
||||
if (settings.redirect) {
|
||||
const target = (await getTargetsBySources(source))[source.id]
|
||||
if (!target) continue
|
||||
if (url === urlCache) continue
|
||||
|
||||
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 (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)
|
||||
const url: URL = new URL(location.href);
|
||||
|
||||
await (async () => {
|
||||
const source = await getSourceByUrl(new URL(location.href))
|
||||
if (!source) return
|
||||
|
||||
try {
|
||||
if (settings.redirect) {
|
||||
const target = (await getTargetsBySources(source))[source.id]
|
||||
if (!target) return
|
||||
console.log(url.href, urlHrefCache)
|
||||
if (url.href === urlHrefCache) return
|
||||
|
||||
const lbryURL = getLbryUrlByTarget(target)
|
||||
|
||||
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 (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 {
|
||||
console.log('open', lbryURL.href)
|
||||
openNewTab(lbryURL, document.hasFocus())
|
||||
|
||||
if (window.history.length === 1) window.close()
|
||||
else window.history.back()
|
||||
}
|
||||
}
|
||||
else {
|
||||
open(lbryURL, '_blank')
|
||||
if (window.history.length === 1) window.close()
|
||||
else window.history.back()
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (urlCache !== url) updateButton(null)
|
||||
let target = (await getTargetsBySources(source))[source.id]
|
||||
|
||||
// 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<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]
|
||||
if (urlHrefCache !== url.href) updateButton(null)
|
||||
let target = (await getTargetsBySources(source))[source.id]
|
||||
|
||||
// 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<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
|
||||
}
|
||||
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
|
||||
|
||||
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 })
|
||||
}
|
||||
|
||||
updateButton({ target, source })
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
urlCache = url
|
||||
})()
|
||||
|
||||
urlHrefCache = url.href
|
||||
}
|
||||
|
||||
})()
|
Loading…
Add table
Reference in a new issue