Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
253e5e4
docs(screenshots): add feature screenshots grouped by section + integ…
thangnm93 Jun 8, 2026
140d8fd
fix(host-panel): pre-populate password field when editing existing host
thangnm93 Jun 9, 2026
6583829
docs(spec): add K8s panel completion design (context switcher, logs, …
thangnm93 Jun 9, 2026
54f9909
docs(plan): add K8s panel completion implementation plan
thangnm93 Jun 9, 2026
e712eb6
feat(ssh): add execStream for persistent exec channels
thangnm93 Jun 9, 2026
3307c52
feat(k8s): add listContexts / parseContextNames to ContainerService
thangnm93 Jun 9, 2026
c095a7e
feat(k8s): add K8sForwardHandle model
thangnm93 Jun 9, 2026
f6bee8e
fix(k8s): make K8sForwardHandle.stop() exception-safe and re-entrant
thangnm93 Jun 9, 2026
ca0e31e
feat(k8s): add streamLogs and startPodPortForward to ContainerService
thangnm93 Jun 9, 2026
96a268b
feat(k8s): add streamLogs and startPodPortForward to ContainerService
thangnm93 Jun 9, 2026
e5a6e73
feat(k8s): add KubernetesPanel widget
thangnm93 Jun 9, 2026
5e6899b
feat(k8s): add KubernetesPanel widget with context switcher, logs, po…
thangnm93 Jun 9, 2026
d292245
refactor(containers): delegate K8s tab to KubernetesPanel
thangnm93 Jun 9, 2026
f85944c
feat(devops): add onOpenBrowser to DevOpsPluginConfig
thangnm93 Jun 9, 2026
c4e967b
perf: cut CPU/memory hotspots in k8s forward, dashboard, external edit
thangnm93 Jun 9, 2026
9402cba
test(host-panel): provide SshService in HostDetailPanel harnesses
thangnm93 Jun 9, 2026
e29adcd
docs: bump to 0.1.34 — update README, CHANGELOG, roadmap
thangnm93 Jun 9, 2026
f265609
docs: use lightweight README logo + trim feature list
thangnm93 Jun 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions .claude/skills/yourssh-screenshots/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
name: yourssh-screenshots
description: Use when the user wants to update, refresh, or add screenshots for the YourSSH app — e.g. "chụp screenshot", "cập nhật screenshots", "refresh screenshots", "add screenshots for new feature", or after a UI change.
---

# yourssh-screenshots

Captures screenshots of every YourSSH feature screen using Flutter integration tests (render tree — no macOS Screen Recording permission needed). Saves PNGs to `screenshots/<group>/`, then updates README.

## Quick Reference

```bash
# Capture all general feature screenshots
cd app && flutter test integration_test/feature_screenshots_test.dart -d macos

# Capture RDP-specific screenshots (requires Docker)
cd app && flutter test integration_test/rdp_screenshots_test.dart -d macos
```

## Folder Structure

```
screenshots/
01-terminal-ssh/ # Dashboard, host editor, SSH terminal
02-sftp/ # Dual-panel SFTP
03-port-forwarding/ # Port forward rules
04-credentials-security/ # Keychain, known hosts
05-settings/ # Settings sections
06-plugins/ # Plugin manager
07-rdp/ # RDP workspace (populated by rdp test)
08-devops/ # DevOps hub
10-audit-recording/ # Audit log, recording library
*.png # Legacy flat screenshots (keep for features needing live connections)
```

## How It Works

`integration_test/feature_screenshots_test.dart`:
1. Backs up user's real host data
2. Seeds demo hosts + port forward rules into SharedPreferences
3. Launches `app.main()` via Flutter integration test harness
4. Navigates each sidebar section by tapping the nav label text
5. Captures frames via `RendererBinding.instance.renderViews.first`
6. Restores user data in `finally`

`integration_test/rdp_screenshots_test.dart`:
- Requires `docker run -d --name yourssh-rdp-demo -p 3389:3389 scottyhardy/docker-remote-desktop:latest`
- Connects to a real xrdp container; captures fullscreen + TOFU dialog screenshots

## Adding a New Screen

1. Open `app/integration_test/feature_screenshots_test.dart`
2. Navigate to the screen with `_navTo(tester, 'Label')` or tap the relevant widget
3. Call `await _snap(tester, '$_gN/filename.png')` where `_gN` is the group constant
4. Add a new group constant if needed: `const _gN = '$_outDir/NN-group-name';`
5. Run the test to verify
6. Add the `<img src="screenshots/NN-group-name/filename.png"/>` entry to README under the correct section

## Updating README

The `## Screenshots` section in `README.md` is organized by feature groups matching the folder structure. Each group uses an HTML `<table>` with 2-column rows:

```html
### Group Name
<table>
<tr>
<td align="center"><b>Screen Title</b><br/><img src="screenshots/NN-group/filename.png"/></td>
<td align="center"><b>Screen Title</b><br/><img src="screenshots/NN-group/filename.png"/></td>
</tr>
</table>
```

After updating, verify all paths exist:
```bash
grep -o 'screenshots/[^"]*\.png' README.md | while read p; do
[ -f "$p" ] && echo "OK: $p" || echo "MISSING: $p"
done
```

## Key Implementation Details

- **Storage keys**: `yourssh.hosts`, `yourssh.known_hosts`, `yourssh.port_forwards` (not bare `hosts`)
- **Nav tap**: `find.text('Port Forwarding')`, `find.text('Known Hosts')`, etc. — matches sidebar label text
- **`_snap` helper**: pumps 200ms before capture to let animations settle
- **Debounce update check**: set `last_update_check` to `DateTime.now().millisecondsSinceEpoch` to prevent update banner polluting shots
- **PortForward JSON**: stored as a flat list, `type` is the enum name (`local`, `remote`, `dynamic`)

## Common Mistakes

| Problem | Fix |
|---|---|
| `screencapture` fails | Use integration test — no Screen Recording permission needed |
| Wrong prefs key | Use `yourssh.hosts` not `hosts`; `yourssh.port_forwards` not `port_forwards` |
| Screenshot is blank/clipped | Increase pump delay in `_snap` or add explicit `_waitFor` before snap |
| Update banner appears | Set `last_update_check` to now in test setup |
| User data not restored | Wrap all test steps in `try { ... } finally { restore }` |
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [0.1.34] — 2026-06-08

### Added
- **Kubernetes panel** — `KubernetesPanel` widget inside the DevOps plugin: context switcher, streamed `kubectl logs -f` in a scrollable sheet, and 1-click port-forward (`kubectl port-forward`) via `ContainerService.execStream`; namespace filter + all-namespaces toggle
- **`onOpenBrowser` DevOps callback** — `DevOpsPluginConfig` gains an `onOpenBrowser` callback so the host app can handle in-app browser navigation from DevOps tools without a hard dependency on the WebTools plugin
- **Keyword highlighting** — user-defined regex rules tint matching terminal output at paint time in the xterm fork; defaults ship with Error/Warning/Fail rules (red/yellow/cyan); toggle + rule list + add/edit dialog + color picker in Settings → Terminal and the terminal config side panel; rules persisted in `SettingsProvider`
- **Server monitor panel** — per-host live dashboard (CPU / memory / disk / uptime / listening ports / firewall status) in a draggable bottom sheet; access from the host card hover button or right-click context menu; `SystemStatsService` polls every 5 s via a single compound SSH exec with sentinel markers; `FirewallStatusService` polls every 30 s and auto-detects ufw / iptables / nftables; requires an active SSH session
- **Network discovery** — scan the local network for SSH/RDP hosts without typing an IP; `NetworkDiscoveryService` combines mDNS (`_ssh._tcp`, `_rdp._tcp`) and a configurable TCP port scan on the local subnet; results appear in a bottom sheet with one-tap **Add Host**; also reachable from a **Scan network** link in the Add Host panel
Expand All @@ -27,6 +29,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Network discovery: silent error catches replaced with `debugPrint` logging; `_loadSubnets` now handles `NetworkInterface.list` failures gracefully; scan errors shown in the UI
- `DiscoveredHost.merge()` now preserves source when merging two hosts from the same discovery method

### Performance
- Dashboard sort memoization — `HostsDashboard` no longer re-sorts the full host list on every keystroke; added an `identical`-based memo (`_memoSortedHosts`) and a set-based selection cleanup; O(n log n) per build → amortized O(1) for unchanged inputs
- External-edit watcher deduplication — `ExternalEditService._startWatcher` cancels any existing watcher for the same (host, remote path) before creating a new one, preventing duplicate poll timers when a file is re-opened
- K8s port-forward log-line accumulation — `ContainerService.startPodPortForward` listener early-returns after `Forwarding from` is matched instead of accumulating all kubectl output indefinitely

---

## [0.1.33] — 2026-06-07
Expand Down
83 changes: 68 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<p align="center">
<img src="app/assets/app_icon.png" alt="YourSSH" />
<img width="120" src="app/assets/logo-readme.png" alt="YourSSH" />
<h1 align="center">YourSSH</h1>
<p align="center">
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT" /></a>
Expand Down Expand Up @@ -86,6 +86,7 @@ sudo dpkg -r yourssh
- **Jump host / bastion proxy** — connect to internal servers via a bastion host; select any saved host as the jump hop in the host detail panel
- **SSH agent forwarding** — per-host toggle (like `ssh -A`) to hop between servers with the keys on your local machine; serves your system agent, falling back to app-Keychain keys when no agent is running — private keys never leave your machine; a status line in the host panel and a per-session key icon show whether forwarding is ready, active, on Keychain fallback, or refused by the server
- **Local shell** — spawn native macOS/Windows/Linux shell alongside SSH sessions
- **Keyword highlighting** — user-defined regex rules tint matching terminal output; ships with Error/Warning/Fail defaults (red/yellow/cyan); toggle, rule list, add/edit dialog, and per-rule color picker in Settings → Terminal and the terminal config side panel
- **xterm-256color** terminal emulation with full PTY support

### File Management
Expand Down Expand Up @@ -148,54 +149,106 @@ sudo dpkg -r yourssh

## Screenshots

### Terminal & SSH

<table>
<tr>
<td align="center"><b>Home — Host List</b><br/><img src="screenshots/01-home-hosts.png"/></td>
<td align="center"><b>Hosts Dashboard</b><br/><img src="screenshots/01-terminal-ssh/01-hosts-dashboard.png"/></td>
<td align="center"><b>New Host Panel (SSH)</b><br/><img src="screenshots/01-terminal-ssh/02-new-host-panel-ssh.png"/></td>
</tr>
<tr>
<td align="center"><b>SSH Terminal with AI Assistant</b><br/><img src="screenshots/02-ssh-terminal-ai.png"/></td>
<td align="center"><b>Dashboard — RDP Host Badges</b><br/><img src="screenshots/01-terminal-ssh/04-dashboard-with-rdp-badge.png"/></td>
</tr>
</table>

### SFTP

<table>
<tr>
<td align="center"><b>SFTP File Browser</b><br/><img src="screenshots/03-sftp-browser.png"/></td>
<td align="center"><b>Plugins</b><br/><img src="screenshots/04-plugins.png"/></td>
<td align="center"><b>Dual-Panel SFTP Browser</b><br/><img src="screenshots/02-sftp/01-sftp-browser.png"/></td>
</tr>
</table>

### Port Forwarding

<table>
<tr>
<td align="center"><b>DevOps Hub — Network Tools</b><br/><img src="screenshots/05-devops-hub-network-tools.png"/></td>
<td align="center"><b>Web Tools — HTTP Client</b><br/><img src="screenshots/08-web-tools-http-client.png"/></td>
<td align="center"><b>Port Forward Rules</b><br/><img src="screenshots/03-port-forwarding/01-port-forward-rules.png"/></td>
</tr>
</table>

### Credentials & Security

<table>
<tr>
<td align="center"><b>Snippets</b><br/><img src="screenshots/09-snippets.png"/></td>
<td align="center"><b>Settings — Sync</b><br/><img src="screenshots/06-settings-sync.png"/></td>
<td align="center"><b>SSH Keychain</b><br/><img src="screenshots/04-credentials-security/01-keychain.png"/></td>
<td align="center"><b>Known Hosts</b><br/><img src="screenshots/04-credentials-security/02-known-hosts.png"/></td>
</tr>
</table>

### Settings

<table>
<tr>
<td align="center"><b>Connection &amp; Terminal</b><br/><img src="screenshots/05-settings/01-settings-general.png"/></td>
<td align="center"><b>Terminal Themes</b><br/><img src="screenshots/05-settings/02-settings-terminal.png"/></td>
</tr>
<tr>
<td align="center"><b>Sync</b><br/><img src="screenshots/05-settings/03-settings-sync.png"/></td>
<td align="center"><b>P2P QR Sync — Export via QR</b><br/><img src="screenshots/10-settings-sync-qr-code.png"/></td>
<td align="center"><b>Session Recording &amp; Playback</b><br/><img src="screenshots/11-recording.png"/></td>
</tr>
<tr>
<td align="center"><b>Terminal Sharing (Multiplayer)</b><br/><img src="screenshots/12-multiple-player.png"/></td>
<td align="center"><b>Settings — Terminal Themes</b><br/><img src="screenshots/07-settings-terminal-themes.png"/></td>
<td align="center"><b>Updates</b><br/><img src="screenshots/05-settings/04-settings-updates.png"/></td>
</tr>
</table>

### Plugins

<table>
<tr>
<td align="center"><b>Plugin Manager</b><br/><img src="screenshots/06-plugins/01-plugins.png"/></td>
<td align="center"><b>DevOps Hub — Network Tools</b><br/><img src="screenshots/05-devops-hub-network-tools.png"/></td>
</tr>
<tr>
<td align="center"><b>Web Tools — HTTP Client</b><br/><img src="screenshots/08-web-tools-http-client.png"/></td>
<td align="center"><b>Snippets</b><br/><img src="screenshots/09-snippets.png"/></td>
</tr>
</table>

### In-App RDP Client

<table>
<tr>
<td align="center"><b>Dashboard — RDP Host Badges</b><br/><img src="screenshots/01-dashboard-rdp-badge.png"/></td>
<td align="center"><b>Host Editor — RDP Form</b><br/><img src="screenshots/02-host-editor-rdp-form.png"/></td>
<td align="center"><b>Server Certificate — TOFU Dialog</b><br/><img src="screenshots/03-tofu-certificate-dialog.png"/></td>
</tr>
<tr>
<td align="center"><b>Server Certificate — TOFU Dialog</b><br/><img src="screenshots/03-tofu-certificate-dialog.png"/></td>
<td align="center"><b>RDP Workspace — Connected</b><br/><img src="screenshots/04-rdp-workspace-connected.png"/></td>
<td align="center"><b>Fullscreen with Hover Pill</b><br/><img src="screenshots/05-fullscreen-with-pill.png"/></td>
</tr>
<tr>
<td align="center"><b>Fullscreen with Hover Pill</b><br/><img src="screenshots/05-fullscreen-with-pill.png"/></td>
<td align="center"><b>Fullscreen — Clean View</b><br/><img src="screenshots/06-fullscreen-clean.png"/></td>
<td align="center"><b>Hover Reveal — Exit Bar</b><br/><img src="screenshots/07-fullscreen-hover-reveal.png"/></td>
</tr>
<tr>
<td align="center"><b>Hover Reveal — Exit Bar</b><br/><img src="screenshots/07-fullscreen-hover-reveal.png"/></td>
<td align="center"><b>Back to Windowed Mode</b><br/><img src="screenshots/08-back-to-windowed.png"/></td>
</tr>
</table>

### Audit Log & Recording

<table>
<tr>
<td align="center"><b>Audit Log</b><br/><img src="screenshots/10-audit-recording/01-audit-log.png"/></td>
<td align="center"><b>Recording Library</b><br/><img src="screenshots/10-audit-recording/02-recording-library.png"/></td>
</tr>
<tr>
<td align="center"><b>Session Recording &amp; Playback</b><br/><img src="screenshots/11-recording.png"/></td>
<td align="center"><b>Terminal Sharing (Multiplayer)</b><br/><img src="screenshots/12-multiple-player.png"/></td>
</tr>
</table>

---

## Tech Stack
Expand Down
Binary file modified app/assets/app_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/logo-readme.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading