From 7be77d5a699e529653c3a870544ca54b0f49caf0 Mon Sep 17 00:00:00 2001 From: Chris Wanstrath <2+defunkt@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:38:50 -0700 Subject: [PATCH] glorious purpose --- src/dispatch.ts | 2 +- src/js/dispatch.ts | 10 ++++++---- src/js/session.ts | 39 ++++++++++++++++++++++++++++++--------- src/server.tsx | 13 ++++++++++--- src/shared/types.ts | 15 +++++++++++++-- 5 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/dispatch.ts b/src/dispatch.ts index a52b08e..908d2cd 100644 --- a/src/dispatch.ts +++ b/src/dispatch.ts @@ -1,5 +1,5 @@ //// -// Dispatch Messages received via WebSocket +// Dispatch client->server Messages received via WebSocket import { basename } from "path" import type { Message, InputMessage, SaveFileMessage } from "./shared/types" diff --git a/src/js/dispatch.ts b/src/js/dispatch.ts index 8435c78..7e5360d 100644 --- a/src/js/dispatch.ts +++ b/src/js/dispatch.ts @@ -1,10 +1,12 @@ +//// +// Dispatch server->client Messages received via WebSocket + import type { Message } from "@/shared/types" import { cacheCommands } from "./commands" import { handleOutput } from "./scrollback" import { handleStreamStart, handleStreamAppend, handleStreamReplace, handleStreamEnd } from "./stream" import { handleGameStart } from "./game" -import { browserCommands } from "./commands" -import { handleSessionUpdate } from "./session" +import { handleSessionStart, handleSessionUpdate } from "./session" // message received from server export async function dispatchMessage(msg: Message) { @@ -25,8 +27,8 @@ export async function dispatchMessage(msg: Message) { handleStreamReplace(msg); break case "game:start": await handleGameStart(msg); break - case "ui:mode": - browserCommands.mode?.(msg.data as string); break + case "session:start": + handleSessionStart(msg); break case "session:update": handleSessionUpdate(msg); break default: diff --git a/src/js/session.ts b/src/js/session.ts index c0de31f..cf24cae 100644 --- a/src/js/session.ts +++ b/src/js/session.ts @@ -2,26 +2,47 @@ // Each browser tab is a shell session. This means you can run multiple sessions // in the same browser. -import type { Message } from "@/shared/types" +import type { SessionStartMessage, SessionUpdateMessage } from "@/shared/types" +import { browserCommands } from "./commands" import { randomId } from "../shared/utils" import { $ } from "./dom" export const sessionId = randomId() export const projectName = $("project-name") as HTMLSpanElement export const projectCwd = $("project-cwd") as HTMLSpanElement +export const sessionStore = new Map() -export function handleSessionUpdate(msg: Message) { +export function handleSessionStart(msg: SessionStartMessage) { + sessionStore.set("NOSE_DIR", msg.data.NOSE_DIR) + updateProjectName(msg.data.project) + updateCwd(msg.data.cwd) + browserCommands.mode?.(msg.data.mode) +} + +export function handleSessionUpdate(msg: SessionUpdateMessage) { const data = msg.data as Record - if (data.project) { - projectName.textContent = data.project - } + if (data.project) + updateProjectName(data.project) - if (data.cwd) { - projectCwd.textContent = displayProjectPath(data.cwd) - } + if (data.cwd) + updateCwd(data.cwd) +} + +function updateProjectName(project: string) { + sessionStore.set("project", project) + projectName.textContent = project +} + +function updateCwd(cwd: string) { + cwd = displayProjectPath(cwd) + sessionStore.set("cwd", cwd) + projectCwd.textContent = cwd } function displayProjectPath(path: string): string { - return path + let prefix = sessionStore.get("NOSE_DIR") || "" + prefix += "/" + sessionStore.get("project") + + return path.replace(prefix, "") } \ No newline at end of file diff --git a/src/server.tsx b/src/server.tsx index d2e4f36..7824cd9 100644 --- a/src/server.tsx +++ b/src/server.tsx @@ -7,7 +7,7 @@ import { prettyJSON } from "hono/pretty-json" import color from "kleur" import type { Message } from "./shared/types" -import { NOSE_ICON, NOSE_BIN, NOSE_DATA, NOSE_DIR, NOSE_ROOT_BIN } from "./config" +import { NOSE_ICON, NOSE_BIN, NOSE_DATA, NOSE_DIR, NOSE_ROOT_BIN, DEFAULT_PROJECT } from "./config" import { transpile, isFile, tilde, isDir } from "./utils" import { serveApp } from "./webapp" import { commands, commandPath, loadCommandModule } from "./commands" @@ -137,8 +137,15 @@ app.get("/ws", c => { addWebsocket(ws) send(ws, { type: "commands", data: await commands() }) - const mode = getState("ui:mode") || "tall" - send(ws, { type: "ui:mode", data: mode }) + send(ws, { + type: "session:start", + data: { + NOSE_DIR: NOSE_DIR, + project: DEFAULT_PROJECT, + cwd: "/", + mode: getState("ui:mode") || "tall" + } + }) }, async onMessage(event, ws) { let data: Message | undefined diff --git a/src/shared/types.ts b/src/shared/types.ts index 8a9eea9..0488241 100644 --- a/src/shared/types.ts +++ b/src/shared/types.ts @@ -6,6 +6,7 @@ export type Message = { } | InputMessage | SaveFileMessage + | SessionStartMessage | SessionUpdateMessage export type MessageType = "error" | "input" | "output" | "commands" | "save-file" @@ -38,7 +39,17 @@ export type SaveFileMessage = { data: CommandResult | CommandOutput } +export type SessionStartMessage = { + type: "session:start" + data: { + NOSE_DIR: string + project: string + cwd: string + mode: string + } +} + export type SessionUpdateMessage = { - type: "session:update", + type: "session:update" data: Record -} \ No newline at end of file +}