diff --git a/src/common/common.css b/src/common/common.css index 3a259ca..0d863d9 100644 --- a/src/common/common.css +++ b/src/common/common.css @@ -10,10 +10,17 @@ } :root { + font-size: .95rem; font-family: Arial, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Open Sans, Helvetica Neue, sans-serif; letter-spacing: .2ch; } +body#page { + --root-smallest-font-size: .95rem; + --root-font-size-relative-to-screen: 1; + font-size: max(var(--root-smallest-font-size), calc(min(1vw, 2vh) * var(--root-font-size-relative-to-screen))); +} + body { background: linear-gradient(to left top, var(--color-master), var(--color-slave)); background-attachment: fixed; @@ -24,7 +31,7 @@ body { body::before { content: ""; - position: absolute; + position: fixed; inset: 0; background: rgba(19, 19, 19, 0.75); } @@ -36,6 +43,30 @@ body::before { position: relative; } +a { + cursor: pointer; +} + +p, +ul, +ol, +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 0; +} + +.options { + display: grid; + width: 100%; + grid-template-columns: repeat(auto-fit, minmax(3em, 1fr)); + justify-content: center; + gap: .25em; + padding: 0 1.5em; +} .button { display: inline-flex; @@ -48,14 +79,9 @@ body::before { color: var(--color-light); border-radius: .5em; -} + border: unset; -.filled { - background: var(--color-gradient-0); - background-clip: text; - -webkit-background-clip: text; - font-weight: bold; - color: transparent; + font-size: inherit; } .button.active { @@ -77,13 +103,36 @@ body::before { pointer-events: none; } -.options { +.filled { + background: var(--color-gradient-0); + background-clip: text; + -webkit-background-clip: text; + font-weight: bold; + color: transparent; +} + +.error { display: grid; - width: 100%; - grid-template-columns: repeat(auto-fit, minmax(3em, 1fr)); - justify-content: center; - gap: .25em; - padding: 0 1.5em; + grid-auto-flow: column; + gap: .5em; + align-items: center; + justify-content: start; + color: var(--color-error); +} + +.error::before { + content: "!"; + width: 2em; + aspect-ratio: 1/1; + + display: grid; + place-items: center; + letter-spacing: 0; + line-height: 0; + + border: .1em solid currentColor; + border-radius: 100000vw; + font-weight: bold; } .overlay { diff --git a/src/common/components/ButtonRadio.sass b/src/common/components/ButtonRadio.sass deleted file mode 100644 index 3109995..0000000 --- a/src/common/components/ButtonRadio.sass +++ /dev/null @@ -1,21 +0,0 @@ -@import '../style' - -.ButtonRadio - display: flex - justify-content: center - flex-wrap: wrap - gap: .25em - cursor: pointer - - * - cursor: pointer - - .radio-button - @extend .button - - .radio-button.checked - @extend .button.active - - input[type="radio"] - opacity: 0 - position: absolute diff --git a/src/common/components/ButtonRadio.tsx b/src/common/components/ButtonRadio.tsx deleted file mode 100644 index b38ce41..0000000 --- a/src/common/components/ButtonRadio.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import classnames from 'classnames' -import { h } from 'preact' -import './ButtonRadio.sass' - - -export interface SelectionOption { - value: string - display: string -} - -export interface ButtonRadioProps { - name?: string - onChange(redirect: string): void - value: T extends SelectionOption ? T['value'] : T - options: T[] -} - -const getAttr = (x: string | SelectionOption, key: keyof SelectionOption): string => typeof x === 'string' ? x : x[key] - -export default function ButtonRadio({ name = 'buttonRadio', onChange, options, value }: ButtonRadioProps) { - /** If it's a string, return the string, if it's a SelectionOption get the selection option property */ - return
- {options.map(o => ({ o: getAttr(o, 'value'), display: getAttr(o, 'display') })).map(({ o, display }) => -
o !== value && onChange(o)}> - - -
- )} -
-} diff --git a/src/common/components/Row/index.tsx b/src/common/components/Row/index.tsx new file mode 100644 index 0000000..5e916a2 --- /dev/null +++ b/src/common/components/Row/index.tsx @@ -0,0 +1,33 @@ +import { ComponentChildren, h } from 'preact' +import './style.css' + +/* + Re-implementation of https://github.com/DeepDoge/svelte-responsive-row +*/ + +export function Row(params: { + children: ComponentChildren + type?: "fit" | "fill", + idealSize?: string, + gap?: string, + maxColumnCount?: number, + justifyItems?: "center" | "start" | "end" | "stretch" +}) { + if (!params.type) params.type = 'fill' + if (!params.gap) params.gap = '0' + if (!params.idealSize) params.idealSize = '100%' + if (!params.maxColumnCount) params.maxColumnCount = Number.MAX_SAFE_INTEGER + if (!params.justifyItems) params.justifyItems = 'center' + + return
+ {params.children} +
+} diff --git a/src/common/components/Row/style.css b/src/common/components/Row/style.css new file mode 100644 index 0000000..940b1d4 --- /dev/null +++ b/src/common/components/Row/style.css @@ -0,0 +1,6 @@ +.responsive-row { + display: grid; + grid-template-columns: repeat(var(--type), minmax(min(max(100% / var(--max-column-count) - var(--gap), var(--ideal-size)), 100%), 1fr)); + gap: var(--gap); + justify-items: var(--justify-items); +} \ No newline at end of file diff --git a/src/manifest.json b/src/manifest.json index cc31a2f..ebc61b3 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -42,7 +42,7 @@ }, "web_accessible_resources": [ "popup.html", - "tools/YTtoLBRY.html", + "tools/YTtoLBRY/index.html", "icons/lbry/lbry-logo.svg", "icons/lbry/odysee-logo.svg", "icons/lbry/madiator-logo.svg" diff --git a/src/popup/popup.css b/src/popup/popup.css index 820bc14..8adad0d 100644 --- a/src/popup/popup.css +++ b/src/popup/popup.css @@ -1,18 +1,3 @@ -label { - font-size: 1.75em; - font-weight: bold; - text-align: center; -} - -a { - cursor: pointer; -} - -p { - margin: 0; - text-align: center; -} - header { display: grid; gap: .5em; @@ -34,6 +19,12 @@ section { gap: .75em; } +section label { + font-size: 1.75em; + font-weight: bold; + text-align: center; +} + #popup { width: 35em; max-width: 100%; diff --git a/src/popup/popup.tsx b/src/popup/popup.tsx index 0d609b5..c8186ff 100644 --- a/src/popup/popup.tsx +++ b/src/popup/popup.tsx @@ -40,20 +40,21 @@ function WatchOnLbryPopup(params: { profile: Awaited{nickname}

{friendlyPublicKey(publicKey)}

Score: {params.profile?.score ?? '...'} - 🔗Leaderboard + { urlResolver !== 'madiatorFinder' && You need to use Madiator Finder API for scoring to work }
{ popupRoute === 'profile' - ? updateRoute('')} className="button filled">⇐ Back - : updateRoute('profile')} href="#profile">Profile Settings + ? updateRoute('')} className="filled">⇐ Back + : updateRoute('profile')} href="#profile">Profile Settings }
:
{ popupRoute === 'profile' - ? updateRoute('')} className="button filled">⇐ Back - : updateRoute('profile')} href="#profile">Your Profile + ? updateRoute('')} className="filled">⇐ Back + : updateRoute('profile')} href="#profile">Profile Settings }
} @@ -156,7 +157,7 @@ function WatchOnLbryPopup(params: { profile: Awaited
- + Subscription Converter
diff --git a/src/tools/YTtoLBRY.css b/src/tools/YTtoLBRY.css deleted file mode 100644 index d6d0b52..0000000 --- a/src/tools/YTtoLBRY.css +++ /dev/null @@ -1,93 +0,0 @@ -body { - --color-text: whitesmoke; - --color-backround: rgb(28, 31, 34); - --color-card: #2a2e32; - --color-primary: rgb(43, 187, 144); - - background-color: var(--color-backround); - color: var(--color-text); - font-size: 1rem; -} - -a { - color: var(--color-primary); -} - -h1, h2, h3, h4, h5, h6 { - margin: 0 0 10px; -} - -.container { - display: block; - text-align: center; - margin: auto; - width: 50%; - margin-bottom: 15px; - border: 3px; - padding: 10px; - -} - -.YTtoLBRY { - display: flex; - justify-content: space-around; - flex-direction: row; -} - -.Conversion { - margin: 1rem; - width: 45em; -} - -.ConversionHelp { - display: flex; - flex-direction: column; - align-items: center; -} - -.ConversionCard { - box-shadow: 0 0 0 1px rgba(16,22,26,.1), 0 1px 1px rgba(16,22,26,.2), 0 2px 6px rgba(16,22,26,.2); - border-radius: 5px; - background-color: var(--color-card); - padding: 20px; -} - -.btn { - color: var(--color-text); - cursor: pointer; - - display: inline-flex; - align-items: center; - justify-content: center; - - border: 0; - padding: 5px 10px; - border-radius: 3px; - font-size: 14px; - min-width: 30px; - min-height: 30px; -} - -.progress-text { - font-weight: bold; - padding: .25em 0; -} - -.btn.btn-primary { - background-color: var(--color-primary); -} - -.btn:disabled { - background-color: rgba(200, 200, 200, .5); - color: rgba(90, 90, 90, .6); - cursor: not-allowed; -} - -@media (max-width: 1400px) { - .YTtoLBRY { - flex-direction: column; - } - .Conversion { - width: auto; - } -} diff --git a/src/tools/YTtoLBRY.html b/src/tools/YTtoLBRY.html deleted file mode 100644 index 3a62039..0000000 --- a/src/tools/YTtoLBRY.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - Subscription Converter - - - - - -
- - - \ No newline at end of file diff --git a/src/tools/YTtoLBRY.tsx b/src/tools/YTtoLBRY.tsx deleted file mode 100644 index 8709429..0000000 --- a/src/tools/YTtoLBRY.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { h, render } from 'preact' -import { useState } from 'preact/hooks' -import { getExtensionSettingsAsync, targetPlatformSettings } from '../common/settings' -import { getFileContent, getSubsFromCsv, getSubsFromJson, getSubsFromOpml } from '../common/yt' -import { resolveById } from '../common/yt/urlResolve' -import readme from './README.md' - -/** - * Parses the subscription file and queries the API for lbry channels - * - * @param file to read - * @returns a promise with the list of channels that were found on lbry - */ -async function lbryChannelsFromFile(file: File) { - const ext = file.name.split('.').pop()?.toLowerCase() - - const ids = new Set(( - ext === 'xml' || ext == 'opml' ? getSubsFromOpml : - ext === 'csv' ? getSubsFromCsv : - getSubsFromJson)(await getFileContent(file))) - - const items = await resolveById( - Array.from(ids).map(id => ({ id, type: 'channel' } as const)), - (progress) => render(, document.getElementById('root')!)) - - const { targetPlatform: platform } = await getExtensionSettingsAsync() - const urlPrefix = targetPlatformSettings[platform].domainPrefix - return Object.values(items).map((item) => urlPrefix + item.id) -} - -function ConversionCard({ onSelect, progress }: { onSelect(file: File): Promise | void, progress: number }) { - const [file, setFile] = useState(null as File | null) - const [isLoading, setLoading] = useState(false) - - return
-

Select YouTube Subscriptions

-
- setFile(e.currentTarget.files?.length ? e.currentTarget.files[0] : null)} /> -
-
-} - -function YTtoLBRY({ progress }: { progress: number }) { - const [lbryChannels, setLbryChannels] = useState([] as string[]) - - return
-
- setLbryChannels(await lbryChannelsFromFile(file))} /> -
    - {lbryChannels.map((x, i) =>
  • } />)} -
-
-
-