Files
netfelix-audio-fix/src/routes/__root.tsx
Felix Förtsch 7d30e6c1a6
All checks were successful
Build and Push Docker Image / build (push) Successful in 1m4s
library: rename Scan nav/page to Library, show audio codecs per row
Per-row audio codec summary (distinct lowercased codecs across an
item's audio streams) via scalar subquery on media_streams, rendered
as "ac3 · aac" in a new monospace Audio column.

v2026.04.15.9

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:10:00 +02:00

87 lines
2.7 KiB
TypeScript

import { createRootRoute, Link, Outlet } from "@tanstack/react-router";
import { useEffect, useState } from "react";
import { api } from "~/shared/lib/api";
import { cn } from "~/shared/lib/utils";
declare const __APP_VERSION__: string;
export const Route = createRootRoute({
component: RootLayout,
});
function NavLink({ to, children, exact = false }: { to: string; children: React.ReactNode; exact?: boolean }) {
return (
<Link
to={to}
className={cn(
"px-2.5 py-1 rounded text-[0.85rem] no-underline transition-colors text-gray-500 hover:bg-gray-100 hover:text-gray-900",
)}
activeProps={{ className: "bg-gray-100 text-gray-900 font-medium" }}
activeOptions={{ exact }}
>
{children}
</Link>
);
}
function VersionBadge() {
const [serverVersion, setServerVersion] = useState<string | null>(null);
useEffect(() => {
api
.get<{ version: string }>("/api/version")
.then((d) => setServerVersion(d.version))
.catch(() => {});
}, []);
const buildVersion = typeof __APP_VERSION__ !== "undefined" ? __APP_VERSION__ : null;
const mismatch = buildVersion && serverVersion && buildVersion !== serverVersion;
return (
<span
className="text-[0.65rem] text-gray-400 font-mono ml-1"
title={mismatch ? `Frontend: ${buildVersion}, Server: ${serverVersion}` : undefined}
>
v{serverVersion ?? buildVersion ?? "?"}
{mismatch && (
<span className="text-amber-500 ml-1" title="Frontend and server versions differ — rebuild or refresh">
</span>
)}
</span>
);
}
function RootLayout() {
const isDev = import.meta.env.DEV;
return (
<div className="min-h-screen bg-white text-gray-900 text-sm">
{isDev && (
<div className="bg-amber-100 border-b border-amber-300 text-amber-800 text-xs font-semibold text-center py-1 px-4">
DEV MODE fresh test database, 50 movies + 10 series per scan
</div>
)}
<nav className="flex flex-wrap items-center gap-0.5 px-3 sm:px-5 py-2 sm:py-0 sm:h-12 bg-white border-b border-gray-200 sticky top-0 z-50">
<Link to="/" className="font-bold text-[0.95rem] mr-3 sm:mr-5 no-underline text-gray-900">
🎬 netfelix
</Link>
<VersionBadge />
<div className="flex flex-wrap items-center gap-0.5">
<NavLink to="/" exact>
Library
</NavLink>
<NavLink to="/pipeline">Pipeline</NavLink>
<NavLink to="/review/subtitles">Subtitles</NavLink>
</div>
<div className="flex-1" />
<div className="flex items-center gap-0.5">
<NavLink to="/paths">Paths</NavLink>
<NavLink to="/settings">Settings</NavLink>
</div>
</nav>
<main className="max-w-[1600px] mx-auto px-3 sm:px-5 pt-4 pb-12">
<Outlet />
</main>
</div>
);
}
import type React from "react";