feat: add URL parameter syncing for session and player
Implement URL search parameter synchronization for `session` and `player` to allow for bookmarkable links. Added `sessionName` to the journal stream state to support displaying human-readable session names in the UI. Improved layout transitions and updated the JournalPanel to show more detailed connection information.
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
createSession,
|
||||
deleteSession,
|
||||
disconnectStream,
|
||||
setSessionId,
|
||||
} from "../stores/journalStream";
|
||||
import { journalSetState } from "../stores/journalStream";
|
||||
|
||||
@@ -38,7 +39,7 @@ export const ConnectionBar: Component = () => {
|
||||
const handleSessionSelect = async (id: string) => {
|
||||
try {
|
||||
await hydrateFromServer(id);
|
||||
journalSetState("sessionId", id);
|
||||
setSessionId(id);
|
||||
} catch (e) {
|
||||
setError("Failed to load session");
|
||||
}
|
||||
@@ -56,7 +57,7 @@ export const ConnectionBar: Component = () => {
|
||||
<span class="text-xs text-gray-500">connected</span>
|
||||
<Show when={stream.sessionId}>
|
||||
<span class="text-xs font-mono bg-gray-100 px-1.5 py-0.5 rounded">
|
||||
{stream.sessionId}
|
||||
{stream.sessionName || stream.sessionId}
|
||||
</span>
|
||||
</Show>
|
||||
<div class="flex-1" />
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
hydrateFromServer,
|
||||
useJournalStream,
|
||||
setMyName,
|
||||
setSessionId,
|
||||
} from "../stores/journalStream";
|
||||
import { ConnectionBar } from "./ConnectionBar";
|
||||
import { StreamView } from "./StreamView";
|
||||
@@ -26,9 +27,9 @@ export const JournalPanel: Component<JournalPanelProps> = (props) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Backdrop — hidden on desktop since panel doesn't overlay content */}
|
||||
{/* Backdrop — only on mobile, starts below header */}
|
||||
<div
|
||||
class="fixed inset-0 bg-black/30 z-40 md:hidden"
|
||||
class="fixed top-16 inset-x-0 bottom-0 bg-black/30 z-40 md:hidden"
|
||||
classList={{ hidden: !props.open }}
|
||||
onClick={props.onClose}
|
||||
/>
|
||||
@@ -43,10 +44,9 @@ export const JournalPanel: Component<JournalPanelProps> = (props) => {
|
||||
>
|
||||
{/* Header */}
|
||||
<div class="flex items-center justify-between px-3 py-2 border-b border-gray-200 shrink-0">
|
||||
<div class="flex items-center gap-2">
|
||||
<h2 class="text-sm font-semibold text-gray-700">Journal</h2>
|
||||
<div class="flex items-center gap-2 min-w-0">
|
||||
<span
|
||||
class="w-2 h-2 rounded-full"
|
||||
class="w-2 h-2 rounded-full shrink-0"
|
||||
classList={{
|
||||
"bg-gray-400": stream.connectionStatus === "disconnected",
|
||||
"bg-yellow-400 animate-pulse":
|
||||
@@ -56,10 +56,27 @@ export const JournalPanel: Component<JournalPanelProps> = (props) => {
|
||||
}}
|
||||
title={stream.connectionStatus}
|
||||
/>
|
||||
<Show
|
||||
when={stream.connected && stream.sessionId}
|
||||
fallback={
|
||||
<h2 class="text-sm font-semibold text-gray-700 truncate">
|
||||
Disconnected
|
||||
</h2>
|
||||
}
|
||||
>
|
||||
<div class="min-w-0">
|
||||
<p class="text-sm font-semibold text-gray-700 truncate leading-tight">
|
||||
{stream.myName}
|
||||
</p>
|
||||
<p class="text-[10px] text-gray-400 truncate leading-tight">
|
||||
{stream.sessionName || stream.sessionId}
|
||||
</p>
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
<button
|
||||
onClick={props.onClose}
|
||||
class="text-gray-400 hover:text-gray-600 text-sm px-1"
|
||||
class="text-gray-400 hover:text-gray-600 text-sm px-1 shrink-0"
|
||||
title="Hide panel"
|
||||
>
|
||||
▸
|
||||
@@ -114,6 +131,7 @@ const ConnectDialog: Component = () => {
|
||||
try {
|
||||
setMyName(name);
|
||||
const sessionId = stream.sessionId || "default";
|
||||
setSessionId(sessionId);
|
||||
await hydrateFromServer(sessionId);
|
||||
await connectStream(sessionId, brokerUrl);
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user