layout refactoring

This commit is contained in:
2024-02-10 09:56:50 +01:00
parent 63b5f00320
commit cc06487b0a
10 changed files with 171 additions and 115 deletions

View File

@@ -1,63 +1,16 @@
<script lang="ts">
import { SvelteToast } from '@zerodevx/svelte-toast';
import * as O from 'fp-ts/Option';
import { pipe } from 'fp-ts/lib/function';
import { onDestroy } from 'svelte';
import DownloadCard from './lib/DownloadCard.svelte';
import Footer from './lib/Footer.svelte';
import Home from './lib/Home.svelte';
import Navbar from './lib/Navbar.svelte';
import Spinner from './lib/Spinner.svelte';
import { downloads, rpcClient } from './lib/store';
import { datetimeCompareFunc, isRPCResponse } from './lib/utils';
const unsubscribe = rpcClient.subscribe(($client) => {
setInterval(() => $client.running(), 750);
$client.socket.onmessage = (ev: any) => {
const event = JSON.parse(ev.data);
// guards
if (!isRPCResponse(event)) {
return;
}
if (!Array.isArray(event.result)) {
return;
}
if (event.result) {
return downloads.set(
O.of(
event.result
.filter((f) => !!f.info.url)
.sort((a, b) =>
datetimeCompareFunc(b.info.created_at, a.info.created_at),
),
),
);
}
downloads.set(O.none);
};
});
onDestroy(unsubscribe);
</script>
<main
class="bg-neutral-50 dark:bg-neutral-900 h-screen text-neutral-950 dark:text-neutral-50"
>
<Navbar />
{#if O.isNone($downloads)}
<div class="h-[90vh] w-full flex justify-center items-center">
<Spinner />
</div>
{:else}
<div class="grid grid-cols-1 lg:grid-cols-2 gap-2 p-8">
{#each pipe( $downloads, O.getOrElseW(() => []), ) as download}
<DownloadCard {download} />
{/each}
</div>
{/if}
<!-- <FloatingAction /> -->
<Home />
<Footer />
<SvelteToast />
<!-- <FloatingAction /> -->
</main>

View File

@@ -26,7 +26,7 @@
border-t dark:border-t-neutral-700
shadow-lg
rounded-t-xl"
style="height: {$height}px;"
style="min-height: {$height}px;"
>
<button
class="p-1 bg-neutral-200 dark:bg-neutral-700 rounded-lg border dark:border-neutral-700"
@@ -44,7 +44,7 @@
{#if $height > 100}
<div class="mt-2">
<NewDownload />
<!-- <Settings /> -->
<Settings />
</div>
{/if}
</footer>

View File

@@ -3,61 +3,68 @@
let group = '';
export let formats: DLFormat[];
$: console.log(group);
</script>
<div class="flex w-full flex-col items-center justify-center">
<div class="w-full px-4 py-16">
<div class="mx-auto w-full max-w-md">
<fieldset class="flex flex-col space-y-2">
{#each formats as format}
<div class="relative">
<input
id="startup"
class="absolute opacity-0 w-0 h-0 peer"
type="radio"
bind:group
name="type"
value="startup"
/>
<label
for="startup"
class="[&_p]:text-gray-900 [&_span]:text-gray-500 peer-checked:[&_p]:text-white peer-checked:[&_span]:text-sky-100 peer-focus:ring-2 peer-focus:ring-white peer-focus:ring-opacity-60 peer-focus:ring-offset-2 peer-focus:ring-offset-sky-300 bg-white relative flex cursor-pointer rounded-lg px-5 py-4 shadow-md focus:outline-none peer-checked:bg-sky-900/75 peer-checked:text-white"
>
<div class="flex w-full items-center justify-between">
<div class="flex items-center">
<div class="text-sm">
<p class="font-medium" id="headlessui-label-:R5mm:">
{format.resolution}
</p>
<span class="inline" id="headlessui-description-:R9mm:">
<span>{format.vcodec}</span>
<span aria-hidden="true">·</span>
<span>{format.vcodec}</span></span
>
</div>
</div>
<div class="shrink-0 text-white">
<svg viewBox="0 0 24 24" fill="none" class="h-6 w-6">
<circle
cx="12"
cy="12"
r="12"
fill="#fff"
opacity="0.2"
/><path
d="M7 13l3 3 7-7"
stroke="#fff"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
<div class="w-full mt-4">
<div class="mx-auto w-full">
<fieldset class="grid grid-cols-7 gap-2">
{#each formats as format}
<div class="relative">
<input
id="formats"
class="absolute opacity-0 w-0 h-0 peer"
type="radio"
bind:group
name="type"
value="formats"
/>
<label
for="formats"
class="
[&_p]:text-gray-900 [&_span]:text-gray-500
peer-checked:[&_p]:text-white peer-checked:[&_span]:text-orange-100
peer-focus:ring-2 peer-focus:ring-white
peer-focus:ring-opacity-60 peer-focus:ring-offset-2 peer-focus:ring-offset-orange-300
bg-white
relative flex
cursor-pointer
rounded-lg px-5 py-4
shadow-md
focus:outline-none
peer-checked:bg-orange-700/75
peer-checked:text-white"
>
<div class="flex w-full items-center justify-between">
<div class="flex items-center">
<div class="text-sm">
<p class="font-medium" id={format.format_id}>
{format.resolution}
</p>
<span class="inline" id={format.format_id}>
<span>{format.vcodec}</span>
<span aria-hidden="true">·</span>
<span>{format.acodec}</span>
</span>
</div>
</div>
</label>
</div>
{/each}
</fieldset>
</div>
<div class="shrink-0 text-white">
<svg viewBox="0 0 24 24" fill="none" class="h-6 w-6">
<circle cx="12" cy="12" r="12" fill="#fff" opacity="0.2" />
<path
d="M7 13l3 3 7-7"
stroke="#fff"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</div>
</div>
</label>
</div>
{/each}
</fieldset>
</div>
</div>

View File

@@ -0,0 +1,9 @@
<script lang="ts">
import Spinner from './Spinner.svelte';
</script>
<div
class="top-0 left-0 absolute w-full h-full bg-neutral-950/20 flex items-center justify-center z-50"
>
<Spinner />
</div>

52
ui/src/lib/Home.svelte Normal file
View File

@@ -0,0 +1,52 @@
<script lang="ts">
import * as O from 'fp-ts/Option';
import { pipe } from 'fp-ts/lib/function';
import { onDestroy } from 'svelte';
import DownloadCard from './DownloadCard.svelte';
import Spinner from './Spinner.svelte';
import { downloads, rpcClient } from './store';
import { datetimeCompareFunc, isRPCResponse } from './utils';
const unsubscribe = rpcClient.subscribe(($client) => {
setInterval(() => $client.running(), 750);
$client.socket.onmessage = (ev: any) => {
const event = JSON.parse(ev.data);
// guards
if (!isRPCResponse(event)) {
return;
}
if (!Array.isArray(event.result)) {
return;
}
if (event.result) {
return downloads.set(
O.of(
event.result
.filter((f) => !!f.info.url)
.sort((a, b) =>
datetimeCompareFunc(b.info.created_at, a.info.created_at),
),
),
);
}
downloads.set(O.none);
};
});
onDestroy(unsubscribe);
</script>
{#if O.isNone($downloads)}
<div class="h-[90vh] w-full flex justify-center items-center">
<Spinner />
</div>
{:else}
<div class="grid grid-cols-1 xl:grid-cols-2 gap-2 p-8">
{#each pipe( $downloads, O.getOrElseW(() => []), ) as download}
<DownloadCard {download} />
{/each}
</div>
{/if}

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { ArrowDownUp, HardDrive, Network } from 'lucide-svelte';
import { ArrowDownUp, Github, HardDrive, Network } from 'lucide-svelte';
import { downloads, rpcClient, serverApiEndpoint } from './store';
import { formatGiB, formatSpeedMiB } from './utils';
import * as O from 'fp-ts/Option';
@@ -70,6 +70,13 @@
{$serverApiEndpoint.split('//')[1]}
</div>
</div>
<a
href="https://github.com/marcopeocchi/yt-dlp-web-ui"
class="flex items-center gap-1.5 p-1 text-neutral-900 bg-orange-200 rounded-lg"
>
<Github size={18} />
</a>
</div>
</div>
</nav>

View File

@@ -25,7 +25,7 @@
<div class="w-full px-8">
<div class="my-4 font-semibold text-xl">New download</div>
<div class="grid grid-cols-2 gap-2 w-full mb-2">
<div class="grid grid-cols-1 md:grid-cols-2 gap-2 w-full mb-2">
<TextField placeholder="https://..." label="URL" bind:value={url} />
<TextField
placeholder="arguments separated by space"

View File

@@ -7,7 +7,14 @@
</script>
<select
class="p-2 bg-neutral-50 border rounded-lg appearance-none text-sm font-semibold"
class="
p-2
bg-neutral-50
border rounded-lg
appearance-none
text-sm font-semibold
focus:outline-orange-300
"
bind:value
{disabled}
{placeholder}

View File

@@ -1,13 +1,34 @@
<script lang="ts">
import CookiesTextField from './CookiesTextField.svelte';
import { rpcHost, rpcPort } from './store';
import { get } from 'svelte/store';
import Button from './Button.svelte';
import TextField from './TextField.svelte';
import { rpcClient, rpcHost, rpcPort } from './store';
import FullscreenSpinner from './FullscreenSpinner.svelte';
let loading: Promise<any>;
const update = () => (loading = get(rpcClient).updateExecutable());
</script>
<div>
<div class="font-semibold text-lg">Settings</div>
<div class="w-full px-8 mt-8">
<div class="font-semibold text-lg mb-4">Settings</div>
<input type="text" bind:value={$rpcHost} />
<input type="text" bind:value={$rpcPort} />
<div class="grid grid-cols-1 md:grid-cols-2 gap-2">
<TextField
label="Server address"
bind:value={$rpcHost}
placeholder="localhost"
/>
<TextField label="Server port" bind:value={$rpcPort} placeholder="3033" />
</div>
<CookiesTextField />
<Button class="mt-4" on:click={update}>Update yt-dlp</Button>
{#if loading}
{#await loading}
<FullscreenSpinner />
{/await}
{/if}
<!-- <CookiesTextField /> -->
</div>

View File

@@ -12,7 +12,7 @@
<label for=""> {label} </label>
<input
type="text"
class={`p-2 bg-neutral-50 border rounded-lg ${clazz}`}
class={`p-2 bg-neutral-50 border rounded-lg focus:outline-orange-300 ${clazz}`}
on:keyup
bind:value
{placeholder}