chore: highlight selected item in dropdowns (#2181)
This commit is contained in:
parent
1c1777bce4
commit
af923d67bf
8 changed files with 174 additions and 80 deletions
|
|
@ -15,6 +15,7 @@ import 'package:fluffychat/pangea/activity_planner/media_enum.dart';
|
|||
import 'package:fluffychat/pangea/activity_planner/suggestion_form_field.dart';
|
||||
import 'package:fluffychat/pangea/activity_planner/topic_list_repo.dart';
|
||||
import 'package:fluffychat/pangea/chat_settings/widgets/language_level_dropdown.dart';
|
||||
import 'package:fluffychat/pangea/common/widgets/dropdown_text_button.dart';
|
||||
import 'package:fluffychat/pangea/instructions/instructions_enum.dart';
|
||||
import 'package:fluffychat/pangea/instructions/instructions_inline_tooltip.dart';
|
||||
import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart';
|
||||
|
|
@ -256,23 +257,42 @@ class ActivityPlannerPageState extends State<ActivityPlannerPage> {
|
|||
),
|
||||
const SizedBox(height: 24),
|
||||
DropdownButtonFormField2<MediaEnum>(
|
||||
customButton: CustomDropdownTextButton(
|
||||
text: _selectedMedia.toDisplayCopyUsingL10n(context),
|
||||
),
|
||||
menuItemStyleData: const MenuItemStyleData(
|
||||
padding: EdgeInsets.zero, // Remove default padding
|
||||
),
|
||||
decoration: InputDecoration(labelText: l10n.mediaLabel),
|
||||
isExpanded: true,
|
||||
dropdownStyleData: DropdownStyleData(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.surfaceContainerHigh,
|
||||
),
|
||||
),
|
||||
items: MediaEnum.values
|
||||
.map(
|
||||
(e) => DropdownMenuItem(
|
||||
value: e,
|
||||
child: Text(e.toDisplayCopyUsingL10n(context)),
|
||||
child: DropdownTextButton(
|
||||
text: e.toDisplayCopyUsingL10n(context),
|
||||
isSelected: _selectedMedia == e,
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
onChanged: (val) =>
|
||||
_selectedMedia = val ?? MediaEnum.nan,
|
||||
onChanged: (val) {
|
||||
setState(() => _selectedMedia = val ?? MediaEnum.nan);
|
||||
},
|
||||
value: _selectedMedia,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
LanguageLevelDropdown(
|
||||
initialLevel: _selectedCefrLevel,
|
||||
onChanged: (val) => _selectedCefrLevel = val,
|
||||
onChanged: (val) =>
|
||||
setState(() => _selectedCefrLevel = val),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
PLanguageDropdown(
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@ class ConversationBotModeDynamicZone extends StatelessWidget {
|
|||
decoration: InputDecoration(
|
||||
hintText: L10n.of(context)
|
||||
.conversationBotDiscussionZone_discussionTopicPlaceholder,
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 28.0, vertical: 12.0),
|
||||
),
|
||||
controller: discussionTopicController,
|
||||
validator: (value) => enabled &&
|
||||
|
|
@ -57,7 +55,6 @@ class ConversationBotModeDynamicZone extends StatelessWidget {
|
|||
decoration: InputDecoration(
|
||||
hintText: L10n.of(context)
|
||||
.conversationBotDiscussionZone_discussionKeywordsPlaceholder,
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 28.0),
|
||||
),
|
||||
controller: discussionKeywordsController,
|
||||
enabled: hasPermission && enabled,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import 'package:dropdown_button2/dropdown_button2.dart';
|
|||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/chat_settings/constants/bot_mode.dart';
|
||||
import 'package:fluffychat/pangea/common/widgets/dropdown_text_button.dart';
|
||||
|
||||
class ConversationBotModeSelect extends StatelessWidget {
|
||||
final String? initialMode;
|
||||
|
|
@ -32,15 +33,28 @@ class ConversationBotModeSelect extends StatelessWidget {
|
|||
};
|
||||
|
||||
return DropdownButtonFormField2(
|
||||
customButton: initialMode != null && options.containsKey(initialMode)
|
||||
? CustomDropdownTextButton(
|
||||
text: options[initialMode]!,
|
||||
)
|
||||
: null,
|
||||
menuItemStyleData: const MenuItemStyleData(
|
||||
padding: EdgeInsets.zero, // Remove default padding
|
||||
),
|
||||
isExpanded: true,
|
||||
dropdownStyleData: DropdownStyleData(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||
),
|
||||
),
|
||||
hint: Text(L10n.of(context).selectBotChatMode),
|
||||
items: [
|
||||
for (final entry in options.entries)
|
||||
DropdownMenuItem(
|
||||
value: entry.key,
|
||||
child: Text(
|
||||
entry.value,
|
||||
overflow: TextOverflow.clip,
|
||||
textAlign: TextAlign.center,
|
||||
child: DropdownTextButton(
|
||||
text: entry.value,
|
||||
isSelected: initialMode == entry.key,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/chat_settings/models/bot_options_model.dart';
|
||||
|
|
@ -9,6 +8,8 @@ import 'package:fluffychat/pangea/chat_settings/widgets/conversation_bot/convers
|
|||
import 'package:fluffychat/pangea/chat_settings/widgets/conversation_bot/conversation_bot_no_permission_dialog.dart';
|
||||
import 'package:fluffychat/pangea/chat_settings/widgets/language_level_dropdown.dart';
|
||||
import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/learning_settings/utils/p_language_store.dart';
|
||||
import 'package:fluffychat/pangea/learning_settings/widgets/p_language_dropdown.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
class ConversationBotSettingsForm extends StatelessWidget {
|
||||
|
|
@ -48,44 +49,15 @@ class ConversationBotSettingsForm extends StatelessWidget {
|
|||
children: [
|
||||
InkWell(
|
||||
onTap: hasPermission ? null : () => showNoPermissionDialog(context),
|
||||
child: DropdownButtonFormField2(
|
||||
dropdownStyleData: const DropdownStyleData(
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
hint: Text(
|
||||
L10n.of(context).selectBotLanguage,
|
||||
overflow: TextOverflow.clip,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
value: botOptions.targetLanguage,
|
||||
isExpanded: true,
|
||||
items: MatrixState.pangeaController.pLanguageStore.targetOptions
|
||||
.map((language) {
|
||||
return DropdownMenuItem(
|
||||
value: language.langCode,
|
||||
child: Text(
|
||||
language.getDisplayName(context) ?? language.langCode,
|
||||
overflow: TextOverflow.clip,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: hasPermission && enabled ? onUpdateBotLanguage : null,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
InkWell(
|
||||
onTap: hasPermission ? null : () => showNoPermissionDialog(context),
|
||||
child: DropdownButtonFormField2<String>(
|
||||
hint: Text(
|
||||
L10n.of(context).chooseVoice,
|
||||
overflow: TextOverflow.clip,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
value: botOptions.targetVoice,
|
||||
isExpanded: true,
|
||||
items: const [],
|
||||
onChanged: hasPermission && enabled ? onUpdateBotVoice : null,
|
||||
child: PLanguageDropdown(
|
||||
languages:
|
||||
MatrixState.pangeaController.pLanguageStore.targetOptions,
|
||||
onChange: (lang) => hasPermission && enabled
|
||||
? onUpdateBotLanguage(lang.langCode)
|
||||
: null,
|
||||
initialLanguage: botOptions.targetLanguage != null
|
||||
? PLanguageStore.byLangCode(botOptions.targetLanguage!)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:dropdown_button2/dropdown_button2.dart';
|
|||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/chat_settings/utils/language_level_copy.dart';
|
||||
import 'package:fluffychat/pangea/common/widgets/dropdown_text_button.dart';
|
||||
import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart';
|
||||
|
||||
class LanguageLevelDropdown extends StatelessWidget {
|
||||
|
|
@ -26,39 +27,47 @@ class LanguageLevelDropdown extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DropdownButtonFormField2<LanguageLevelTypeEnum>(
|
||||
decoration: InputDecoration(labelText: L10n.of(context).cefrLevelLabel),
|
||||
hint: Text(
|
||||
L10n.of(context).selectLanguageLevel,
|
||||
overflow: TextOverflow.clip,
|
||||
textAlign: TextAlign.center,
|
||||
customButton: initialLevel != null &&
|
||||
LanguageLevelTypeEnum.values.contains(initialLevel)
|
||||
? CustomDropdownTextButton(
|
||||
text: LanguageLevelTextPicker.languageLevelText(
|
||||
context,
|
||||
initialLevel!,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
menuItemStyleData: const MenuItemStyleData(
|
||||
padding: EdgeInsets.zero, // Remove default padding
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
labelText: L10n.of(context).cefrLevelLabel,
|
||||
),
|
||||
isExpanded: true,
|
||||
dropdownStyleData: DropdownStyleData(
|
||||
maxHeight: kIsWeb ? 500 : null,
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor ??
|
||||
Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||
),
|
||||
),
|
||||
value: initialLevel,
|
||||
items:
|
||||
LanguageLevelTypeEnum.values.map((LanguageLevelTypeEnum levelOption) {
|
||||
return DropdownMenuItem(
|
||||
value: levelOption,
|
||||
child: Text(
|
||||
LanguageLevelTextPicker.languageLevelText(
|
||||
child: DropdownTextButton(
|
||||
text: LanguageLevelTextPicker.languageLevelText(
|
||||
context,
|
||||
levelOption,
|
||||
),
|
||||
overflow: TextOverflow.clip,
|
||||
textAlign: TextAlign.center,
|
||||
isSelected: initialLevel == levelOption,
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: enabled
|
||||
? (value) => onChanged?.call(value as LanguageLevelTypeEnum)
|
||||
: null,
|
||||
value: initialLevel,
|
||||
validator: validator,
|
||||
dropdownStyleData: DropdownStyleData(
|
||||
maxHeight: kIsWeb ? 500 : null,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
color: backgroundColor ??
|
||||
Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
63
lib/pangea/common/widgets/dropdown_text_button.dart
Normal file
63
lib/pangea/common/widgets/dropdown_text_button.dart
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class DropdownTextButton extends StatelessWidget {
|
||||
final bool isSelected;
|
||||
final String text;
|
||||
|
||||
const DropdownTextButton({
|
||||
required this.text,
|
||||
this.isSelected = false,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: isSelected
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.primary
|
||||
.withAlpha(20) // Highlight selected
|
||||
: Colors.transparent,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 12,
|
||||
horizontal: 12,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
text,
|
||||
overflow: TextOverflow.clip,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CustomDropdownTextButton extends StatelessWidget {
|
||||
final String text;
|
||||
|
||||
const CustomDropdownTextButton({
|
||||
required this.text,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
text,
|
||||
overflow: TextOverflow.clip,
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
Icons.arrow_drop_down,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -43,6 +43,9 @@ class CountryPickerDropdownState extends State<CountryPickerDropdown> {
|
|||
isDropdown: true,
|
||||
)
|
||||
: null,
|
||||
menuItemStyleData: const MenuItemStyleData(
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
isExpanded: true,
|
||||
decoration: InputDecoration(
|
||||
labelText: L10n.of(context).countryInformation,
|
||||
|
|
@ -50,7 +53,7 @@ class CountryPickerDropdownState extends State<CountryPickerDropdown> {
|
|||
dropdownStyleData: DropdownStyleData(
|
||||
maxHeight: kIsWeb ? 500 : null,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
// borderRadius: BorderRadius.circular(14),
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||
),
|
||||
),
|
||||
|
|
@ -58,7 +61,16 @@ class CountryPickerDropdownState extends State<CountryPickerDropdown> {
|
|||
...countries.map(
|
||||
(country) => DropdownMenuItem(
|
||||
value: country,
|
||||
child: CountryPickerTile(country),
|
||||
child: Container(
|
||||
color: widget.learningController.country == country
|
||||
? Theme.of(context).colorScheme.primary.withAlpha(20)
|
||||
: Colors.transparent,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
horizontal: 12,
|
||||
),
|
||||
child: CountryPickerTile(country),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class PLanguageDropdown extends StatefulWidget {
|
|||
final Function(LanguageModel) onChange;
|
||||
final bool showMultilingual;
|
||||
final bool isL2List;
|
||||
final String decorationText;
|
||||
final String? decorationText;
|
||||
final String? error;
|
||||
final String? Function(LanguageModel?)? validator;
|
||||
final Color? backgroundColor;
|
||||
|
|
@ -28,7 +28,7 @@ class PLanguageDropdown extends StatefulWidget {
|
|||
required this.onChange,
|
||||
required this.initialLanguage,
|
||||
this.showMultilingual = false,
|
||||
required this.decorationText,
|
||||
this.decorationText,
|
||||
this.isL2List = false,
|
||||
this.error,
|
||||
this.validator,
|
||||
|
|
@ -95,21 +95,19 @@ class PLanguageDropdownState extends State<PLanguageDropdown> {
|
|||
isDropdown: true,
|
||||
)
|
||||
: null,
|
||||
menuItemStyleData: const MenuItemStyleData(
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
labelText: widget.decorationText,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(36.0),
|
||||
),
|
||||
enabledBorder: hasError
|
||||
? OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(36.0),
|
||||
borderSide:
|
||||
BorderSide(color: Theme.of(context).colorScheme.error),
|
||||
)
|
||||
: null,
|
||||
focusedBorder: hasError
|
||||
? OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(36.0),
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
width: 2,
|
||||
|
|
@ -138,9 +136,18 @@ class PLanguageDropdownState extends State<PLanguageDropdown> {
|
|||
...sortedLanguages.map(
|
||||
(languageModel) => DropdownMenuItem(
|
||||
value: languageModel,
|
||||
child: LanguageDropDownEntry(
|
||||
languageModel: languageModel,
|
||||
isL2List: widget.isL2List,
|
||||
child: Container(
|
||||
color: widget.initialLanguage == languageModel
|
||||
? Theme.of(context).colorScheme.primary.withAlpha(20)
|
||||
: Colors.transparent,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
horizontal: 12,
|
||||
),
|
||||
child: LanguageDropDownEntry(
|
||||
languageModel: languageModel,
|
||||
isL2List: widget.isL2List,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue