Fix device/replay/session UX issues, add pagination, bump to 0.3.0
- Fix device rename input collapsing on mobile (fixed width vs w-full inside an auto-layout table column). - Add cascade-delete confirmation for sessions with a saved recording. - Fix header connection LED: derive state from scanning/device-count/ recording instead of the Buttplug client's raw connected flag; drop the label text and hide the indicator entirely when idle. - Add a per-device disconnect button (stop + remove from store, the closest equivalent Buttplug's protocol allows per device). - Fix replay ending early: duration now comes from the recording's actual durationMs, not the last event's timestamp. - Replay robustness: show which devices are being replayed to, reset actuators to zero on start/play/pause, fully disconnect devices and the whole client on stop/unmount, surface command failures via toast. - Stop flagging the header LED red during replay - recording is only for live sessions. - Add page-number pagination to recordings/sessions/devices lists. - Wordmark SEXY -> Sexy; add proper per-page <title>s including dynamic titles for recording/session detail and replay pages. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,18 +1,28 @@
|
||||
"use client";
|
||||
|
||||
import { useButtplugStore } from "@/lib/buttplug/store";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type IndicatorState = "scanning" | "connected" | "recording";
|
||||
|
||||
export function ConnectionStatus() {
|
||||
const connected = useButtplugStore((s) => s.connected);
|
||||
const scanning = useButtplugStore((s) => s.scanning);
|
||||
const recording = useButtplugStore((s) => s.recording);
|
||||
const deviceCount = useButtplugStore((s) => Object.keys(s.devices).length);
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2 rounded-md border border-border bg-card/60 px-3 py-1 text-xs">
|
||||
<span className={cn("bp-led", connected && "bp-pulse")} data-on={connected} aria-hidden />
|
||||
<span className="bp-readout text-muted-foreground">
|
||||
{connected ? `${deviceCount} device${deviceCount === 1 ? "" : "s"} connected` : "not connected"}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
// Priority: an active recording is the most important thing to surface,
|
||||
// then whether toys are actually connected, then a bare scan-in-progress -
|
||||
// this is deliberately independent of the Buttplug client's own `connected`
|
||||
// flag, which goes true as soon as the embedded server initializes (i.e. as
|
||||
// soon as scanning starts), not when a device is actually paired.
|
||||
const state: IndicatorState | null = recording
|
||||
? "recording"
|
||||
: deviceCount > 0
|
||||
? "connected"
|
||||
: scanning
|
||||
? "scanning"
|
||||
: null;
|
||||
|
||||
if (!state) return null;
|
||||
|
||||
return <span className="bp-led bp-pulse" data-state={state} aria-hidden />;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ export function NavBar() {
|
||||
<div className="mx-auto flex h-14 max-w-6xl items-center gap-3 px-4">
|
||||
<Link href="/" className="mr-2 flex items-center gap-2">
|
||||
<BrandMark size={26} />
|
||||
<span className="font-heading bp-gradient-text text-lg font-semibold">SEXY</span>
|
||||
<span className="font-heading bp-gradient-text text-lg font-semibold">Sexy</span>
|
||||
</Link>
|
||||
|
||||
<nav className="hidden items-center gap-1 md:flex">
|
||||
|
||||
Reference in New Issue
Block a user