[PR #8] feat: SSH session persistence across app background/foreground #6

Open
opened 2026-02-28 00:49:12 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/Termix-SSH/Mobile/pull/8
Author: @ZacharyZcR
Created: 2/22/2026
Status: 🔄 Open

Base: dev-1.3.0Head: feat/session-persistence


📝 Commits (1)

  • 4bf62fa feat: add SSH session persistence for background/foreground transitions

📊 Changes

2 files changed (+67 additions, -15 deletions)

View changed files

📝 app/tabs/sessions/terminal/NativeWebSocketManager.ts (+60 -11)
📝 app/tabs/sessions/terminal/Terminal.tsx (+7 -4)

📄 Description

Summary

  • Adapt mobile client to server-side session persistence protocol (depends on Termix PR #594): when the app goes to background and iOS/Android kills the WebSocket, the server keeps the SSH session alive (default 30 min). On foreground return, the client sends attachSession to reattach with buffered output replay instead of creating a new SSH connection.
  • Handle session lifecycle messages: sessionCreated, sessionAttached, sessionExpired (auto-fallback to fresh connect), and sessionTakenOver (multi-device graceful disconnect).
  • Send explicit disconnect on component destroy to clean up server-side sessions when the user intentionally closes a terminal tab.
  • Skip terminal clear and post-connection setup on reattach so the user sees continuous output without a jarring reset.

Files Changed

File Change
app/tabs/sessions/terminal/NativeWebSocketManager.ts Core session persistence logic — track serverSessionId, conditional attachSession vs connectToHost, new message handlers
app/tabs/sessions/terminal/Terminal.tsx Skip terminal reset and hasReceivedData clear on reattach

Test plan

  • Connect to a host → background the app for ~10s → return to foreground → verify session reattaches without terminal clear, previous output preserved
  • Connect to a host → background the app → wait for server timeout (default 30 min) → return → verify graceful fallback to fresh connection
  • Connect to a host → close the terminal tab → verify server-side session is destroyed (check server logs for session_destroyed)
  • Connect to same host from two devices → verify second device takes over, first shows disconnect
  • Connect to a host → toggle airplane mode → return → verify reconnection works (fresh connect since server lost the session)
  • Verify npx tsc --noEmit shows no new errors beyond pre-existing upstream issues

Note: This PR depends on the server-side session persistence feature from Termix PR #594. Without the server changes, the client will receive no sessionCreated messages and behave identically to the current version (always fresh connectToHost).

Fixes Termix-SSH/Support#364


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/Termix-SSH/Mobile/pull/8 **Author:** [@ZacharyZcR](https://github.com/ZacharyZcR) **Created:** 2/22/2026 **Status:** 🔄 Open **Base:** `dev-1.3.0` ← **Head:** `feat/session-persistence` --- ### 📝 Commits (1) - [`4bf62fa`](https://github.com/Termix-SSH/Mobile/commit/4bf62fa3b50e5180407131d927fd5cfde411816a) feat: add SSH session persistence for background/foreground transitions ### 📊 Changes **2 files changed** (+67 additions, -15 deletions) <details> <summary>View changed files</summary> 📝 `app/tabs/sessions/terminal/NativeWebSocketManager.ts` (+60 -11) 📝 `app/tabs/sessions/terminal/Terminal.tsx` (+7 -4) </details> ### 📄 Description ## Summary - **Adapt mobile client to server-side session persistence protocol** (depends on [Termix PR #594](https://github.com/Termix-SSH/Termix/pull/594)): when the app goes to background and iOS/Android kills the WebSocket, the server keeps the SSH session alive (default 30 min). On foreground return, the client sends `attachSession` to reattach with buffered output replay instead of creating a new SSH connection. - **Handle session lifecycle messages**: `sessionCreated`, `sessionAttached`, `sessionExpired` (auto-fallback to fresh connect), and `sessionTakenOver` (multi-device graceful disconnect). - **Send explicit `disconnect` on component destroy** to clean up server-side sessions when the user intentionally closes a terminal tab. - **Skip terminal clear and post-connection setup on reattach** so the user sees continuous output without a jarring reset. ## Files Changed | File | Change | |------|--------| | `app/tabs/sessions/terminal/NativeWebSocketManager.ts` | Core session persistence logic — track `serverSessionId`, conditional `attachSession` vs `connectToHost`, new message handlers | | `app/tabs/sessions/terminal/Terminal.tsx` | Skip terminal reset and `hasReceivedData` clear on reattach | ## Test plan - [ ] Connect to a host → background the app for ~10s → return to foreground → verify session reattaches without terminal clear, previous output preserved - [ ] Connect to a host → background the app → wait for server timeout (default 30 min) → return → verify graceful fallback to fresh connection - [ ] Connect to a host → close the terminal tab → verify server-side session is destroyed (check server logs for `session_destroyed`) - [ ] Connect to same host from two devices → verify second device takes over, first shows disconnect - [ ] Connect to a host → toggle airplane mode → return → verify reconnection works (fresh connect since server lost the session) - [ ] Verify `npx tsc --noEmit` shows no new errors beyond pre-existing upstream issues > **Note:** This PR depends on the server-side session persistence feature from [Termix PR #594](https://github.com/Termix-SSH/Termix/pull/594). Without the server changes, the client will receive no `sessionCreated` messages and behave identically to the current version (always fresh `connectToHost`). Fixes Termix-SSH/Support#364 --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/Mobile#6
No description provided.