From b6ddac2ce0860d55037052745d0bab79e8a95ef8 Mon Sep 17 00:00:00 2001 From: zarzet <42882290+zarzet@users.noreply.github.com> Date: Sun, 4 Oct 2026 05:03:14 +0700 Subject: [PATCH] fix(extensions): use themed account option picker --- lib/utils/extension_action_forms.dart | 65 ++++++++++++++++++--------- test/extension_action_forms_test.dart | 26 +++++++---- 2 files changed, 61 insertions(+), 30 deletions(-) diff --git a/lib/utils/extension_action_forms.dart b/lib/utils/extension_action_forms.dart index 9e1d509f..cd263d0c 100644 --- a/lib/utils/extension_action_forms.dart +++ b/lib/utils/extension_action_forms.dart @@ -205,6 +205,7 @@ class _AccountFormDialogState extends State<_AccountFormDialog> { } Future _chooseOption(Map field) async { + FocusScope.of(context).unfocus(); final key = field['key'] as String; final value = await showAppBottomSheet( context: context, @@ -215,12 +216,15 @@ class _AccountFormDialogState extends State<_AccountFormDialog> { mainAxisSize: MainAxisSize.min, children: [ for (final option in (field['options'] as List).cast()) - AppSheetOption( - title: Text(option), - trailing: option == _choices[key] - ? const Icon(CupertinoIcons.check_mark) - : null, - onTap: () => Navigator.pop(sheetContext, option), + Semantics( + selected: option == _choices[key], + child: AppSheetOption( + title: Text(option), + trailing: option == _choices[key] + ? const Icon(Icons.check) + : null, + onTap: () => Navigator.pop(sheetContext, option), + ), ), ], ), @@ -244,6 +248,10 @@ class _AccountFormDialogState extends State<_AccountFormDialog> { borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none, ); + final themedBorder = theme.inputDecorationTheme.enabledBorder; + final materialRadius = themedBorder is OutlineInputBorder + ? themedBorder.borderRadius + : border.borderRadius; final decoration = InputDecoration( labelText: label, filled: true, @@ -275,20 +283,31 @@ class _AccountFormDialogState extends State<_AccountFormDialog> { ], ), ) - : DropdownButtonFormField( - initialValue: _choices[key], - isExpanded: true, - decoration: decoration, - items: (field['options'] as List) - .cast() - .map( - (option) => - DropdownMenuItem(value: option, child: Text(option)), - ) - .toList(), - onChanged: (value) { - if (value != null) setState(() => _choices[key] = value); - }, + : Material( + color: Colors.transparent, + child: Ink( + decoration: BoxDecoration( + color: decoration.fillColor, + borderRadius: materialRadius, + ), + child: InkWell( + borderRadius: materialRadius, + onTap: () => _chooseOption(field), + child: InputDecorator( + decoration: decoration.copyWith( + fillColor: Colors.transparent, + suffixIcon: Icon( + Icons.expand_more, + color: colors.onSurfaceVariant, + ), + ), + child: Text( + _choices[key]!, + style: theme.textTheme.bodyLarge, + ), + ), + ), + ), ); } else if (mornye) { input = FormField( @@ -362,7 +381,11 @@ class _AccountFormDialogState extends State<_AccountFormDialog> { ), ), ], - Semantics(label: label, child: input), + Semantics( + label: label, + button: field['type'] == 'select' ? true : null, + child: input, + ), ], ), ); diff --git a/test/extension_action_forms_test.dart b/test/extension_action_forms_test.dart index ca133ab1..0c2d57f5 100644 --- a/test/extension_action_forms_test.dart +++ b/test/extension_action_forms_test.dart @@ -9,6 +9,7 @@ import 'package:spotiflac_android/models/settings.dart'; import 'package:spotiflac_android/providers/settings_provider.dart'; import 'package:spotiflac_android/theme/mornye_theme.dart'; import 'package:spotiflac_android/utils/extension_action_forms.dart'; +import 'package:spotiflac_android/widgets/app_bottom_sheet.dart'; class _Settings extends SettingsNotifier { @override @@ -126,16 +127,23 @@ void main() { final text = tester.widget(fields.last); expect(text.obscureText, isTrue); expect(text.enableIMEPersonalizedLearning, isFalse); - await tester.tap(find.text('Europe')); - await tester.pumpAndSettle(); - await tester.tap(find.text('Asia')); - await tester.pumpAndSettle(); - } else { - await tester.tap(find.byType(DropdownButtonFormField)); - await tester.pumpAndSettle(); - await tester.tap(find.text('Asia').last); - await tester.pumpAndSettle(); } + await tester.tap(find.text('Europe')); + await tester.pumpAndSettle(); + expect(find.byType(AppBottomSheet), findsOneWidget); + expect(find.byType(AppSheetOption), findsNWidgets(2)); + expect(tester.testTextInput.isVisible, isFalse); + + // Dismissing the picker must leave both the choice and typed fields intact. + await tester.binding.handlePopRoute(); + await tester.pumpAndSettle(); + expect(find.text('Europe'), findsOneWidget); + await tester.tap(find.text('Europe')); + await tester.pumpAndSettle(); + await tester.tap(find.text('Asia')); + await tester.pumpAndSettle(); + expect(find.byType(AppBottomSheet), findsNothing); + expect(find.text('Asia'), findsOneWidget); await tester.tap(find.text('Continue')); await tester.pumpAndSettle(); expect(result!['state'], 'active');