From 84ca051b2f1e492df4c313b512f012c1b4e450c9 Mon Sep 17 00:00:00 2001 From: Thang Nguyen Date: Wed, 24 Jun 2026 08:45:04 +0700 Subject: [PATCH 1/3] feat(ssh): rich connection screen with live connection log Replace the bare connecting/error/disconnected status view in the session tab with a host card (OS icon, label, host:port), an animated node -> line -> terminal graphic, a "Show logs" panel over a new per-session connection log, and Close/Retry actions. Connection steps (resolve, auth method, jump-host tunnel, host-key verify, established/failed, reconnect countdown) are recorded at the SessionProvider level, so SshService.connect's shared signature is untouched. Manual retry reuses the same tab/terminal and starts a fresh log. The card scrolls instead of overflowing on short panes. Refs #82 --- app/lib/models/connection_log.dart | 22 + app/lib/models/ssh_session.dart | 19 + app/lib/providers/session_provider.dart | 52 +- app/lib/widgets/session_connecting_view.dart | 456 ++++++++++++++++++ app/lib/widgets/terminal_view.dart | 31 +- app/test/models/connection_log_test.dart | 53 ++ .../session_provider_connection_log_test.dart | 126 +++++ .../widgets/session_connecting_view_test.dart | 107 ++++ 8 files changed, 843 insertions(+), 23 deletions(-) create mode 100644 app/lib/models/connection_log.dart create mode 100644 app/lib/widgets/session_connecting_view.dart create mode 100644 app/test/models/connection_log_test.dart create mode 100644 app/test/providers/session_provider_connection_log_test.dart create mode 100644 app/test/widgets/session_connecting_view_test.dart diff --git a/app/lib/models/connection_log.dart b/app/lib/models/connection_log.dart new file mode 100644 index 00000000..ef9f1879 --- /dev/null +++ b/app/lib/models/connection_log.dart @@ -0,0 +1,22 @@ +/// A single line in a session's connection log — the human-readable trace of a +/// connect attempt (resolve → TCP → host-key verify → auth → shell) surfaced by +/// the "Show logs" panel on the connecting screen. +library; + +enum ConnectionLogLevel { info, success, warn, error } + +class ConnectionLogLine { + final DateTime time; + final ConnectionLogLevel level; + final String message; + + const ConnectionLogLine({ + required this.time, + required this.level, + required this.message, + }); +} + +/// Cap on retained connection-log lines. A flapping host with verbose reconnect +/// chatter must not grow this list without bound. +const int kMaxConnectionLogLines = 200; diff --git a/app/lib/models/ssh_session.dart b/app/lib/models/ssh_session.dart index bc523532..092c4ae0 100644 --- a/app/lib/models/ssh_session.dart +++ b/app/lib/models/ssh_session.dart @@ -1,6 +1,7 @@ import 'package:uuid/uuid.dart'; import 'package:xterm/xterm.dart'; import 'agent_forwarding_state.dart'; +import 'connection_log.dart'; import 'host.dart'; import 'terminal_session.dart'; @@ -33,6 +34,24 @@ class SshSession implements TerminalSession { /// SessionProvider.handleAgentForwardingEvent. AgentForwardingState agentForwardingState = AgentForwardingState.off; + /// Human-readable trace of the connect attempt, shown by the "Show logs" + /// panel on the connecting screen. Bounded to [kMaxConnectionLogLines]. + final List connectionLog = []; + + /// Appends a connection-log line, trimming the oldest entries past the cap. + void logConnection(ConnectionLogLevel level, String message, {DateTime? at}) { + connectionLog.add(ConnectionLogLine( + time: at ?? DateTime.now(), + level: level, + message: message, + )); + if (connectionLog.length > kMaxConnectionLogLines) { + connectionLog.removeRange(0, connectionLog.length - kMaxConnectionLogLines); + } + } + + void clearConnectionLog() => connectionLog.clear(); + SshSession({ String? id, required this.host, diff --git a/app/lib/providers/session_provider.dart b/app/lib/providers/session_provider.dart index 5acbafa5..b46f807b 100644 --- a/app/lib/providers/session_provider.dart +++ b/app/lib/providers/session_provider.dart @@ -5,6 +5,7 @@ import 'package:yourssh_rdp/yourssh_rdp.dart'; import 'package:yourssh_vnc/yourssh_vnc.dart'; import '../models/agent_forwarding_state.dart'; import '../models/audit_event.dart'; +import '../models/connection_log.dart'; import '../models/host.dart'; import '../models/local_session.dart'; import '../models/rdp_session.dart'; @@ -457,18 +458,29 @@ class SessionProvider extends ChangeNotifier { jumpLookup: (id) => jumpHostLookup?.call(id), keyLookup: (id) => keyLookup?.call(id), ); + session.logConnection(ConnectionLogLevel.info, + 'Connecting to ${host.host}:${host.port} as ${host.username}'); + session.logConnection( + ConnectionLogLevel.info, 'Auth method: ${host.authType.name}'); + if (jumpChain.isNotEmpty) { + session.logConnection(ConnectionLogLevel.info, + 'Tunneling via ${jumpChain.map((h) => h.host.label).join(' → ')}'); + } + _safeNotify(); await _ssh.connect( host, keyEntry: keyEntry, jumpChain: jumpChain, verifyHostKey: hostKeyVerifier != null - ? (keyType, fp) => hostKeyVerifier!(host.host, host.port, keyType, fp) + ? (keyType, fp) => + _verifyAndLog(session, host.host, host.port, keyType, fp) : null, verifyHopHostKey: hostKeyVerifier != null ? (hop, keyType, fp) => - hostKeyVerifier!(hop.host, hop.port, keyType, fp) + _verifyAndLog(session, hop.host, hop.port, keyType, fp) : null, ); + session.logConnection(ConnectionLogLevel.success, 'Connection established'); session.status = SessionStatus.connected; audit?.record(AuditEvent.now( type: AuditEventType.connect, host: host, sessionId: session.id)); @@ -516,6 +528,7 @@ class SessionProvider extends ChangeNotifier { } } catch (e) { if (!_sessions.contains(session)) return; + session.logConnection(ConnectionLogLevel.error, 'Connection failed: $e'); final maxAttempts = reconnectAttempts?.call() ?? 0; final isUnlimited = maxAttempts == 0; // A jump-chain config error (deleted bastion, cycle) can never succeed @@ -545,10 +558,45 @@ class SessionProvider extends ChangeNotifier { } } + /// Wraps the host-key verifier so the TOFU check is reflected in the + /// session's connection log (shown by the "Show logs" panel). + Future _verifyAndLog( + SshSession session, String host, int port, String keyType, Uint8List fp) async { + session.logConnection( + ConnectionLogLevel.info, 'Verifying host key ($keyType) for $host:$port'); + _safeNotify(); + final ok = await hostKeyVerifier!(host, port, keyType, fp); + session.logConnection( + ok ? ConnectionLogLevel.success : ConnectionLogLevel.warn, + ok ? 'Host key accepted' : 'Host key rejected'); + _safeNotify(); + return ok; + } + + /// Manual retry from the connecting screen's "Retry" button. Reuses the + /// existing session/tab (preserving its terminal and metadata) rather than + /// closing and reopening, and cancels any pending auto-reconnect first. + void reconnectSession(String sessionId) { + final session = sshSessions.where((s) => s.id == sessionId).firstOrNull; + if (session == null || session.status == SessionStatus.connecting) return; + _reconnectTimers.remove(sessionId)?.cancel(); + _countdownTimers.remove(sessionId)?.cancel(); + session.status = SessionStatus.connecting; + session.errorMessage = null; + // A manual retry is a fresh attempt — drop the prior attempt's trace so the + // log panel shows only the new connection. + session.clearConnectionLog(); + session.logConnection(ConnectionLogLevel.info, 'Retrying connection…'); + _safeNotify(); + unawaited(_doConnect(session, session.host, attempt: 1)); + } + void _scheduleReconnect(SshSession session, Host host, {required int attempt}) { session.reconnectCount++; final delay = (attempt * 2).clamp(2, 60); session.status = SessionStatus.connecting; + session.logConnection( + ConnectionLogLevel.warn, 'Reconnecting in ${delay}s (attempt $attempt)'); _safeNotify(); _startCountdown(session, delay, attempt); diff --git a/app/lib/widgets/session_connecting_view.dart b/app/lib/widgets/session_connecting_view.dart new file mode 100644 index 00000000..a7a0d613 --- /dev/null +++ b/app/lib/widgets/session_connecting_view.dart @@ -0,0 +1,456 @@ +import 'dart:math' as math; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +import '../models/connection_log.dart'; +import '../models/host.dart'; +import '../models/ssh_session.dart'; +import '../services/os_detection.dart'; +import '../theme/app_theme.dart'; + +/// Full-area screen shown inside a session tab while an SSH session is +/// connecting, has errored, or has disconnected. Mirrors mstsc-style connect +/// UX: a host card, an animated node → line → terminal connection graphic, a +/// "Show logs" panel over [SshSession.connectionLog], and Close/Retry actions. +class SessionConnectingView extends StatefulWidget { + final SshSession session; + final VoidCallback onClose; + final VoidCallback onRetry; + + const SessionConnectingView({ + super.key, + required this.session, + required this.onClose, + required this.onRetry, + }); + + @override + State createState() => _SessionConnectingViewState(); +} + +class _SessionConnectingViewState extends State + with SingleTickerProviderStateMixin { + late final AnimationController _anim; + bool _showLogs = false; + + @override + void initState() { + super.initState(); + _anim = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 1400), + ); + _syncAnimation(); + } + + @override + void didUpdateWidget(SessionConnectingView old) { + super.didUpdateWidget(old); + _syncAnimation(); + } + + /// Spin only while connecting; freeze for error/disconnected states. + void _syncAnimation() { + final connecting = widget.session.status == SessionStatus.connecting; + if (connecting && !_anim.isAnimating) { + _anim.repeat(); + } else if (!connecting && _anim.isAnimating) { + _anim.stop(); + } + } + + @override + void dispose() { + _anim.dispose(); + super.dispose(); + } + + Color get _nodeColor => switch (widget.session.status) { + SessionStatus.error => AppColors.red, + SessionStatus.disconnected => AppColors.textTertiary, + _ => AppColors.blue, + }; + + @override + Widget build(BuildContext context) { + final session = widget.session; + final host = session.host; + final status = session.status; + final isError = status == SessionStatus.error; + final isDisconnected = status == SessionStatus.disconnected; + final canRetry = isError || isDisconnected; + + final message = switch (status) { + SessionStatus.error => session.errorMessage ?? 'Connection error', + SessionStatus.disconnected => 'Disconnected', + _ => 'Connecting…', + }; + final messageColor = switch (status) { + SessionStatus.error => AppColors.red, + SessionStatus.disconnected => AppColors.textSecondary, + _ => AppColors.textSecondary, + }; + + // Centered when it fits; scrolls instead of overflowing when the pane is + // short (split view / small window) — especially with the logs panel open. + return Container( + color: AppColors.bg, + child: LayoutBuilder( + builder: (context, constraints) => SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints(minHeight: constraints.maxHeight), + child: Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 520), + child: Container( + decoration: BoxDecoration( + color: AppColors.card, + borderRadius: BorderRadius.circular(16), + border: Border.all(color: AppColors.border), + ), + padding: const EdgeInsets.fromLTRB(20, 18, 20, 18), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _header(host), + const SizedBox(height: 22), + _ConnectionGraphic( + animation: _anim, + active: status == SessionStatus.connecting, + nodeColor: _nodeColor, + ), + const SizedBox(height: 14), + Text(message, style: TextStyle(color: messageColor, fontSize: 12.5)), + const SizedBox(height: 18), + Row( + children: [ + _PillButton(label: 'Close', onTap: widget.onClose), + if (canRetry) ...[ + const SizedBox(width: 10), + _PillButton( + label: 'Retry', + accent: true, + onTap: widget.onRetry, + ), + ], + ], + ), + if (_showLogs) ...[ + const SizedBox(height: 16), + _LogsPanel(lines: session.connectionLog), + ], + ], + ), + ), + ), + ), + ), + ), + ), + ), + ); + } + + Widget _header(Host host) { + return Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + _OsAvatar(detectedOs: host.detectedOs), + const SizedBox(width: 14), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + host.label, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + color: AppColors.textPrimary, + fontSize: 15, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 2), + Text( + 'SSH ${host.host}:${host.port}', + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle(color: AppColors.textSecondary, fontSize: 12), + ), + ], + ), + ), + const SizedBox(width: 12), + _PillButton( + label: _showLogs ? 'Hide logs' : 'Show logs', + onTap: () => setState(() => _showLogs = !_showLogs), + ), + ], + ); + } +} + +class _OsAvatar extends StatelessWidget { + final String? detectedOs; + const _OsAvatar({required this.detectedOs}); + + @override + Widget build(BuildContext context) { + final asset = osIconAsset(detectedOs); + return Container( + width: 44, + height: 44, + decoration: BoxDecoration( + color: Colors.black, + borderRadius: BorderRadius.circular(12), + ), + alignment: Alignment.center, + child: asset != null + ? SvgPicture.asset( + asset, + width: 22, + height: 22, + colorFilter: + const ColorFilter.mode(AppColors.textPrimary, BlendMode.srcIn), + ) + : const Icon(Icons.dns_outlined, size: 22, color: AppColors.textPrimary), + ); + } +} + +/// node (link icon, spinning arc while active) ── line ── terminal node. +class _ConnectionGraphic extends StatelessWidget { + final Animation animation; + final bool active; + final Color nodeColor; + + const _ConnectionGraphic({ + required this.animation, + required this.active, + required this.nodeColor, + }); + + @override + Widget build(BuildContext context) { + return SizedBox( + height: 48, + child: AnimatedBuilder( + animation: animation, + builder: (context, _) { + final t = animation.value; + return Row( + children: [ + _node( + child: _spinningRing(t), + ), + Expanded( + child: CustomPaint( + size: const Size(double.infinity, 48), + painter: _LinePainter( + progress: active ? t : null, + color: nodeColor, + ), + ), + ), + _node( + color: AppColors.cardHover, + child: const Icon(Icons.terminal, size: 20, color: AppColors.textPrimary), + ), + ], + ); + }, + ), + ); + } + + Widget _spinningRing(double t) { + final icon = const Icon(Icons.link, size: 18, color: Colors.white); + if (!active) return icon; + return CustomPaint( + painter: _ArcPainter(turn: t, color: Colors.white), + child: SizedBox(width: 38, height: 38, child: Center(child: icon)), + ); + } + + Widget _node({Color? color, required Widget child}) { + return Container( + width: 38, + height: 38, + decoration: BoxDecoration( + color: color ?? nodeColor, + shape: BoxShape.circle, + ), + alignment: Alignment.center, + child: child, + ); + } +} + +class _ArcPainter extends CustomPainter { + final double turn; + final Color color; + _ArcPainter({required this.turn, required this.color}); + + @override + void paint(Canvas canvas, Size size) { + final center = size.center(Offset.zero); + final radius = size.width / 2 - 1; + final paint = Paint() + ..color = color + ..style = PaintingStyle.stroke + ..strokeWidth = 2.5 + ..strokeCap = StrokeCap.round; + final start = turn * 2 * math.pi; + canvas.drawArc( + Rect.fromCircle(center: center, radius: radius), + start, + math.pi * 0.6, + false, + paint, + ); + } + + @override + bool shouldRepaint(_ArcPainter old) => old.turn != turn || old.color != color; +} + +class _LinePainter extends CustomPainter { + /// Animation phase in [0,1] while connecting; null when frozen. + final double? progress; + final Color color; + _LinePainter({required this.progress, required this.color}); + + @override + void paint(Canvas canvas, Size size) { + final y = size.height / 2; + final base = Paint() + ..color = AppColors.border + ..strokeWidth = 2 + ..strokeCap = StrokeCap.round; + canvas.drawLine(Offset(0, y), Offset(size.width, y), base); + + if (progress == null) return; + // A short glowing segment travels left → right along the line. + final dotX = progress! * size.width; + final glow = Paint() + ..color = color + ..strokeWidth = 3 + ..strokeCap = StrokeCap.round; + final half = size.width * 0.12; + canvas.drawLine( + Offset((dotX - half).clamp(0, size.width), y), + Offset((dotX + half).clamp(0, size.width), y), + glow, + ); + } + + @override + bool shouldRepaint(_LinePainter old) => + old.progress != progress || old.color != color; +} + +class _LogsPanel extends StatelessWidget { + final List lines; + const _LogsPanel({required this.lines}); + + @override + Widget build(BuildContext context) { + return Container( + constraints: const BoxConstraints(maxHeight: 180), + width: double.infinity, + decoration: BoxDecoration( + color: AppColors.bg, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: AppColors.border), + ), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + child: lines.isEmpty + ? const Text( + 'No logs yet', + style: TextStyle(color: AppColors.textTertiary, fontSize: 12, fontFamily: 'monospace'), + ) + : SingleChildScrollView( + reverse: true, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [for (final l in lines) _line(l)], + ), + ), + ); + } + + Widget _line(ConnectionLogLine l) { + final color = switch (l.level) { + ConnectionLogLevel.success => AppColors.accent, + ConnectionLogLevel.warn => AppColors.orange, + ConnectionLogLevel.error => AppColors.red, + ConnectionLogLevel.info => AppColors.textSecondary, + }; + const base = TextStyle(fontSize: 12, fontFamily: 'monospace', height: 1.35); + return Padding( + padding: const EdgeInsets.symmetric(vertical: 1), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(_hms(l.time), style: base.copyWith(color: AppColors.textTertiary)), + const SizedBox(width: 10), + Expanded(child: Text(l.message, style: base.copyWith(color: color))), + ], + ), + ); + } + + String _hms(DateTime t) { + String two(int n) => n.toString().padLeft(2, '0'); + return '${two(t.hour)}:${two(t.minute)}:${two(t.second)}'; + } +} + +class _PillButton extends StatefulWidget { + final String label; + final bool accent; + final VoidCallback onTap; + const _PillButton({required this.label, this.accent = false, required this.onTap}); + + @override + State<_PillButton> createState() => _PillButtonState(); +} + +class _PillButtonState extends State<_PillButton> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final accent = widget.accent; + final bg = accent + ? (_hovered ? AppColors.accentDim : AppColors.accent) + : (_hovered ? AppColors.cardHover : AppColors.bg); + final fg = accent ? Colors.black : AppColors.textPrimary; + return MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.onTap, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 9), + decoration: BoxDecoration( + color: bg, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: accent ? AppColors.accent : AppColors.border), + ), + child: Text( + widget.label, + style: TextStyle(color: fg, fontSize: 13, fontWeight: FontWeight.w500), + ), + ), + ), + ); + } +} diff --git a/app/lib/widgets/terminal_view.dart b/app/lib/widgets/terminal_view.dart index 6211a186..2a5fef9c 100644 --- a/app/lib/widgets/terminal_view.dart +++ b/app/lib/widgets/terminal_view.dart @@ -7,6 +7,7 @@ import '../models/host.dart'; import '../models/ssh_session.dart'; import '../providers/command_history_provider.dart'; import '../providers/host_provider.dart'; +import '../providers/session_provider.dart'; import '../providers/settings_provider.dart'; import '../providers/shell_integration_provider.dart'; import '../services/hotkey_service.dart'; @@ -14,6 +15,7 @@ import '../theme/terminal_themes.dart'; import '../util/terminal_appearance.dart'; import 'command_gutter.dart'; import 'record_button.dart'; +import 'session_connecting_view.dart'; import 'suggestion_popup.dart'; import 'terminal_context_menu.dart'; @@ -23,27 +25,14 @@ class SessionTerminalView extends StatelessWidget { @override Widget build(BuildContext context) { - return switch (session.status) { - SessionStatus.connecting => _statusView(Icons.sync, 'Connecting to ${session.host.host}…', Colors.orange), - SessionStatus.error => _statusView(Icons.error_outline, session.errorMessage ?? 'Connection error', Colors.red), - SessionStatus.disconnected => _statusView(Icons.link_off, 'Disconnected', Colors.grey), - SessionStatus.connected => _TerminalWidget(key: ValueKey(session.id), session: session), - }; - } - - Widget _statusView(IconData icon, String message, Color color) { - return Container( - color: Colors.black, - child: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(icon, color: color, size: 40), - const SizedBox(height: 12), - Text(message, style: TextStyle(color: color, fontFamily: 'monospace', fontSize: 13)), - ], - ), - ), + if (session.status == SessionStatus.connected) { + return _TerminalWidget(key: ValueKey(session.id), session: session); + } + final sessions = context.read(); + return SessionConnectingView( + session: session, + onClose: () => sessions.closeSession(session.id), + onRetry: () => sessions.reconnectSession(session.id), ); } } diff --git a/app/test/models/connection_log_test.dart b/app/test/models/connection_log_test.dart new file mode 100644 index 00000000..c6d5258f --- /dev/null +++ b/app/test/models/connection_log_test.dart @@ -0,0 +1,53 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:yourssh/models/connection_log.dart'; +import 'package:yourssh/models/host.dart'; +import 'package:yourssh/models/ssh_session.dart'; + +SshSession _session() => SshSession( + host: Host(id: 'h1', label: 'Box', host: 'example.com', port: 22, username: 'root'), + ); + +void main() { + group('SshSession.logConnection', () { + test('starts empty', () { + expect(_session().connectionLog, isEmpty); + }); + + test('appends a line with the given level and message', () { + final s = _session(); + s.logConnection(ConnectionLogLevel.info, 'Connecting…'); + s.logConnection(ConnectionLogLevel.success, 'Connected'); + + expect(s.connectionLog, hasLength(2)); + expect(s.connectionLog.first.level, ConnectionLogLevel.info); + expect(s.connectionLog.first.message, 'Connecting…'); + expect(s.connectionLog.last.level, ConnectionLogLevel.success); + }); + + test('uses the provided timestamp when given', () { + final s = _session(); + final t = DateTime(2026, 6, 23, 10, 30, 45); + s.logConnection(ConnectionLogLevel.info, 'x', at: t); + expect(s.connectionLog.single.time, t); + }); + + test('bounds the log to the most recent kMaxConnectionLogLines', () { + final s = _session(); + for (var i = 0; i < kMaxConnectionLogLines + 50; i++) { + s.logConnection(ConnectionLogLevel.info, 'line $i'); + } + expect(s.connectionLog, hasLength(kMaxConnectionLogLines)); + // Oldest lines dropped; the newest line is retained. + expect(s.connectionLog.last.message, 'line ${kMaxConnectionLogLines + 49}'); + expect(s.connectionLog.first.message, 'line 50'); + }); + + test('clearConnectionLog empties the buffer', () { + final s = _session() + ..logConnection(ConnectionLogLevel.info, 'a') + ..logConnection(ConnectionLogLevel.error, 'b'); + s.clearConnectionLog(); + expect(s.connectionLog, isEmpty); + }); + }); +} diff --git a/app/test/providers/session_provider_connection_log_test.dart b/app/test/providers/session_provider_connection_log_test.dart new file mode 100644 index 00000000..2c670ac7 --- /dev/null +++ b/app/test/providers/session_provider_connection_log_test.dart @@ -0,0 +1,126 @@ +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:dartssh2/dartssh2.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:yourssh/models/connection_log.dart'; +import 'package:yourssh/models/host.dart'; +import 'package:yourssh/models/ssh_key.dart'; +import 'package:yourssh/models/ssh_session.dart'; +import 'package:yourssh/providers/session_provider.dart'; +import 'package:yourssh/services/ssh_service.dart'; +import 'package:yourssh/services/storage_service.dart'; +import 'package:yourssh/services/tab_metadata_service.dart'; + +class _NullClient implements SSHClient { + @override + dynamic noSuchMethod(Invocation i) => super.noSuchMethod(i); +} + +class _FakeSsh extends SshService { + _FakeSsh() : super(StorageService()); + bool failConnect = false; + + /// Keeps connect() pending so the session stays in `connecting`. + Completer? connectGate; + + /// Keeps openShell pending so a connected session doesn't drop. + Completer? shellGate; + + @override + Future connect( + Host host, { + SshKeyEntry? keyEntry, + List jumpChain = const [], + Future Function(String keyType, Uint8List fingerprint)? verifyHostKey, + Future Function(Host hop, String keyType, Uint8List fp)? + verifyHopHostKey, + }) async { + final gate = connectGate; + if (gate != null) await gate.future; + if (failConnect) throw Exception('refused'); + return _NullClient(); + } + + @override + Future openShell(SshSession session, + {bool useTmux = false, String termType = 'xterm-256color'}) async { + final gate = shellGate; + if (gate != null) await gate.future; + } + + @override + void disconnectSession(String sessionId) {} + @override + void disconnect(String hostId) {} +} + +Host _host() => Host(label: 'prod', host: 'p.com', username: 'root'); + +List _messages(SshSession s) => + s.connectionLog.map((l) => l.message).toList(); + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + setUp(() => SharedPreferences.setMockInitialValues({})); + + test('successful connect logs the connecting and established steps', () async { + final p = SessionProvider(_FakeSsh(), TabMetadataService()); + await p.connect(_host()); + final s = p.sshSessions.single; + + final msgs = _messages(s); + expect(msgs, contains('Connecting to p.com:22 as root')); + expect(msgs, contains('Connection established')); + p.dispose(); + }); + + test('failed connect logs an error line', () async { + final p = SessionProvider(_FakeSsh()..failConnect = true, TabMetadataService()); + await p.connect(_host()); + final s = p.sshSessions.single; + + expect(s.status, SessionStatus.error); + expect(_messages(s).any((m) => m.startsWith('Connection failed:')), isTrue); + expect(s.connectionLog.last.level, ConnectionLogLevel.error); + p.dispose(); + }); + + test('reconnectSession retries an errored session and clears the error', () async { + final ssh = _FakeSsh()..failConnect = true; + final p = SessionProvider(ssh, TabMetadataService()); + await p.connect(_host()); + final s = p.sshSessions.single; + expect(s.status, SessionStatus.error); + + // Next attempt succeeds and the shell stays open. + ssh.failConnect = false; + ssh.shellGate = Completer(); + p.reconnectSession(s.id); + await Future.delayed(Duration.zero); + + expect(s.status, SessionStatus.connected); + expect(s.errorMessage, isNull); + expect(_messages(s), contains('Retrying connection…')); + // A manual retry starts a fresh log — the prior attempt's failure is gone. + expect(_messages(s).any((m) => m.startsWith('Connection failed:')), isFalse); + expect(_messages(s).first, 'Retrying connection…'); + p.dispose(); + }); + + test('reconnectSession is a no-op while already connecting', () async { + final ssh = _FakeSsh()..connectGate = Completer(); + final p = SessionProvider(ssh, TabMetadataService()); + // Don't await: the gated connect() keeps the session in `connecting`. + unawaited(p.connect(_host())); + await Future.delayed(Duration.zero); + final s = p.sshSessions.single; + expect(s.status, SessionStatus.connecting); + + final before = s.connectionLog.length; + p.reconnectSession(s.id); + expect(s.connectionLog.length, before); // no "Retrying…" line appended + p.dispose(); + }); +} diff --git a/app/test/widgets/session_connecting_view_test.dart b/app/test/widgets/session_connecting_view_test.dart new file mode 100644 index 00000000..60c8c7e3 --- /dev/null +++ b/app/test/widgets/session_connecting_view_test.dart @@ -0,0 +1,107 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:yourssh/models/connection_log.dart'; +import 'package:yourssh/models/host.dart'; +import 'package:yourssh/models/ssh_session.dart'; +import 'package:yourssh/widgets/session_connecting_view.dart'; + +SshSession _session({ + SessionStatus status = SessionStatus.connecting, + String? error, +}) { + final s = SshSession( + host: Host(id: 'h1', label: 'Thang MacBook Pro', host: 'thngs-macbook-pro', port: 22, username: 'thang'), + status: status, + ); + s.errorMessage = error; + return s; +} + +Future _pump( + WidgetTester tester, + SshSession session, { + VoidCallback? onClose, + VoidCallback? onRetry, +}) async { + await tester.pumpWidget(MaterialApp( + home: Scaffold( + body: SessionConnectingView( + session: session, + onClose: onClose ?? () {}, + onRetry: onRetry ?? () {}, + ), + ), + )); + await tester.pump(); // start the spinner animation; don't settle (it repeats). +} + +void main() { + testWidgets('shows the host label and SSH host:port subtitle', (tester) async { + await _pump(tester, _session()); + expect(find.text('Thang MacBook Pro'), findsOneWidget); + expect(find.text('SSH thngs-macbook-pro:22'), findsOneWidget); + }); + + testWidgets('connecting state shows Close but not Retry', (tester) async { + await _pump(tester, _session(status: SessionStatus.connecting)); + expect(find.text('Close'), findsOneWidget); + expect(find.text('Retry'), findsNothing); + }); + + testWidgets('error state shows the error message and a Retry button', (tester) async { + await _pump(tester, _session(status: SessionStatus.error, error: 'Auth failed')); + expect(find.text('Auth failed'), findsOneWidget); + expect(find.text('Retry'), findsOneWidget); + expect(find.text('Close'), findsOneWidget); + }); + + testWidgets('Show logs toggles the connection log panel', (tester) async { + final s = _session() + ..logConnection(ConnectionLogLevel.info, 'Resolving thngs-macbook-pro') + ..logConnection(ConnectionLogLevel.success, 'TCP established'); + await _pump(tester, s); + + // Hidden by default. + expect(find.text('Resolving thngs-macbook-pro'), findsNothing); + + await tester.tap(find.text('Show logs')); + await tester.pump(); + + expect(find.text('Resolving thngs-macbook-pro'), findsOneWidget); + expect(find.text('TCP established'), findsOneWidget); + }); + + testWidgets('does not overflow on a short pane with logs open', (tester) async { + tester.view.physicalSize = const Size(420, 300); + tester.view.devicePixelRatio = 1.0; + addTearDown(tester.view.resetPhysicalSize); + addTearDown(tester.view.resetDevicePixelRatio); + + final s = _session(); + for (var i = 0; i < 12; i++) { + s.logConnection(ConnectionLogLevel.info, 'log line number $i'); + } + await _pump(tester, s); + await tester.tap(find.text('Show logs')); + await tester.pump(); + + expect(tester.takeException(), isNull); + }); + + testWidgets('Close and Retry fire their callbacks', (tester) async { + var closed = 0, retried = 0; + await _pump( + tester, + _session(status: SessionStatus.error, error: 'x'), + onClose: () => closed++, + onRetry: () => retried++, + ); + + await tester.tap(find.text('Retry')); + await tester.tap(find.text('Close')); + await tester.pump(); + + expect(retried, 1); + expect(closed, 1); + }); +} From a15c96df2b63769e699e7479da0e3e55cdea32fe Mon Sep 17 00:00:00 2001 From: Thang Nguyen Date: Wed, 24 Jun 2026 08:52:05 +0700 Subject: [PATCH 2/3] test(ssh): screenshot harness + images for the connection screen Adds integration_test/connecting_screenshots_test.dart (render-tree capture, no Screen-Recording permission) that pumps SessionConnectingView in its connecting and error+logs states, plus the captured PNGs under screenshots/01-terminal-ssh/. Refs #82 --- .../connecting_screenshots_test.dart | 108 ++++++++++++++++++ .../ssh-connecting-error-logs.png | Bin 0 -> 100623 bytes .../01-terminal-ssh/ssh-connecting.png | Bin 0 -> 40653 bytes 3 files changed, 108 insertions(+) create mode 100644 app/integration_test/connecting_screenshots_test.dart create mode 100644 screenshots/01-terminal-ssh/ssh-connecting-error-logs.png create mode 100644 screenshots/01-terminal-ssh/ssh-connecting.png diff --git a/app/integration_test/connecting_screenshots_test.dart b/app/integration_test/connecting_screenshots_test.dart new file mode 100644 index 00000000..49e68004 --- /dev/null +++ b/app/integration_test/connecting_screenshots_test.dart @@ -0,0 +1,108 @@ +// Captures screenshots of the SSH connection screen (SessionConnectingView) +// in its connecting and error+logs states. Pumps the widget directly (it takes +// plain callbacks, no providers) so the transient connecting state is +// deterministic, and captures from the render tree — no Screen-Recording +// permission needed. +// +// Run: +// cd app && flutter test integration_test/connecting_screenshots_test.dart -d macos +import 'dart:io'; +import 'dart:ui' as ui; + +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:yourssh/models/connection_log.dart'; +import 'package:yourssh/models/host.dart'; +import 'package:yourssh/models/ssh_session.dart'; +import 'package:yourssh/theme/app_theme.dart'; +import 'package:yourssh/widgets/session_connecting_view.dart'; + +const _outDir = '/Users/thangnguyen/Projects/Personal/yourssh/screenshots'; +const _g1 = '$_outDir/01-terminal-ssh'; + +final _captureKey = GlobalKey(); + +/// Captures exactly the fixed-size RepaintBoundary around the card — independent +/// of the real macOS window size, so the framing is deterministic. +Future _snap(WidgetTester tester, String path) async { + await tester.pump(const Duration(milliseconds: 200)); + final boundary = + _captureKey.currentContext!.findRenderObject() as RenderRepaintBoundary; + final image = await boundary.toImage(pixelRatio: 2.0); + final bytes = await image.toByteData(format: ui.ImageByteFormat.png); + image.dispose(); + final file = File(path); + await file.parent.create(recursive: true); + await file.writeAsBytes(bytes!.buffer.asUint8List()); + // ignore: avoid_print + print('SNAP: $path'); +} + +SshSession _session(SessionStatus status, {String? error}) { + final s = SshSession( + host: Host( + id: 'demo', + label: 'Thang MacBook Pro', + host: 'thngs-macbook-pro', + port: 22, + username: 'thang', + detectedOs: 'macos', + ), + status: status, + ); + s.errorMessage = error; + return s; +} + +Future _pump(WidgetTester tester, SshSession session) async { + await tester.pumpWidget(MaterialApp( + theme: buildAppTheme(), + debugShowCheckedModeBanner: false, + home: Scaffold( + backgroundColor: AppColors.bg, + body: Center( + child: RepaintBoundary( + key: _captureKey, + child: SizedBox( + width: 760, + height: 520, + child: SessionConnectingView( + session: session, + onClose: () {}, + onRetry: () {}, + ), + ), + ), + ), + ), + )); + await tester.pump(const Duration(milliseconds: 300)); +} + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets('connecting state', (tester) async { + final s = _session(SessionStatus.connecting) + ..logConnection(ConnectionLogLevel.info, 'Connecting to thngs-macbook-pro:22 as thang') + ..logConnection(ConnectionLogLevel.info, 'Auth method: publicKey'); + await _pump(tester, s); + await _snap(tester, '$_g1/ssh-connecting.png'); + await tester.pumpWidget(const SizedBox()); // unmount → dispose animation + }); + + testWidgets('error state with logs open', (tester) async { + final s = _session(SessionStatus.error, error: 'Auth failed: permission denied (publickey)') + ..logConnection(ConnectionLogLevel.info, 'Connecting to thngs-macbook-pro:22 as thang') + ..logConnection(ConnectionLogLevel.info, 'Auth method: publicKey') + ..logConnection(ConnectionLogLevel.info, 'Verifying host key (ssh-ed25519) for thngs-macbook-pro:22') + ..logConnection(ConnectionLogLevel.success, 'Host key accepted') + ..logConnection(ConnectionLogLevel.error, 'Connection failed: permission denied (publickey)'); + await _pump(tester, s); + await tester.tap(find.text('Show logs')); + await _snap(tester, '$_g1/ssh-connecting-error-logs.png'); + await tester.pumpWidget(const SizedBox()); + }); +} diff --git a/screenshots/01-terminal-ssh/ssh-connecting-error-logs.png b/screenshots/01-terminal-ssh/ssh-connecting-error-logs.png new file mode 100644 index 0000000000000000000000000000000000000000..698ab8d2aa8e8d4dbaa5830ef4114b6b50ccb9aa GIT binary patch literal 100623 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�lq=gvT574Z6B=8#t6Qe{iKit+ycec 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 Z9&qQ4k;#50GDwwqg?p-Z3+|Y`{9l+>^@IQb literal 0 HcmV?d00001 diff --git a/screenshots/01-terminal-ssh/ssh-connecting.png b/screenshots/01-terminal-ssh/ssh-connecting.png new file mode 100644 index 0000000000000000000000000000000000000000..34022a40fff3ea4c06ac76cfdbff4b196f7b3948 GIT binary patch literal 40653 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

Qi;`wchlSv2rjM|PwM=S)<$bHE$24#qo7G#UZ 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 literal 0 HcmV?d00001 From 356bbffaab82e87078ed79bc2259fab7bb020368 Mon Sep 17 00:00:00 2001 From: Thang Nguyen Date: Wed, 24 Jun 2026 09:03:13 +0700 Subject: [PATCH 3/3] =?UTF-8?q?release:=200.1.39=20=E2=80=94=20SSH=20conne?= =?UTF-8?q?ction=20screen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bump version to 0.1.39, add the CHANGELOG 0.1.39 section (SSH connection screen, #82), restore the missing 0.1.38 comparison link, and update the roadmap version/shipped list. --- CHANGELOG.md | 9 +++++++++ app/pubspec.yaml | 2 +- docs/roadmap.md | 4 +++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17d09f6d..a6f2220e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.39] — 2026-06-24 + +### Added +- **SSH connection screen (#82)** — while an SSH session connects, the tab now shows a host card (OS icon, label, `host:port`) with an animated node → line → terminal graphic, a **Show logs** panel over a new per-session connection log (resolve, auth method, jump-host tunnel, host-key verify, established / failed, reconnect countdown), and **Close** / **Retry** actions. Manual retry reuses the same tab and terminal and starts a fresh log. Replaces the bare "Connecting…" spinner; the step log is captured at the `SessionProvider` level so `SshService.connect`'s shared signature is untouched, and the card scrolls instead of overflowing on short / split panes (`SessionConnectingView`, `ConnectionLogLine`). + +--- + ## [0.1.38] — 2026-06-23 ### Added @@ -654,6 +661,8 @@ Initial release of YourSSH — a cross-platform SSH client for macOS, Windows, a - **Host management** — CRUD for SSH host profiles with `StorageService` - **Known hosts** — TOFU dialog for host-key verification; `KnownHostsProvider` +[0.1.39]: https://github.com/YoursshLabs/yourssh/compare/v0.1.38...v0.1.39 +[0.1.38]: https://github.com/YoursshLabs/yourssh/compare/v0.1.37...v0.1.38 [0.1.37]: https://github.com/YoursshLabs/yourssh/compare/v0.1.36...v0.1.37 [0.1.36]: https://github.com/YoursshLabs/yourssh/compare/v0.1.35...v0.1.36 [0.1.35]: https://github.com/YoursshLabs/yourssh/compare/v0.1.34...v0.1.35 diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 5748b3eb..0d6b81d1 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -1,7 +1,7 @@ name: yourssh description: YourSSH - A professional SSH client for macOS, Windows, and Linux with advanced features like SFTP, port forwarding, and a built-in code editor. publish_to: 'none' -version: 0.1.38+1 +version: 0.1.39+1 environment: sdk: ^3.12.0 diff --git a/docs/roadmap.md b/docs/roadmap.md index 1b0ccaee..7932e549 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,7 +1,7 @@ # YourSSH — Roadmap > Direction: **infra workstation for DevOps/SRE managing 10–100+ hosts**, not just an SSH client. -> Current version: 0.1.38 · updated: 2026-06-23 +> Current version: 0.1.39 · updated: 2026-06-24 This document lists proposed features ordered by priority. Each item can be broken out into its own spec (`docs/superpowers/specs/`) when ready for implementation. @@ -11,6 +11,8 @@ Already shipped (not repeated in roadmap): multi-tab terminal, split view, broad **Shipped (0.1.38):** **Docker panel completion** — the Containers screen gains dedicated **Docker** and **Compose** tabs beside Kubernetes (`DockerPanel` / `ComposePanel`, extracted from `ContainersScreen`). Docker: live container list (`docker ps -a`) with per-container Stop / Start / Restart, one-click Exec into a new SSH tab, and an inline follow-mode log viewer (`docker logs -f --tail`, auto-scroll with manual-scroll detach, 2000-line cap). Compose (v2): stack discovery via `docker compose ls` merged with a `find` sweep of `~ /opt /srv /home` (ls entries win on dir collision) plus manual compose-file path add; per-stack Up / Down, per-service Start / Stop with replica counts, and per-service follow-mode logs. New `ComposeStack` / `ComposeService` models and `ContainerService` methods (`streamDockerLogs`, `stop`/`start`/`restartContainer`, `discoverComposeStacks`, `listComposeServices`, `composeUp`/`composeDown`, `start`/`stopComposeService`, `streamComposeServiceLogs`) with pure static parsers (`parseComposeLs` / `parseComposeFindOutput` / `parseComposePs`); all exec/stream calls tagged `auditSource: 'devops'` and shell-quote project paths. +**Shipped (0.1.39):** **SSH connection screen (#82)** — the SSH session tab shows a host card (OS icon, label, `host:port`) with an animated node → line → terminal graphic, a **Show logs** panel over a new per-session connection log (resolve, auth method, jump-host tunnel, host-key verify, established / failed, reconnect countdown), and **Close** / **Retry** actions while connecting / on error; manual retry reuses the same tab and terminal. Replaces the bare "Connecting…" spinner; step logging captured at the `SessionProvider` level (no change to `SshService.connect`'s shared signature), card scrolls instead of overflowing on short / split panes (`SessionConnectingView`, `ConnectionLogLine`). + --- ## P0 — Must-have to retain "power" users