feat: change the UI of language selector (#2317)

* feat: change the UI of language selector

* chore: clean up code

* chore: delete unnecessary code and clean up
This commit is contained in:
Yijing Huang 2023-04-24 21:20:10 -05:00 committed by GitHub
parent 49caf74ee1
commit fccd6135f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 108 additions and 84 deletions

View File

@ -242,6 +242,12 @@ class AppearanceSettingsState with _$AppearanceSettingsState {
shadow: theme.shadow, shadow: theme.shadow,
); );
const Set<MaterialState> scrollbarInteractiveStates = <MaterialState>{
MaterialState.pressed,
MaterialState.hovered,
MaterialState.dragged,
};
return ThemeData( return ThemeData(
brightness: brightness, brightness: brightness,
textTheme: _getTextTheme(fontFamily: fontFamily, fontColor: theme.text), textTheme: _getTextTheme(fontFamily: fontFamily, fontColor: theme.text),
@ -264,15 +270,15 @@ class AppearanceSettingsState with _$AppearanceSettingsState {
contentTextStyle: TextStyle(color: colorScheme.onSurface), contentTextStyle: TextStyle(color: colorScheme.onSurface),
), ),
scrollbarTheme: ScrollbarThemeData( scrollbarTheme: ScrollbarThemeData(
thumbColor: MaterialStateProperty.all(theme.shader3), thumbColor: MaterialStateProperty.resolveWith((states) {
if (states.any(scrollbarInteractiveStates.contains)) {
return theme.shader7;
}
return theme.shader5;
}),
thickness: MaterialStateProperty.resolveWith((states) { thickness: MaterialStateProperty.resolveWith((states) {
const Set<MaterialState> interactiveStates = <MaterialState>{ if (states.any(scrollbarInteractiveStates.contains)) {
MaterialState.pressed, return 4;
MaterialState.hovered,
MaterialState.dragged,
};
if (states.any(interactiveStates.contains)) {
return 5.0;
} }
return 3.0; return 3.0;
}), }),

View File

@ -77,8 +77,8 @@ class ThemeSetting extends StatelessWidget {
child: FlowyButton( child: FlowyButton(
text: FlowyText.medium(theme), text: FlowyText.medium(theme),
rightIcon: currentTheme == theme rightIcon: currentTheme == theme
? svgWidget("grid/checkmark") ? const FlowySvg(name: 'grid/checkmark')
: const SizedBox(), : null,
onTap: () { onTap: () {
if (currentTheme != theme) { if (currentTheme != theme) {
context.read<AppearanceSettingsCubit>().setTheme(theme); context.read<AppearanceSettingsCubit>().setTheme(theme);
@ -134,8 +134,8 @@ class ThemeModeSetting extends StatelessWidget {
child: FlowyButton( child: FlowyButton(
text: FlowyText.medium(_themeModeLabelText(themeMode)), text: FlowyText.medium(_themeModeLabelText(themeMode)),
rightIcon: currentThemeMode == themeMode rightIcon: currentThemeMode == themeMode
? svgWidget("grid/checkmark") ? const FlowySvg(name: 'grid/checkmark')
: const SizedBox(), : null,
onTap: () { onTap: () {
if (currentThemeMode != themeMode) { if (currentThemeMode != themeMode) {
context.read<AppearanceSettingsCubit>().setThemeMode(themeMode); context.read<AppearanceSettingsCubit>().setThemeMode(themeMode);

View File

@ -1,7 +1,9 @@
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/workspace/application/appearance.dart'; import 'package:appflowy/workspace/application/appearance.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra/image.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flowy_infra/language.dart'; import 'package:flowy_infra/language.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@ -12,85 +14,101 @@ class SettingsLanguageView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SingleChildScrollView( return SingleChildScrollView(
child: Column( child: BlocBuilder<AppearanceSettingsCubit, AppearanceSettingsState>(
crossAxisAlignment: CrossAxisAlignment.start, builder: (context, state) => Row(
children: [ children: [
Row( Expanded(
children: [ child: FlowyText.medium(
FlowyText.medium(LocaleKeys.settings_menu_language.tr()), LocaleKeys.settings_menu_language.tr(),
const LanguageSelectorDropdown(), ),
),
LanguageSelector(currentLocale: state.locale),
], ],
), ),
],
), ),
); );
} }
} }
class LanguageSelectorDropdown extends StatefulWidget { class LanguageSelector extends StatelessWidget {
const LanguageSelectorDropdown({ final Locale currentLocale;
Key? key, const LanguageSelector({
}) : super(key: key); super.key,
required this.currentLocale,
@override
State<LanguageSelectorDropdown> createState() =>
_LanguageSelectorDropdownState();
}
class _LanguageSelectorDropdownState extends State<LanguageSelectorDropdown> {
Color currHoverColor = Colors.white.withOpacity(0.0);
void hoverExitLanguage() {
setState(() {
currHoverColor = Colors.white.withOpacity(0.0);
}); });
}
void hoverEnterLanguage() {
setState(() {
currHoverColor = Theme.of(context).colorScheme.secondaryContainer;
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MouseRegion( return AppFlowyPopover(
onEnter: (_) => hoverEnterLanguage(), direction: PopoverDirection.bottomWithRightAligned,
onExit: (_) => hoverExitLanguage(), child: FlowyTextButton(
child: Container( languageFromLocale(currentLocale),
margin: const EdgeInsets.symmetric(horizontal: 8), fontColor: Theme.of(context).colorScheme.onBackground,
decoration: BoxDecoration( fillColor: Colors.transparent,
borderRadius: BorderRadius.circular(8), onPressed: () {},
color: currHoverColor,
), ),
child: DropdownButtonHideUnderline( popupBuilder: (BuildContext context) {
child: Padding( final allLocales = EasyLocalization.of(context)!.supportedLocales;
padding: const EdgeInsets.symmetric(horizontal: 6),
child: DropdownButton<Locale>( return LanguageItemsListView(
value: context.locale, allLocales: allLocales,
dropdownColor: Theme.of(context).cardColor, currentLocale: currentLocale,
onChanged: (locale) { );
context
.read<AppearanceSettingsCubit>()
.setLocale(context, locale!);
}, },
autofocus: true, );
borderRadius: BorderRadius.circular(8), }
items: }
EasyLocalization.of(context)!.supportedLocales.map((locale) {
return DropdownMenuItem<Locale>( class LanguageItemsListView extends StatelessWidget {
value: locale, const LanguageItemsListView({
child: Padding( super.key,
padding: const EdgeInsets.all(12.0), required this.allLocales,
child: FlowyText.medium( required this.currentLocale,
});
final List<Locale> allLocales;
final Locale currentLocale;
@override
Widget build(BuildContext context) {
return ConstrainedBox(
constraints: const BoxConstraints(maxHeight: 400),
child: ListView.builder(
itemBuilder: (context, index) {
final locale = allLocales[index];
return LanguageItem(locale: locale, currentLocale: currentLocale);
},
itemCount: allLocales.length,
),
);
}
}
class LanguageItem extends StatelessWidget {
final Locale locale;
final Locale currentLocale;
const LanguageItem({
super.key,
required this.locale,
required this.currentLocale,
});
@override
Widget build(BuildContext context) {
return SizedBox(
height: 32,
child: FlowyButton(
text: FlowyText.medium(
languageFromLocale(locale), languageFromLocale(locale),
color: Theme.of(context).colorScheme.tertiary,
),
),
);
}).toList(),
),
),
), ),
rightIcon: currentLocale == locale
? const FlowySvg(name: 'grid/checkmark')
: null,
onTap: () {
if (currentLocale != locale) {
context.read<AppearanceSettingsCubit>().setLocale(context, locale);
}
},
), ),
); );
} }