Mobile-responsive layout, image attachments, session list - #18
Open
LeonmanRolls wants to merge 3 commits into
Open
Mobile-responsive layout, image attachments, session list#18LeonmanRolls wants to merge 3 commits into
LeonmanRolls wants to merge 3 commits into
Conversation
- add @media (max-width: 640px) breakpoint tightening header, message, and input-bar padding - hide wordmark and connection-status text on phones to free header room - bump prompt-input font-size to 16px on small screens so iOS Safari doesn't auto-zoom when the textarea is focused - add overflow-wrap: anywhere on message text and bubbles so long unbroken strings (URLs, tokens) can't push the layout wide - min-width: 0 on the prompt-input so flex doesn't keep it stuck at placeholder text width - overflow-x: hidden on #app as a safety net - switch #app height from 100vh to 100dvh (with 100vh fallback) so the input bar stays inside the visible viewport on mobile Safari when the URL bar is showing
Add the ability to attach images to a prompt from the web UI. The pi SDK
already accepts an `images?: ImageContent[]` array on prompt options, so
this wires the existing capability through to the user.
Server (server/index.ts):
- Accept an optional `images` array on the `prompt` WebSocket command.
- Validate each entry: shape, mime type (png/jpeg/gif/webp), decoded size
(≤10 MB), and drop anything that fails.
- Pass through to session.prompt(text, { images }).
- Allow image-only prompts (no longer require text).
Frontend (index.html, src/main.ts, src/style.css):
- New 📎 button next to the textarea triggers a hidden file input.
- Picked files are FileReader-encoded to base64 and shown as a
thumbnail strip above the input bar, each with an × to remove.
- On send, images are packed into the WebSocket payload alongside
the text and cleared from the strip.
- User-message bubbles render any attached images inline.
- state_sync rehydration extracts image content from user messages so
past attachments survive a page reload.
- Mobile breakpoint shrinks the chips and bounds bubble images to 60vw.
The web UI previously had no way to navigate back to a prior chat — clicking + New silently abandoned the current session (the JSONL file on disk is preserved by pi-coding-agent, but the UI didn't expose it). Wires the SDK's existing capability — AgentSession.switchSession() and SessionManager.getSessionDir() — through to the user. Server (server/index.ts): - Add `list_sessions` WebSocket command. Reads the SessionManager's session directory, parses each .jsonl header, finds the first user message for a preview, sorts newest-first. - Add `switch_session` WebSocket command. Validates the requested file is inside the session directory (path-traversal guard), calls session.switchSession(path), then broadcasts state_sync so all connected clients re-render. Frontend (index.html, src/main.ts): - New "⌛ History" button in the header next to "+ New". - Clicking it sends `list_sessions` and shows a dialog (reusing the existing dialog-overlay) listing prior chats with timestamp + first user-message preview. The active session is highlighted. - Clicking an entry sends `switch_session` and the server broadcasts state_sync, which re-rehydrates the message list.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three additions tested running on a Mac, accessed from an iPhone via Tailscale.
1. Mobile-responsive layout (
38e796b)The existing layout was desktop-only; on a phone the input bar sat below the visible viewport (iOS Safari
100vhincludes the URL-bar area) and message text overflowed off-screen.@media (max-width: 640px)breakpoint tightens header / message / input-bar padding.font-sizeto 16px on small screens so iOS Safari doesn't auto-zoom on focus.overflow-wrap: anywhereon message text and bubbles so long unbroken strings (URLs, tokens) can't push the layout wide.min-width: 0on the prompt-input so flex doesn't keep it stuck at placeholder-text width.overflow-x: hiddenon#appas a safety net.#appheight:100vh→100dvh(with100vhfallback) so the input bar stays inside the visible viewport on mobile Safari when the URL bar is showing.2. Image attachments (
d48d3f6)The pi SDK already accepts an
images?: ImageContent[]array onPromptOptions; this wires the existing capability through to the user.Server (
server/index.ts):imagesfield on thepromptWebSocket command.session.prompt(text, { images }).Frontend (
index.html,src/main.ts,src/style.css):state_syncrehydration extracts image content from past user messages so attachments survive a page reload.Note: whether the agent can see the attached image depends on the active model. Vision-capable models render and reason about it; text-only models receive the payload but ignore the image content.
3. Session list + resume (
dcd2e37)Previously there was no way to navigate back to a prior chat — clicking + New silently abandoned the current session (the JSONL file on disk was preserved, but the UI didn't expose it). Wires the SDK's existing capability —
AgentSession.switchSession()andSessionManager.getSessionDir()— through to the user.Server:
list_sessionsWebSocket command. Reads the SessionManager's session directory, parses each.jsonlheader, finds the first user message for a preview snippet, sorts newest-first.switch_sessionWebSocket command. Validates the requested file is inside the session directory (path-traversal guard), callssession.switchSession(path), then broadcastsstate_syncso all connected clients re-render.Frontend:
list_sessions→ dialog (reusing the existingdialog-overlay) lists prior chats with timestamp + first user-message preview. The active session is highlighted.switch_session→ server broadcastsstate_sync→ message list re-hydrates.Test plan
npm run buildandnpm run build:serverboth clean.127.0.0.1:8080.serveproxy delivers HTTPS to a phone, layout fits without horizontal overflow.{ type: "image", data, mimeType }shape.⌛ Historylists prior sessions in this cwd; clicking one swaps the chat in place.