Commit Graph

474 Commits

Author SHA1 Message Date
Fusion 738e01bb7c fix: add window resize fallback and delay refresh to next frame
- Add window resize listener as fallback for ResizeObserver
- Use 250ms debounce to avoid early layout reads
- Delay term.refresh() to next animation frame so renderer
  can process resize before we force redraw
- Clean up window resize listener on unmount
2026-05-24 19:31:15 +02:00
Fusion 4d0c70de98 fix: hide stty resize command from terminal output using ANSI escapes 2026-05-24 19:17:54 +02:00
Fusion 701bd57293 fix: send stty resize on every resize, not just first time
The _stty_sent guard prevented the container shell from updating its
terminal size after the first resize. This caused visual mismatches
where xterm.js displayed at the new size but the shell still wrapped
output at the old size.

Remove the guard so stty is sent on every resize event.
2026-05-24 19:07:37 +02:00
Fusion 85f04447ea fix: force xterm.js canvas redraw on resize via internal renderer 2026-05-24 18:51:15 +02:00
Fusion d931f3071d Revert "fix: add window resize listener and refresh on font size change"
This reverts commit 4a356fe88e.
2026-05-24 18:42:14 +02:00
Fusion 4a356fe88e fix: add window resize listener and refresh on font size change
- Add window resize listener to complement ResizeObserver
- Clear window resize timeout on cleanup
- Force term.refresh() after font size changes
- Send resize message after font size change
2026-05-24 18:18:41 +02:00
Fusion ca22e9c9d2 fix: reset xterm position to relative on mobile to prevent layout issues 2026-05-24 18:13:28 +02:00
Fusion 4de312c170 fix: terminal resize propagation and redraw
- Frontend: Add ResizeObserver with dimension tracking for accurate resize detection
- Frontend: Fix cleanup function to properly disconnect ResizeObserver
- Frontend: Use CSS grid for terminal wrapper layout
- Backend: Add duplicate dimension check to avoid unnecessary resizes
- Backend: Ensure stty command is sent correctly to container shell
2026-05-24 17:44:00 +02:00
Fusion e7a89a853f fix: ensure terminal container fills viewport and redraws on resize
Issues fixed:
1. Terminal container now has explicit width: 100% and height: 100%
2. Added term.refresh() after fit() to force redraw when dimensions change
3. Changed shell-body from min-height to height for definite sizing
4. Added .xterm-viewport width: 100% to ensure proper filling

This ensures the terminal properly fills the viewport and redraws
content when the window is resized.
2026-05-24 17:12:32 +02:00
Fusion 7b23618ae7 fix: use requestAnimationFrame before fit() on window resize
When window resize fires, CSS layout hasn't settled yet. Adding
requestAnimationFrame ensures the browser has calculated new sizes
before xterm.js fit() reads the container dimensions. Reduced
debounce from 250ms to 100ms since rAF handles the layout timing.
2026-05-24 17:03:25 +02:00
Fusion 8b4e1a7428 fix: ensure shell-content fills available viewport height
The terminal page uses height: 100% but parent .shell-content didn't
have explicit height, so the terminal couldn't fill the viewport.

Changes:
- .shell-content: added height: 100%
- .shell-body: added flex: 1 to fill flex parent
- Mobile .shell-content: added height: 100%

This ensures the terminal wrapper can properly calculate and fill
the available viewport space.
2026-05-24 17:01:15 +02:00
Fusion f37813a317 revert: remove ResizeObserver and stty-on-every-resize to fix infinite loop
The ResizeObserver detected size changes caused by the stty command
output appearing in the terminal, creating an infinite resize loop:
1. Resize detected -> fit() -> send resize to backend
2. Backend sends stty command through PTY
3. stty text appears in terminal output
4. ResizeObserver detects content height change
5. fit() calculates new rows -> send resize
6. Loop continues forever

Reverted to:
- Window resize event instead of ResizeObserver
- stty command only sent once on first resize

This means the container shell stays at the initial size and won't
dynamically resize when the browser window changes, but prevents
the infinite loop.
2026-05-24 16:54:05 +02:00
Fusion 6e600fdbcd fix: use ResizeObserver for more reliable terminal resize detection
Window resize events fire before CSS layout settles, so FitAddon
was reading stale container dimensions. ResizeObserver fires after
the element actually changes size, ensuring fit() gets correct
dimensions. Reduced debounce from 250ms to 100ms for snappier response.
2026-05-24 16:50:34 +02:00
Fusion f4211ad452 chore: remove debug console.log statements from terminal component 2026-05-24 16:40:05 +02:00
Fusion 058c501e4a fix: prevent terminal from growing beyond viewport on resize
Added max-height constraints at multiple levels:
- .mobile-terminal-wrapper: max-height 100vh/100dvh
- .mobile-terminal-content: max-height 100%, min-height 0
- .terminal-container: max-height 100%
- .xterm: max-height 100%
- .xterm-viewport: max-height 100% + overflow-y auto

This prevents xterm.js from expanding the container when fit() adds rows,
which was causing an infinite growth loop on window resize.
2026-05-24 16:37:18 +02:00
Fusion 74033243c9 feat: send stty resize command on every resize, not just first
Previously the stty command was only sent on the first resize. Now it
is sent every time the terminal dimensions change, so resizing the
browser window or rotating the device properly updates the container
shell size. Added a check to skip when dimensions haven't changed.
2026-05-24 16:27:37 +02:00
Fusion 9910fd4445 fix: send stty command to resize container shell on first resize
Docker exec doesn't forward PTY resize to the container process,
so the container bash stays at 80x24 regardless of frontend resize.
Work around this by sending a stty command through the terminal
on first resize to set the correct dimensions inside the container.
2026-05-24 16:25:14 +02:00
Fusion 4a66a4a384 fix: pass instance_id to _write_loop to resolve NameError
The write loop was crashing with 'name instance_id is not defined' when
processing resize messages. This caused the connection to drop with 1006
and the frontend to reconnect in a loop. Fixed by passing instance_id
as a parameter to _write_loop. Also cleaned up debug logging.
2026-05-24 16:18:53 +02:00
Fusion fa20d00d14 debug: add loop exit logging to terminal WebSocket handler 2026-05-24 16:13:44 +02:00
Fusion f59274ae64 revert: remove explicit WebSocket close that caused immediate disconnection 2026-05-24 16:12:21 +02:00
Fusion b89fb608b6 fix: explicitly close WebSocket with code 1000 when loops end
When any of the read/write/heartbeat loops ends, we were cancelling
remaining tasks but not explicitly closing the WebSocket. This caused
the connection to be dropped with 1006 abnormal closure instead of
a clean 1000 close. The frontend then reconnected, creating a loop.
2026-05-24 16:08:51 +02:00
Fusion 116cd22ff8 revert: remove stty resize workaround that caused 1006 loops 2026-05-24 16:06:00 +02:00
Fusion 0094ba01cd fix: send stty command to resize container shell
Docker exec doesn't forward PTY resize to the container process,
so the container bash stays at 80x24 regardless of frontend resize.
Work around this by sending a stty command through the terminal
on first resize to set the correct dimensions inside the container.
2026-05-24 16:04:00 +02:00
Fusion f6fb984ec6 revert: remove SIGWINCH signal that caused connection loops
Sending SIGWINCH to the docker exec process was crashing/killing it,
which closed the PTY and caused WebSocket 1006 abnormal closure loops.
Reverting to the original TIOCSWINSZ-only approach.
2026-05-24 16:00:25 +02:00
Fusion 0dba13a354 fix: send SIGWINCH to docker exec after PTY resize
When resizing the PTY, docker exec needs to be notified so it can
re-read the terminal size and propagate it to the container's PTY.
Without this, the container shell stays at 80x24 regardless of what
the frontend sends.
2026-05-24 15:57:29 +02:00
Fusion 5500552993 fix: send terminal resize immediately on WebSocket connect
- Backend PTY starts with default 80x24 dimensions
- Previous code only sent resize during layout changes
- Now sends current terminal size immediately when WebSocket opens
- Ensures PTY is properly sized before shell starts rendering
2026-05-24 15:42:22 +02:00
Fusion fed49dba6d debug: add logging and simplify fit logic
- Simplified fit logic: just fit after open, after fonts load, and on resize
- Added console logging to debug what FitAddon calculates
- Single fitTerminal() function used everywhere
- Removed complex retry logic that wasn't working
2026-05-24 15:30:34 +02:00
Fusion fa17b13413 fix: wait for fonts and retry fit until proper dimensions
- Wait for document.fonts.ready before fitting (ensures correct cell metrics)
- Retry fit every 100ms if rows <= 1 or cols <= 10 (layout still settling)
- Up to 30 retries (3 seconds) for layout to stabilize
- Remove redundant delayed fits, keep only header auto-hide fit at 4s
2026-05-24 15:25:47 +02:00
Fusion 38185b9659 fix: remove container ResizeObserver causing infinite growth loop
- Container-level ResizeObserver created feedback loop with fitAddon.fit()
- Removed it, kept initialization-time dimension check only
- Rely on window resize listener for viewport changes
2026-05-24 15:19:31 +02:00
Fusion 07e7c6ea0f fix: wait for container dimensions before xterm init
- xterm docs require parent to have dimensions when open() is called
- Added ResizeObserver to wait for non-zero dimensions before initializing
- Added container ResizeObserver to handle resizes (header hide, keyboard)
- Fixed cleanup to properly disconnect observers and handle uninitialized ws
2026-05-24 15:16:11 +02:00
Fusion b638dccd36 Merge branch 'dev' of ssh://git.commumedia.org:2222/alex/headquarter into dev 2026-05-24 15:02:56 +02:00
Fusion 8f7e19fdb1 fix: remove conflicting CSS that broke terminal sizing
- Remove second .terminal-wrapper.mobile definition that overrode position:absolute
- Add flex display to .xterm for proper viewport filling
- Add position:relative to mobile terminal-container
- Remove manual dimension setting workaround from terminal.tsx
- Root cause: CSS specificity conflict caused FitAddon to read height=0
2026-05-24 15:02:40 +02:00
alex ba76f09a1c Merge branch 'dev' of ssh://git.commumedia.org:2222/alex/headquarter into dev 2026-05-24 12:59:36 +00:00
alex 8b08c3886c fix: prevent reconnection loop on concurrent connection close
- Don't reconnect when server closes old connection with code 4000
- Code 4000 means new connection was established, not an error
- Prevents infinite reconnection loop between old/new connections

Refs: terminal switching between 4000 error and connected
2026-05-24 12:59:28 +00:00
Fusion 5577e19782 fix: set explicit container dimensions before xterm init
- Measure parent dimensions and set them on container before term.open()
- Ensures FitAddon gets correct dimensions on initialization
- Prevents 1-row/1-col calculation that breaks scrolling and sizing
2026-05-24 14:57:03 +02:00
Fusion 268651bab0 Merge branch 'dev' of ssh://git.commumedia.org:2222/alex/headquarter into dev 2026-05-24 14:48:45 +02:00
Fusion 7389344b6d fix: defer terminal manager idle check until event loop is running
TerminalManager was trying to create an asyncio task at module import time,
but no event loop exists yet during import. This caused RuntimeError on startup.

Changes:
- _start_idle_check() now checks if event loop is running before creating task
- If no loop exists, silently skips (will be started lazily)
- Added lazy start call in get_or_create_session() when websocket connects
2026-05-24 14:48:30 +02:00
alex 09938bede4 Merge branch 'dev' of ssh://git.commumedia.org:2222/alex/headquarter into dev 2026-05-24 12:45:59 +00:00
alex 073013bc61 feat: add heartbeat/ping to terminal WebSocket
- Backend: Send ping every 30s from WebSocket endpoint
- Frontend: Respond to pings with pongs, detect missed pings (60s timeout)
- Update type definitions to include 'resetting' status

Refs: persistent-terminal-sessions task 6.4
2026-05-24 12:45:50 +00:00
Fusion 865b9411da fix: add 'resetting' status to terminal callback types
TypeScript build failed because 'resetting' status was not included
in the onTerminalReady callback type definition.

Updated types in:
- TerminalComponent props
- MobileTerminalWrapper state and callback
- MobileTerminalHeader props
2026-05-24 14:43:27 +02:00
Fusion 48d1a7d05c Merge branch 'dev' of ssh://git.commumedia.org:2222/alex/headquarter into dev 2026-05-24 14:39:20 +02:00
Fusion ab1d3a6aa1 fix: use CSS Grid for mobile terminal layout
Replace flexbox chains with CSS Grid to give content area definite height:
- grid-template-rows: auto 1fr auto for header/content/keys
- Use 100dvh for proper mobile viewport handling
- Terminal fills content area with position: absolute
- Remove mobile-terminal-shell wrapper (redundant)
- Content area gets real height from grid, fixing FitAddon calculations
2026-05-24 14:39:06 +02:00
alex d1c187ab16 feat: implement persistent terminal sessions
- Terminal sessions now persist across WebSocket disconnections
- Added circular output buffer (10KB) for replay on reconnect
- Added idle timeout cleanup (30 minutes)
- Added reset functionality via WebSocket message and HTTP endpoint
- Concurrent connections close old WebSocket when new one connects
- Frontend: Added reset button with confirmation dialog
- Frontend: Handle resetting status and reconnection

Refs: persistent-terminal-sessions
2026-05-24 12:35:52 +00:00
Fusion 39cf01c3c9 fix: use absolute positioning for xterm.js to fill container
- Make .terminal-container position: relative with overflow: hidden
- Make xterm element absolutely positioned to fill container
- This ensures xterm.js always has concrete dimensions for fitAddon
- Remove conflicting height: 100% !important overrides
- Terminal now properly fills available space and calculates correct rows
2026-05-24 14:28:03 +02:00
Fusion c49bb028c4 fix: remove ResizeObserver to prevent infinite resize loop
The ResizeObserver triggered fit() which changed canvas dimensions,
triggering the observer again in an infinite loop. We already have
window resize handling and delayed fit() calls, so the observer was
redundant.
2026-05-24 14:23:34 +02:00
Fusion 0baf7f7750 Merge branch 'dev' of ssh://git.commumedia.org:2222/alex/headquarter 2026-05-24 14:15:26 +02:00
Fusion 6e496e102d fix: terminal sizing and newline rendering issues
- Add ResizeObserver to terminal container for responsive sizing
  (catches keyboard open/close, header auto-hide, layout changes)
- Remove padding from mobile terminal container to maximize space
- Fix CSS: ensure xterm viewport fills container height properly
- Fix session-card.tsx TypeScript error (removed non-existent port field)
- Remove explicit xterm-viewport/xterm-screen width overrides that
  interfered with xterm.js canvas sizing
2026-05-24 14:14:45 +02:00
alex 7cb88a3163 Merge branch 'dev' of ssh://git.commumedia.org:2222/alex/headquarter into dev 2026-05-24 12:07:54 +00:00
alex ce1a73abce feat: add styles and polish for unified session list components
- Add CSS styles for SessionCard and SessionList components
- Add responsive styles for mobile viewport
- Fix TypeScript errors (remove unused port property)
- Fix ESLint errors (remove unused imports and variables)

Refs: session-list-overhaul tasks 5-6
2026-05-24 12:07:37 +00:00
Fusion 5fddc65468 Merge branch 'dev' of ssh://git.commumedia.org:2222/alex/headquarter into dev 2026-05-24 14:05:38 +02:00