Add terminal big mode, keyboard shortcuts menu, and UX refinements

- Reduce mobile terminal widths by 2 chars (portrait 42x24, landscape 86x24)
- Add "Big mode" for mobile: desktop sizing (120x36) at 70% zoom
- Click zoom percentage to reset to 100%
- Add keyboard shortcuts submenu in session settings
- Update PRD with all terminal features and documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-21 00:20:40 -05:00
parent 5171059692
commit a2e10688bf
7 changed files with 473 additions and 36 deletions
+276 -9
View File
@@ -339,6 +339,38 @@ stream_session_response(session_id, callback)
- Filters for `spiceflow-*` prefix
- Returns managed sessions only
#### 4.1.5 External Tmux Session Import
Users can import existing tmux sessions not managed by Spiceflow:
1. **List External:** `GET /api/tmux/external` returns sessions without `spiceflow-` prefix
2. **Import:** `POST /api/tmux/import` with session name
3. **Rename:** Server renames `{name}` to `spiceflow-{name}`
4. **Setup:** Enables pipe-pane capture for imported session
5. **Return:** Session available in Spiceflow with new prefixed ID
#### 4.1.6 Session Rename
Sessions can be renamed via `PATCH /api/sessions/:id`:
**Claude/OpenCode:**
- Updates title in database
- Session ID remains unchanged
**Tmux:**
- Renames tmux session via `tmux rename-session`
- **Session ID changes** to new `spiceflow-{name}` format
- Response includes `idChanged: true` and new session object
- Client navigates to new URL with `replaceState`
#### 4.1.7 Session Eject (Tmux only)
Removes session from Spiceflow management while keeping it running:
1. Rename tmux session from `spiceflow-{name}` to `{name}`
2. Delete session from Spiceflow database
3. Session continues running, attachable via `tmux attach -t {name}`
### 4.2 Process Handle Structure
```clojure
@@ -572,6 +604,11 @@ Permissions are recorded as assistant messages with metadata:
- **Examples:** `spiceflow-brave-fox-0042`, `spiceflow-calm-owl-1337`
- **Purpose:** Human-readable, unique identifiers
**Name Generation:**
- 30 adjectives × 30 nouns = 900 base combinations
- 4-digit random suffix (0000-9999)
- Docker-style naming convention
#### 7.1.2 Output Capture
```bash
@@ -635,10 +672,96 @@ tmux capture-pane -t {session-name} -p -e -S -1000
| Mode | Dimensions | Use Case |
|------|------------|----------|
| `portrait` | 40x24 | Phone portrait |
| `landscape` | 65x24 | Phone landscape |
| `desktop` | 100x24 | Split screen |
| `fullscreen` | 180x24 | Full terminal |
| `portrait` | 42x24 | Phone portrait |
| `landscape` | 86x24 | Phone landscape |
| `desktop` | 120x36 | Split screen |
| `fullscreen` | 260x36 | Full terminal |
### 7.5 Auto Orientation Detection
On mobile devices, the terminal automatically resizes when the user rotates their phone:
```javascript
screen.orientation.addEventListener('change', () => {
const type = screen.orientation.type;
if (type.includes('portrait')) {
resizeScreen('portrait');
} else if (type.includes('landscape')) {
resizeScreen('landscape');
}
});
```
**Trigger Conditions:**
- Only on mobile (width < 640px or height < 450px)
- Uses `screen.orientation` API (modern browsers)
### 7.6 Font Zoom Control
Terminal text size can be adjusted from 50% to 150% in 5% increments:
| Control | Action |
|---------|--------|
| `-` button | Decrease font scale |
| `+` button | Increase font scale |
| Percentage display | Shows current zoom; click to reset to 100% |
**Visibility:** Zoom controls hidden on mobile portrait, visible on landscape/desktop.
### 7.7 Big Mode
Mobile users can enable "Big mode" from the settings menu to view more terminal content:
- **Resize:** Sets terminal to desktop dimensions (120x36)
- **Zoom:** Sets font scale to 70%
- **Access:** Settings menu (gear icon) → "Big mode" button
- **Visibility:** Only shown for tmux sessions on mobile devices
### 7.8 Session Eject
Tmux sessions can be "ejected" from Spiceflow management while keeping them running:
1. User clicks "Eject session" in settings menu
2. Server renames session from `spiceflow-{name}` to `{name}`
3. Session removed from Spiceflow database
4. User can reattach manually via `tmux attach -t {name}`
**Use Case:** Transfer session to local terminal for continued work.
### 7.9 Keyboard Shortcuts
| Shortcut | Action |
|----------|--------|
| `Ctrl+Down` | Scroll to bottom |
| `Ctrl+Shift+V` | Paste from clipboard |
| `Shift+Enter` | Send literal newline |
| `Shift+Tab` | Send reverse-tab escape sequence |
| `^` toggle | Enable Ctrl mode (next letter sends control character) |
### 7.10 Quick Action Buttons
| Button | Function | Color |
|--------|----------|-------|
| `^` | Toggle Ctrl mode | Gray (cyan ring when active) |
| `^C` | Send interrupt | Red |
| `^D` | Send EOF | Amber |
| `y` | Send 'y' | Green |
| `n` | Send 'n' | Red |
| `1-4` | Send number | Gray |
| `⇥` | Send Tab | Cyan |
| `⇤` | Send Shift+Tab | Cyan |
| `↵` | Send Enter | Green |
| `📋` | Paste clipboard | Violet |
**Visibility:** `^`, `y`, `n`, `1-4`, and paste hidden on mobile portrait.
### 7.11 ANSI Color Rendering
Terminal output preserves ANSI escape sequences:
- Converted to HTML via `ansi-to-html` library
- Default foreground: green (#22c55e)
- Background: transparent
- Supports standard terminal colors
---
@@ -954,6 +1077,23 @@ salt (16) || record_size (4) || keyid_len (1) || keyid (65) || ciphertext
}
```
#### POST /api/sessions/:id/eject
Ejects a tmux session from Spiceflow management (tmux only).
**Response:**
```json
{
"status": "ejected",
"message": "Session ejected. Reattach with: tmux attach -t {name}",
"session-name": "my-session"
}
```
**Errors:**
- 400: Not a tmux session
- 404: Session not found
---
## 10. WebSocket Protocol
@@ -1085,6 +1225,24 @@ salt (16) || record_size (4) || keyid_len (1) || keyid (65) || ciphertext
- **Heartbeat:** Ping every 25 seconds
- **Pong Timeout:** 10 seconds
### 10.5 Terminal Update Broadcasting
After tmux input, server broadcasts terminal updates:
1. Input received via `POST /api/sessions/:id/terminal/input`
2. Input sent to tmux immediately
3. 100ms delay for command execution
4. Fresh terminal content captured
5. Diff computed and broadcast via WebSocket
6. Broadcast always sent (even if unchanged) to ensure client sync
### 10.6 Full Frame Refresh
To handle potential drift, the server periodically sends full frames:
- Every 5 seconds during active streaming
- On explicit `fresh=true` request
- After terminal resize operations
---
## 11. User Interface
@@ -1097,6 +1255,9 @@ salt (16) || record_size (4) || keyid_len (1) || keyid (65) || ciphertext
┌─────────────────────────────────────────┐
│ ☰ Spiceflow 🔔 + ↻ │
├─────────────────────────────────────────┤
│ ┌─────────────────────────────────┐ │
│ │ ● 2 sessions processing │ │ (green badge, pulsing)
│ └─────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────┐ │
│ │ ● My Claude Session claude │ │
@@ -1108,14 +1269,19 @@ salt (16) || record_size (4) || keyid_len (1) || keyid (65) || ciphertext
│ │ /home/user 1d ago │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────┐ │
│ │ + Import tmux session │ │ (if external sessions exist)
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────┘
```
**Elements:**
- Header with branding and action buttons
- Processing sessions counter (green pulsing badge)
- Session cards with status indicators
- Provider badges (color-coded)
- Relative timestamps
- Import button for external tmux sessions
#### Session Page (`/session/:id`)
@@ -1135,10 +1301,15 @@ salt (16) || record_size (4) || keyid_len (1) || keyid (65) || ciphertext
│ └─────────────────────────────────┘ │
│ │
├─────────────────────────────────────────┤
│ [Type a message... ] [➤] │
[⌨] [Type a message... ] [➤] │
└─────────────────────────────────────────┘
```
**Mobile Keyboard Toggle:**
- `⌨` button shows/hides mobile keyboard
- Addresses issue where keyboard can hide input field
- Toggles between up/down arrow indicators
**Terminal Mode (tmux):**
```
┌─────────────────────────────────────────┐
@@ -1164,7 +1335,7 @@ salt (16) || record_size (4) || keyid_len (1) || keyid (65) || ciphertext
│ ⚠️ Claude needs permission │
├─────────────────────────────────────────┤
│ │
│ Write: /home/user/foo.md
│ Write: /home/user/foo.md .md (file extension badge)
│ ┌─────────────────────────────────┐ │
│ │ + 1 # My Haiku │ │
│ │ + 2 │ │
@@ -1177,6 +1348,14 @@ salt (16) || record_size (4) || keyid_len (1) || keyid (65) || ciphertext
└─────────────────────────────────────────┘
```
**File Diff Viewer:**
- **Write operations:** All lines shown as green additions (+)
- **Edit operations:** Old lines in red (-), new lines in green (+)
- **Line numbers:** Shown for both old and new content
- **File extension badge:** Displayed in top-right corner
- **Hover highlighting:** Lines highlight on mouse over
- **Tab handling:** Tabs rendered as 4 spaces
### 11.3 Component Inventory
| Component | Purpose | Props |
@@ -1194,9 +1373,65 @@ salt (16) || record_size (4) || keyid_len (1) || keyid (65) || ciphertext
| Breakpoint | Header | Layout |
|------------|--------|--------|
| Portrait | Full header | Vertical stack |
| Landscape mobile | Hamburger menu | Compact header |
| Desktop | Full header | All controls visible |
| Portrait (<640px width, >450px height) | Full header | Vertical stack |
| Landscape mobile (<450px height) | Hamburger menu | Compact header |
| Desktop (≥640px width, ≥450px height) | Full header | All controls visible |
| XL Desktop (≥1280px width) | Full header | Mobile orientation buttons hidden |
### 11.5 Mobile-Specific UI Classes
| CSS Class | Behavior |
|-----------|----------|
| `portrait-hide` | Hidden on mobile portrait (width < 640px AND height > 450px) |
| `desktop-only` | Hidden on mobile (width < 640px OR height < 450px) |
| `mobile-only` | Hidden on XL desktop (width ≥ 1280px) |
| `landscape-mobile:hidden` | Hidden when height < 450px |
| `landscape-menu` | Shown only when height < 450px |
### 11.6 Message Condensing
Long messages (5+ lines) can be collapsed:
- **Threshold:** 5 lines minimum to show collapse toggle
- **Preview:** Shows first 3 lines when collapsed
- **Toggle:** Chevron indicator expands/collapses
- **Bulk action:** "Condense all" in settings menu
### 11.7 Thinking Indicator
Animated indicator when Claude is processing:
- Three bouncing dots (●●●)
- Separate from streaming content display
- Disappears when response completes or permission requested
### 11.8 Auto-Scroll Control
- **Default:** Enabled
- **Persistence:** Saved to localStorage (`spiceflow-auto-scroll`)
- **Toggle:** Available in session settings menu
- **Behavior:** Scrolls to bottom on new content
- **Override:** Ctrl+Down forces scroll regardless of setting
### 11.9 Session Status Indicators
| Status | Indicator |
|--------|-----------|
| Idle | Gray dot (static) |
| Processing | Green dot (pulsing) |
| Awaiting Permission | Amber dot (pulsing) |
| Tmux Alive | Green dot |
| Tmux Dead | Gray dot |
### 11.10 Markdown Rendering
Assistant messages render Markdown with:
- Headings (h1-h6) with appropriate sizing
- Code blocks with monospace font and background
- Inline code with background highlight
- Lists (ordered and unordered)
- Blockquotes with left border
- Links styled in orange (spice color)
- Line breaks preserved (`breaks: true`)
---
@@ -1262,6 +1497,38 @@ salt (16) || record_size (4) || keyid_len (1) || keyid (65) || ciphertext
8. User taps notification → app opens to session
9. User sees permission UI, responds
### 12.6 Import External Tmux Session
1. User has existing tmux session running (e.g., `dev-session`)
2. User opens Spiceflow home page
3. "Import tmux session" button appears
4. User clicks import → dropdown shows available sessions
5. User selects `dev-session`
6. Server renames to `spiceflow-dev-session`
7. Session appears in Spiceflow list
8. User can now manage session via Spiceflow
### 12.7 Eject Tmux Session
1. User opens tmux session in Spiceflow
2. User clicks settings gear (⚙️)
3. User clicks "Eject session"
4. Confirmation alert shows reattach command
5. Session renamed from `spiceflow-{name}` to `{name}`
6. User redirected to home page
7. Session removed from Spiceflow but continues running
8. User can reattach via `tmux attach -t {name}`
### 12.8 Rotate Phone (Terminal)
1. User viewing terminal session on phone
2. User rotates phone from portrait to landscape
3. `screen.orientation` change event fires
4. App detects orientation is now landscape
5. Terminal automatically resizes to landscape dimensions (88x24)
6. Fresh terminal content fetched after 150ms
7. UI updates to show landscape-specific controls
---
## 13. Security Considerations