techfreakworm's picture
feat(web): IndexedDB v2 migration; show seed and reuse button on history rows
8122b04 unverified
import { useEffect, useState } from "react";
import { listHistory, type HistoryRecord } from "@/lib/idb";
type Props = {
refreshKey?: number;
onRegenerate: (h: HistoryRecord) => void;
onReuseSeed?: (seed: number) => void;
};
function fmtTime(ts: number): string {
return new Date(ts).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
}
export default function HistoryList({ refreshKey, onRegenerate, onReuseSeed }: Props) {
const [items, setItems] = useState<HistoryRecord[]>([]);
useEffect(() => {
listHistory().then(setItems);
}, [refreshKey]);
if (items.length === 0) {
return (
<p className="text-sm text-muted-foreground italic">
Generations will be archived here.
</p>
);
}
return (
<ul className="space-y-3">
{items.map((h, i) => {
const url = URL.createObjectURL(h.audioBlob);
const kindLabel =
h.kind === "dialog"
? `dialog · ${(h.speakers ?? []).length} spk · ${h.modelId.replace("chatterbox-", "")}`
: `${h.modelId.replace("chatterbox-", "")} · ${h.language ?? "—"}`;
return (
<li key={h.id} className="card-paper p-3 space-y-2.5">
<div className="flex items-baseline justify-between gap-3">
<span className="marker-num">
{String(items.length - i).padStart(2, "0")}
</span>
<span className="label-mono">{kindLabel} · {fmtTime(h.createdAt)}</span>
</div>
<p className="text-[13px] leading-snug line-clamp-3">{h.text}</p>
<audio controls src={url} className="w-full h-9" />
<div className="flex items-center justify-between">
{h.seedUsed != null ? (
<button
type="button"
onClick={() => onReuseSeed?.(h.seedUsed!)}
className="label-mono hover:text-[hsl(var(--ember))] transition-colors"
title="Copy this seed into the active params"
>
seed {h.seedUsed} · ↻
</button>
) : (
<span className="label-mono text-muted-foreground/60">no seed</span>
)}
<div className="flex gap-3">
<a
href={url}
download={`${h.id}.wav`}
className="label-mono hover:text-foreground transition-colors"
>
↓ download
</a>
<button
type="button"
className="label-mono hover:text-[hsl(var(--ember))] transition-colors"
onClick={() => onRegenerate(h)}
>
↻ regenerate
</button>
</div>
</div>
</li>
);
})}
</ul>
);
}