From 3c470002910c26890ac63667d328ebc3a2a6b806 Mon Sep 17 00:00:00 2001 From: keinstn Date: Wed, 29 Jul 2026 19:11:17 +0900 Subject: [PATCH 1/2] fix: disable SSH key text scanning --- app/lib/src/screens/host_setup_screen.dart | 2 ++ app/test/screens/host_setup_screen_test.dart | 27 ++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/app/lib/src/screens/host_setup_screen.dart b/app/lib/src/screens/host_setup_screen.dart index 2471ad6..3160adf 100644 --- a/app/lib/src/screens/host_setup_screen.dart +++ b/app/lib/src/screens/host_setup_screen.dart @@ -7,6 +7,7 @@ import '../models/host_config.dart'; import '../models/plugin_info.dart'; import '../notifications/host_pairing.dart'; import '../widgets/error_message_view.dart'; +import '../widgets/text_context_menu.dart'; /// Form for entering (or editing) the SSH connection details for the dev /// machine running Herdr. @@ -414,6 +415,7 @@ class _HostSetupScreenState extends State { ), style: const TextStyle(fontFamily: 'monospace'), maxLines: 6, + contextMenuBuilder: noScanTextContextMenuBuilder, validator: (v) { final t = v?.trim() ?? ''; if (t.isEmpty) return l10n.hostSetupPrivateKeyRequired; diff --git a/app/test/screens/host_setup_screen_test.dart b/app/test/screens/host_setup_screen_test.dart index 55401b4..768cd34 100644 --- a/app/test/screens/host_setup_screen_test.dart +++ b/app/test/screens/host_setup_screen_test.dart @@ -5,6 +5,7 @@ import 'package:drover/src/models/host_config.dart'; import 'package:drover/src/models/plugin_info.dart'; import 'package:drover/src/notifications/host_pairing.dart'; import 'package:drover/src/screens/host_setup_screen.dart'; +import 'package:drover/src/widgets/text_context_menu.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -21,6 +22,32 @@ const _samplePlugin = PluginInfo( ); void main() { + testWidgets('disables Scan Text for the SSH private-key input', ( + tester, + ) async { + await tester.pumpWidget( + MaterialApp( + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + home: HostSetupScreen(onSubmit: (config) async {}), + ), + ); + + final privateKeyEditableText = tester.widget( + find.descendant( + of: find.widgetWithText(TextFormField, 'Private key PEM'), + matching: find.byType(EditableText), + ), + ); + + expect( + privateKeyEditableText.contextMenuBuilder, + same(noScanTextContextMenuBuilder), + ); + + await tester.pumpWidget(const SizedBox()); + }); + testWidgets('renders the demo entry when onEnterDemo is provided', ( tester, ) async { From 8417d8157b8cd163171f863535a0ced4913712e4 Mon Sep 17 00:00:00 2001 From: keinstn Date: Wed, 29 Jul 2026 19:20:29 +0900 Subject: [PATCH 2/2] fix: disable host setup text scanning --- app/lib/src/screens/host_setup_screen.dart | 6 ++++ app/test/screens/host_setup_screen_test.dart | 30 +++++++++++++++----- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/app/lib/src/screens/host_setup_screen.dart b/app/lib/src/screens/host_setup_screen.dart index 3160adf..3d279e2 100644 --- a/app/lib/src/screens/host_setup_screen.dart +++ b/app/lib/src/screens/host_setup_screen.dart @@ -373,11 +373,13 @@ class _HostSetupScreenState extends State { TextFormField( controller: _nameController, decoration: InputDecoration(labelText: l10n.hostSetupNameLabel), + contextMenuBuilder: noScanTextContextMenuBuilder, ), const SizedBox(height: 12), TextFormField( controller: _hostController, decoration: InputDecoration(labelText: l10n.hostSetupHostLabel), + contextMenuBuilder: noScanTextContextMenuBuilder, validator: (v) => (v == null || v.trim().isEmpty) ? l10n.hostSetupHostRequired : null, @@ -387,6 +389,7 @@ class _HostSetupScreenState extends State { controller: _portController, decoration: InputDecoration(labelText: l10n.hostSetupPortLabel), keyboardType: TextInputType.number, + contextMenuBuilder: noScanTextContextMenuBuilder, // Blank is allowed and defaults to 22 (see _buildConfig); only a // non-blank value has to be a valid port number. validator: (v) { @@ -403,6 +406,7 @@ class _HostSetupScreenState extends State { TextFormField( controller: _userController, decoration: InputDecoration(labelText: l10n.hostSetupUserLabel), + contextMenuBuilder: noScanTextContextMenuBuilder, validator: (v) => (v == null || v.trim().isEmpty) ? l10n.hostSetupUserRequired : null, @@ -432,6 +436,7 @@ class _HostSetupScreenState extends State { labelText: l10n.hostSetupPassphraseLabel, ), obscureText: true, + contextMenuBuilder: noScanTextContextMenuBuilder, ), const SizedBox(height: 12), ExpansionTile( @@ -443,6 +448,7 @@ class _HostSetupScreenState extends State { decoration: InputDecoration( labelText: l10n.hostSetupHerdrBinLabel, ), + contextMenuBuilder: noScanTextContextMenuBuilder, ), ], ), diff --git a/app/test/screens/host_setup_screen_test.dart b/app/test/screens/host_setup_screen_test.dart index 768cd34..04031fb 100644 --- a/app/test/screens/host_setup_screen_test.dart +++ b/app/test/screens/host_setup_screen_test.dart @@ -22,9 +22,7 @@ const _samplePlugin = PluginInfo( ); void main() { - testWidgets('disables Scan Text for the SSH private-key input', ( - tester, - ) async { + testWidgets('disables Scan Text for every host setup input', (tester) async { await tester.pumpWidget( MaterialApp( localizationsDelegates: AppLocalizations.localizationsDelegates, @@ -32,16 +30,34 @@ void main() { home: HostSetupScreen(onSubmit: (config) async {}), ), ); + final editableTexts = tester.widgetList( + find.byType(EditableText), + ); + + expect(editableTexts, hasLength(6)); + for (final editableText in editableTexts) { + expect( + editableText.contextMenuBuilder, + same(noScanTextContextMenuBuilder), + ); + } + + await tester.scrollUntilVisible( + find.byType(ExpansionTile), + 500, + scrollable: find.byType(Scrollable).first, + ); + await tester.tap(find.byType(ExpansionTile)); + await tester.pumpAndSettle(); - final privateKeyEditableText = tester.widget( + final herdrBinEditableText = tester.widget( find.descendant( - of: find.widgetWithText(TextFormField, 'Private key PEM'), + of: find.byType(ExpansionTile), matching: find.byType(EditableText), ), ); - expect( - privateKeyEditableText.contextMenuBuilder, + herdrBinEditableText.contextMenuBuilder, same(noScanTextContextMenuBuilder), );