First working POC

This commit is contained in:
2026-01-26 22:21:54 +01:00
commit cfddc1edea
255 changed files with 77606 additions and 0 deletions
@@ -0,0 +1,98 @@
<script lang="ts">
import { sessions, controllableSessions } from "$lib/stores";
import SessionCard from "./SessionCard.svelte";
interface Props {
onSelectSession?: (sessionId: string) => void;
}
let { onSelectSession }: Props = $props();
function handleSessionClick(sessionId: string) {
if (onSelectSession) {
onSelectSession(sessionId);
}
}
</script>
<div class="flex flex-col gap-3">
<!-- Header -->
<div class="flex items-center justify-between">
<h2 class="text-lg font-semibold text-white">
Active Sessions
{#if $controllableSessions.length > 0}
<span class="text-sm text-gray-400 font-normal">
({$controllableSessions.length})
</span>
{/if}
</h2>
<button
onclick={() => sessions.refresh()}
class="p-2 rounded-lg text-gray-400 hover:text-white hover:bg-white/10 transition-colors"
title="Refresh sessions"
>
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
/>
</svg>
</button>
</div>
<!-- Loading state -->
{#if $sessions.isLoading && $sessions.sessions.length === 0}
<div class="flex items-center justify-center py-12">
<div class="flex flex-col items-center gap-3">
<div class="w-8 h-8 border-4 border-[var(--color-jellyfin)] border-t-transparent rounded-full animate-spin"></div>
<p class="text-sm text-gray-400">Loading sessions...</p>
</div>
</div>
{/if}
<!-- Error state -->
{#if $sessions.error}
<div class="p-4 rounded-lg bg-red-500/10 border border-red-500/50">
<p class="text-sm text-red-400">{$sessions.error}</p>
</div>
{/if}
<!-- Sessions list -->
{#if $controllableSessions.length > 0}
<div class="flex flex-col gap-2">
{#each $controllableSessions as session (session.id)}
<SessionCard
{session}
selected={$sessions.selectedSessionId === session.id}
onclick={() => handleSessionClick(session.id)}
/>
{/each}
</div>
{:else if !$sessions.isLoading}
<!-- Empty state -->
<div class="flex flex-col items-center justify-center py-12 text-center">
<svg class="w-16 h-16 text-gray-600 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
/>
</svg>
<h3 class="text-lg font-medium text-gray-400 mb-2">No Active Sessions</h3>
<p class="text-sm text-gray-500 max-w-sm">
No controllable Jellyfin sessions found. Start playing media on another device to control it from here.
</p>
</div>
{/if}
<!-- Last updated -->
{#if $sessions.lastUpdated && $controllableSessions.length > 0}
<p class="text-xs text-gray-500 text-center">
Last updated: {$sessions.lastUpdated.toLocaleTimeString()}
</p>
{/if}
</div>