feat: publish initial manifest on startup and improve UI focus
- Publish the existing session manifest via the broker on startup - Automatically focus the new session input field when it is shown - Prevent event propagation when clicking to create a new session
This commit is contained in:
parent
3eba8b3279
commit
57ffb35f2b
|
|
@ -150,6 +150,20 @@ export async function createJournalServer(
|
|||
() => {},
|
||||
);
|
||||
|
||||
// Publish the initial manifest on startup so clients see existing sessions
|
||||
const initialManifest = loadManifest(root);
|
||||
broker.publish(
|
||||
{
|
||||
topic: $SESSIONS,
|
||||
payload: Buffer.from(JSON.stringify(initialManifest)),
|
||||
qos: 1,
|
||||
retain: true,
|
||||
cmd: "publish" as const,
|
||||
dup: false,
|
||||
},
|
||||
() => {},
|
||||
);
|
||||
|
||||
console.log("[journal] persistence listener active");
|
||||
console.log("[journal] broker available at ws://<host>:<port>");
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,14 @@
|
|||
* Auto-connects to ws://{current host}:{current port} — no URL input needed.
|
||||
*/
|
||||
|
||||
import { Component, Show, createSignal, onMount, For } from "solid-js";
|
||||
import {
|
||||
Component,
|
||||
Show,
|
||||
createSignal,
|
||||
onMount,
|
||||
For,
|
||||
createEffect,
|
||||
} from "solid-js";
|
||||
import {
|
||||
connectStream,
|
||||
hydrateFromServer,
|
||||
|
|
@ -113,6 +120,7 @@ const JournalHeader: Component<JournalHeaderProps> = (props) => {
|
|||
const [newSessionName, setNewSessionName] = createSignal("");
|
||||
const [showNewInput, setShowNewInput] = createSignal(false);
|
||||
let dropdownRef!: HTMLDivElement;
|
||||
let newSessionInputRef!: HTMLInputElement;
|
||||
|
||||
const handleSessionSelect = async (id: string) => {
|
||||
try {
|
||||
|
|
@ -132,6 +140,13 @@ const JournalHeader: Component<JournalHeaderProps> = (props) => {
|
|||
setShowNewInput(false);
|
||||
};
|
||||
|
||||
// Focus the input when it appears
|
||||
createEffect(() => {
|
||||
if (showNewInput() && newSessionInputRef) {
|
||||
newSessionInputRef.focus();
|
||||
}
|
||||
});
|
||||
|
||||
const handleDisconnect = () => disconnectStream();
|
||||
|
||||
// Close dropdown on outside click
|
||||
|
|
@ -214,6 +229,7 @@ const JournalHeader: Component<JournalHeaderProps> = (props) => {
|
|||
fallback={
|
||||
<div class="px-3 py-1 flex gap-1">
|
||||
<input
|
||||
ref={newSessionInputRef}
|
||||
type="text"
|
||||
value={newSessionName()}
|
||||
onInput={(e) =>
|
||||
|
|
@ -221,7 +237,6 @@ const JournalHeader: Component<JournalHeaderProps> = (props) => {
|
|||
}
|
||||
placeholder="会话名称"
|
||||
class="flex-1 border border-gray-300 rounded px-1.5 py-0.5 text-xs"
|
||||
autofocus
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") handleCreate();
|
||||
if (e.key === "Escape") setShowNewInput(false);
|
||||
|
|
@ -237,7 +252,10 @@ const JournalHeader: Component<JournalHeaderProps> = (props) => {
|
|||
}
|
||||
>
|
||||
<button
|
||||
onClick={() => setShowNewInput(true)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setShowNewInput(true);
|
||||
}}
|
||||
class="w-full text-left px-3 py-1 text-xs text-blue-600 hover:bg-gray-100"
|
||||
>
|
||||
+ 新建会话
|
||||
|
|
|
|||
Loading…
Reference in New Issue