mirror of
https://github.com/LBRYFoundation/Watch-on-LBRY.git
synced 2025-08-23 17:47:26 +00:00
🍙 refactoring and fixes
This commit is contained in:
parent
fe5c38bfed
commit
e8d7a349f4
6 changed files with 95 additions and 151 deletions
|
@ -10,6 +10,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
|
font-family: Arial, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Open Sans, Helvetica Neue, sans-serif;
|
||||||
letter-spacing: .2ch;
|
letter-spacing: .2ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +22,13 @@ body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(19, 19, 19, 0.75);
|
||||||
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
*::before,
|
*::before,
|
||||||
*::after {
|
*::after {
|
||||||
|
@ -28,19 +36,28 @@ body {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
justify-content: center;
|
place-items: center;
|
||||||
align-items: center;
|
place-content: center;
|
||||||
|
text-align: center;
|
||||||
padding: .5em 1em;
|
padding: .5em 1em;
|
||||||
|
|
||||||
background: var(--color-dark);
|
background: var(--color-dark);
|
||||||
color: var(--color-light);
|
color: var(--color-light);
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: .5em;
|
border-radius: .5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filled {
|
||||||
|
background: var(--color-gradient-0);
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
font-weight: bold;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
.button.active {
|
.button.active {
|
||||||
background: var(--color-gradient-0);
|
background: var(--color-gradient-0);
|
||||||
}
|
}
|
||||||
|
@ -58,4 +75,30 @@ body {
|
||||||
.button.disabled {
|
.button.disabled {
|
||||||
filter: saturate(0);
|
filter: saturate(0);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.options {
|
||||||
|
display: grid;
|
||||||
|
width: 100%;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(3em, 1fr));
|
||||||
|
justify-content: center;
|
||||||
|
gap: .25em;
|
||||||
|
padding: 0 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
font-size: 2em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background-color: #0e1117;
|
||||||
|
opacity: .75;
|
||||||
}
|
}
|
|
@ -54,7 +54,7 @@ export async function resolveById(params: Paramaters, progressCallback?: (progre
|
||||||
const response: ApiResponse = await apiResponse.json()
|
const response: ApiResponse = await apiResponse.json()
|
||||||
for (const item of params)
|
for (const item of params)
|
||||||
{
|
{
|
||||||
const lbryUrl = ((item.type === 'channel' ? response.channels : response.videos) ?? {})[item.id] ?? null
|
const lbryUrl = ((item.type === 'channel' ? response.channels : response.videos) ?? {})[item.id]?.replaceAll('#', ':') ?? null
|
||||||
// we cache it no matter if its null or not
|
// we cache it no matter if its null or not
|
||||||
await LbryPathnameCache.put(lbryUrl, item.id)
|
await LbryPathnameCache.put(lbryUrl, item.id)
|
||||||
|
|
||||||
|
|
|
@ -1,40 +1,3 @@
|
||||||
:root {
|
|
||||||
--color-master: #499375;
|
|
||||||
--color-slave: #43889d;
|
|
||||||
--color-error: rgb(245, 81, 69);
|
|
||||||
--color-gradient-0: linear-gradient(130deg, var(--color-master), var(--color-slave));
|
|
||||||
--color-gradient-1: linear-gradient(130deg, #ff7a18, #af002d 41.07%, #319197 76.05%);
|
|
||||||
--color-dark: #0e1117;
|
|
||||||
--color-light: rgb(235, 237, 241);
|
|
||||||
--gradient-animation: gradient-animation 5s linear infinite alternate;
|
|
||||||
}
|
|
||||||
|
|
||||||
:root {
|
|
||||||
letter-spacing: .2ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
background: linear-gradient(to left top, var(--color-master), var(--color-slave));
|
|
||||||
background-attachment: fixed;
|
|
||||||
color: var(--color-light);
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
background: rgba(19, 19, 19, 0.75);
|
|
||||||
}
|
|
||||||
|
|
||||||
*,
|
|
||||||
*::before,
|
|
||||||
*::after {
|
|
||||||
box-sizing: border-box;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
label {
|
||||||
font-size: 1.75em;
|
font-size: 1.75em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -75,76 +38,4 @@ section {
|
||||||
width: 35em;
|
width: 35em;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
display: inline-flex;
|
|
||||||
place-items: center;
|
|
||||||
text-align: center;
|
|
||||||
padding: .5em 1em;
|
|
||||||
|
|
||||||
background: var(--color-dark);
|
|
||||||
color: var(--color-light);
|
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: .5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filled {
|
|
||||||
background: var(--color-gradient-0);
|
|
||||||
background-clip: text;
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
font-weight: bold;
|
|
||||||
color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button.active {
|
|
||||||
background: var(--color-gradient-0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.button.active::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
background: var(--color-gradient-0);
|
|
||||||
filter: blur(.5em);
|
|
||||||
z-index: -1;
|
|
||||||
border-radius: .5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button.disabled {
|
|
||||||
filter: saturate(0);
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.go-back {
|
|
||||||
color: currentColor;
|
|
||||||
text-decoration: none;
|
|
||||||
font-size: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.options {
|
|
||||||
display: grid;
|
|
||||||
width: 100%;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(3em, 1fr));
|
|
||||||
justify-content: center;
|
|
||||||
gap: .25em;
|
|
||||||
padding: 0 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overlay {
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
position: fixed;
|
|
||||||
inset: 0;
|
|
||||||
font-size: 2em;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overlay::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
background-color: #0e1117;
|
|
||||||
opacity: .75;
|
|
||||||
}
|
}
|
|
@ -82,7 +82,7 @@ function WatchOnLbryPopup(params: { profile: Awaited<ReturnType<typeof getProfil
|
||||||
<label>Purge your profile and data!</label>
|
<label>Purge your profile and data!</label>
|
||||||
<p>Purge your profile data online and offline.</p>
|
<p>Purge your profile data online and offline.</p>
|
||||||
<div className='options'>
|
<div className='options'>
|
||||||
<a className="button filled">(╯°□°)╯︵ ┻━┻</a>
|
<span className="filled button">(╯°□°)╯︵ ┻━┻</span>
|
||||||
<a onClick={() => startAsyncOperation(purgeProfile()).then(() => renderPopup())} className={`button`}>
|
<a onClick={() => startAsyncOperation(purgeProfile()).then(() => renderPopup())} className={`button`}>
|
||||||
Purge Everything!!
|
Purge Everything!!
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -1,34 +1,27 @@
|
||||||
import { resolveById, YtUrlResolveItem } from '../common/yt/urlResolve'
|
import { resolveById } from '../common/yt/urlResolve'
|
||||||
|
|
||||||
async function resolveYT(item: YtUrlResolveItem) {
|
const onGoingLbryPathnameRequest: Record<string, ReturnType<typeof resolveById>> = {}
|
||||||
const lbryProtocolUrl: string | null = (await resolveById([item]).then((items) => items[item.id]))?.id ?? null
|
|
||||||
if (!lbryProtocolUrl) return null
|
|
||||||
return lbryProtocolUrl.replaceAll('#', ':')
|
|
||||||
/* const segments = parseProtocolUrl(lbryProtocolUrl || '', { encode: true })
|
|
||||||
if (segments.length === 0) throw new Error()
|
|
||||||
return segments.join('/') */
|
|
||||||
}
|
|
||||||
|
|
||||||
const onGoingLbryPathnameRequest: Record<string, Promise<string | null>> = {}
|
chrome.runtime.onMessage.addListener(({ json }, sender, sendResponse) => {
|
||||||
async function lbryPathnameFromVideoId(videoId: string): Promise<string | null> {
|
function resolve(result: Awaited<ReturnType<typeof resolveById>>) {
|
||||||
// Don't create a new Promise for same ID until on going one is over.
|
sendResponse(JSON.stringify(result))
|
||||||
try {
|
|
||||||
const promise = onGoingLbryPathnameRequest[videoId] ?? (onGoingLbryPathnameRequest[videoId] = resolveYT({ id: videoId, type: 'video' }))
|
|
||||||
console.log('lbrypathname request', videoId, await promise)
|
|
||||||
return await promise
|
|
||||||
} catch (error) {
|
|
||||||
throw error
|
|
||||||
}
|
}
|
||||||
finally {
|
(async () => {
|
||||||
delete onGoingLbryPathnameRequest[videoId]
|
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]
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener(({ videoId }: { videoId: string }, sender, sendResponse) => {
|
|
||||||
lbryPathnameFromVideoId(videoId).then((lbryPathname) => sendResponse(lbryPathname)).catch((err) => {
|
|
||||||
sendResponse('error')
|
|
||||||
console.error(err)
|
|
||||||
})
|
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { h, render } from 'preact'
|
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'
|
||||||
|
import { resolveById } from '../common/yt/urlResolve'
|
||||||
|
|
||||||
const sleep = (t: number) => new Promise(resolve => setTimeout(resolve, t))
|
const sleep = (t: number) => new Promise(resolve => setTimeout(resolve, t))
|
||||||
|
|
||||||
|
@ -79,10 +80,10 @@ async function findVideoElement() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
// 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 requestLbryPathname(videoId: string) {
|
async function requestResolveById(...params: Parameters<typeof resolveById>): ReturnType<typeof resolveById> {
|
||||||
const response = await new Promise<string | null | 'error'>((resolve) => chrome.runtime.sendMessage({ videoId }, resolve))
|
const json = await new Promise<string | null | 'error'>((resolve) => chrome.runtime.sendMessage({ json: JSON.stringify(params) }, resolve))
|
||||||
if (response === 'error') throw new Error("Background error.")
|
if (json === 'error') throw new Error("Background error.")
|
||||||
return response
|
return json ? JSON.parse(json) : null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start
|
// Start
|
||||||
|
@ -106,13 +107,29 @@ async function requestLbryPathname(videoId: string) {
|
||||||
chrome.runtime.onMessage.addListener(() => updater())
|
chrome.runtime.onMessage.addListener(() => updater())
|
||||||
|
|
||||||
async function getTargetByURL(url: URL) {
|
async function getTargetByURL(url: URL) {
|
||||||
if (url.pathname !== '/watch') return null
|
if (url.pathname === '/watch' && url.searchParams.has('v')) {
|
||||||
|
const videoId = url.searchParams.get('v')!
|
||||||
|
const result = await requestResolveById([{ id: videoId, type: 'video' }])
|
||||||
|
const target: Target | null = result?.[videoId] ? { lbryPathname: result[videoId].id, platfrom: targetPlatformSettings[settings.targetPlatform], time: null } : null
|
||||||
|
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
else if (url.pathname.startsWith('/channel/')) {
|
||||||
|
await requestResolveById([{ id: url.pathname.substring("/channel/".length), type: 'channel' }])
|
||||||
|
}
|
||||||
|
else if (url.pathname.startsWith('/c/') || url.pathname.startsWith('/user/'))
|
||||||
|
{
|
||||||
|
// We have to download the page content again because these parts of the page are not responsive
|
||||||
|
// yt front end sucks anyway
|
||||||
|
const content = await (await fetch(location.href)).text()
|
||||||
|
const prefix = `https://www.youtube.com/feeds/videos.xml?channel_id=`
|
||||||
|
const suffix = `"`
|
||||||
|
const startsAt = content.indexOf(prefix) + prefix.length
|
||||||
|
const endsAt = content.indexOf(suffix, startsAt)
|
||||||
|
await requestResolveById([{ id: content.substring(startsAt, endsAt), type: 'channel' }])
|
||||||
|
}
|
||||||
|
|
||||||
const videoId = url.searchParams.get('v')
|
return null
|
||||||
const lbryPathname = videoId && await requestLbryPathname(videoId)
|
|
||||||
const target: Target | null = lbryPathname ? { lbryPathname, platfrom: targetPlatformSettings[settings.targetPlatform], time: null } : null
|
|
||||||
|
|
||||||
return target
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function redirectTo({ lbryPathname, platfrom, time }: Target) {
|
async function redirectTo({ lbryPathname, platfrom, time }: Target) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue