Skip to content

feat: keyword highlighting, server monitor, network discovery, import sources (v0.1.34)#58

Merged
thangnm93 merged 60 commits into
masterfrom
develop
Jun 8, 2026
Merged

feat: keyword highlighting, server monitor, network discovery, import sources (v0.1.34)#58
thangnm93 merged 60 commits into
masterfrom
develop

Conversation

@thangnm93

@thangnm93 thangnm93 commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Keyword highlighting — regex rules tint matching terminal output at paint time (xterm fork); defaults: Error/Warning/Fail rules; toggle + rule list + add/edit dialog + color picker in Settings → Terminal and terminal config panel
  • Server monitor panel — per-host live dashboard (CPU / mem / disk / uptime / ports / firewall) in a draggable bottom sheet; accessible from host card hover button and context menu; polls via SSH every 5 s (stats) / 30 s (firewall); auto-detects ufw / iptables / nftables
  • Network discovery — scan local network for SSH/RDP hosts via mDNS + TCP port scan; results in a bottom sheet with one-tap Add Host; also reachable from Add Host panel
  • Import sources expansion — 9-source picker grid UI; new formats: PuTTY .reg, MobaXterm .mxtsessions, SecureCRT XML, Ansible INI, WinSCP .ini, Termius JSON, SSH URI (one per line)
  • Known hosts import — IMPORT button on Known Hosts screen; MD5 fingerprint computed to match dartssh2 verifier; skips hashed/duplicate entries

Fixes (post-review)

  • In-flight guard on polling services — overlapping execs no longer stack on slow links
  • Error state in ServerMonitorSheet — spinner no longer shown indefinitely on poll failure
  • debugPrint on all silent catches in NetworkDiscoveryService
  • _loadSubnets error handling in NetworkDiscoverySheet
  • DiscoveredHost.merge() source field fixed (was always both)
  • Keyword highlight list identity check — avoids spurious repaints on unrelated provider changes

Test Plan

  • flutter test — 1333 tests pass
  • flutter analyze — no issues
  • Open server monitor on a connected host → CPU/mem/disk/ports render; firewall section shows status
  • Open server monitor on a non-Linux host → error message shown (not infinite spinner)
  • Network discovery → mDNS + TCP scan finds local hosts; Add Host works
  • Import → source picker grid shows 9 sources; each parses correctly
  • Known hosts import → imports fingerprints from ~/.ssh/known_hosts
  • Keyword highlight → Error/Warning rules tint output; custom rules persist across restart

thangnm93 added 30 commits June 7, 2026 21:39
Render-layer overlay approach via xterm fork — scans only visible lines
at paint time, no data mutation, recordings unaffected.
…ncation, Color.toARGB32

- Error/Fail/Warning/Warn default backgrounds: 0xFF→0xCC (80% opacity) so text
  stays legible under the background rect (opaque colors painted post-glyph
  would cover the matched text entirely)
- _paintKeywordHighlights lineY: add .truncateToDouble() to match paintLine's
  coordinate rounding and avoid sub-pixel vertical misalignment
- Color serialization: foreground?.value → toARGB32() to silence deprecation
Per-host live monitoring panel — CPU/mem/disk/uptime/ports/firewall via
draggable bottom sheet on the Hosts Dashboard. Covers models, two polling
services (SystemStatsService 5s, FirewallStatusService 30s), UI layout,
error handling, and test plan.
- local_terminal_pane + recording_player_widget: pass keywordRules so
  local shells and recording playback actually show highlights
- split_terminal_view + main_screen: thread onNavigateToSettings so the
  'Manage rules in Settings →' link in the config panel is reachable
- terminal_view: remove redundant context.select (context.watch already
  subscribes; select was a no-op and produced a new list identity each build)
- render.dart: build a string-index → cell-column map before matching so
  highlights land on the correct pixel column when wide (CJK) chars are present
- keyword_highlight_rule: guard toXtermRule against both-null fg+bg (avoids
  a no-op rule scanning every visible line); treat missing 'id' in fromJson
  as null so constructor auto-generates a UUID instead of throwing TypeError
- keyword_highlight_settings: re-read provider state after await showDialog
  to avoid stale-snapshot overwrites; re-check rule cap before add() to close
  the sync-race window that could push count past kMaxKeywordHighlightRules
thangnm93 added 28 commits June 8, 2026 21:26
- fix #1: Connect button broken — move Navigator.pop() after await addHost
  so context.mounted is true and connectAny actually fires
- fix #2: hostsInSubnet now respects CIDR prefix length (was always 254);
  /25 → 126 hosts, /23 → 510, /16 → 65534
- fix #3: mDNS service types scanned in parallel via Future.wait (max 5s
  instead of sequential 3x5s = 15s freeze)
- fix #4: per-scan _ScanToken replaces shared _cancelled field; restarting
  a scan no longer resets the old scan's cancellation state
- fix #5: onSave checks context.mounted before context.read<HostProvider>
- fix #6: _onAdd passes builder context (panelCtx) to onClose so close
  targets the panel route, not potentially an open sub-dialog
- fix #7: subnetFromAddress guards against <4-part addresses (IPv6/empty)
- fix #8: _mdnsCount/_tcpCount derived from _results (not separate mutable
  counters that diverge when hosts are merged from two sources)
- fix #9: DiscoveredHost.preferredPort extracted; removes duplication
  between _onAdd and _onConnect
- fix #10: SubnetInfo.interfaceDisplayName is single source of truth;
  P2PSyncService.NetworkInterfaceInfo.displayName delegates to it
…CRT XML + Ansible parsers; fix xml extension import
…er monitor, network discovery, import expansion
Add ImportSource enum and ImportSourceDef registry (9 sources) to
import_panel.dart, and wire a 3-column grid source-picker as the new
first step of the import flow. Selecting a source shows the existing
file/paste UI scoped to that source's file extensions, hint text, and
parser; the back arrow returns to the picker. Legacy exported functions
(parseSshConfig, parseCsvHosts, parseJsonHosts, detectAndParse) are
unchanged for backward compat.
…olling services

SystemStatsService and FirewallStatusService now guard against overlapping
poll() calls with _inFlight, surface errors via optional onError callback,
and log failures with debugPrint instead of swallowing them silently.
Wire onError callbacks from both polling services into _statsError /
_firewallError fields; show inline error text when the first poll fails
instead of a perpetual spinner. Update the widget test's fake SSH to
use a never-completing future so the loading-state test remains valid.
…rvice

Replace bare catch(_){} with catch(e) + debugPrint in: mDNS bind failure,
mDNS A-record lookup, DNS fallback, per-service-type timeout, and the
top-level run().catchError handler. TCP scan is unaffected by mDNS errors.
… NetworkDiscoverySheet

_loadSubnets now catches interface enumeration failures and surfaces them
via _subnetsError. The stream onError handler now logs via debugPrint and
sets _scanError shown in the result list. Both error strings render in the
UI instead of being silently discarded.
…cel test

DiscoveredHost.merge() now preserves the source when both sides share the
same source (e.g. two TCP hits) instead of always upgrading to 'both'.
The cancel-stops-emitting test now asserts emitted < 254 (scan interrupted
before completion) instead of the vacuously-true >= 0.
RenderTerminal.keywordRules setter now performs a structural comparison
(pattern source, case-sensitivity, foreground, background) when identity
differs, preventing unnecessary repaints every build() due to a freshly
allocated list with identical contents.
…aceDisplayName, toXtermRule

- KnownHostsImporter: 10 cases covering happy path, bracket format,
  comma-separated hosts, @cert-authority skip, hashed-line skip, !negation
  strip, malformed base64 skip, empty input, comments, and short lines
- DiscoveredHost.preferredPort: 4 cases (RDP, port 22, port 2222, fallback)
- DiscoveredHost.merge source: same-source preserves source; mixed → both
- SubnetInfo.interfaceDisplayName: 6 cases (en0, wlan0, eth0, utun0, bridge0, unknown)
- AppKeywordHighlightRule.toXtermRule: null when both colors null
- FirewallStatusService: stop() cancels timer; onError callback fires on exec exception
@thangnm93 thangnm93 changed the title feat: keyword highlighting + server monitor panel feat: keyword highlighting, server monitor, network discovery, import sources (v0.1.34) Jun 8, 2026
@thangnm93 thangnm93 merged commit 06e62fc into master Jun 8, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant