From fccd6135f7f4cc44b89b800cca9d090955ddfb41 Mon Sep 17 00:00:00 2001 From: Yijing Huang Date: Mon, 24 Apr 2023 21:20:10 -0500 Subject: [PATCH] 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 --- .../lib/workspace/application/appearance.dart | 22 ++- .../widgets/settings_appearance_view.dart | 8 +- .../widgets/settings_language_view.dart | 162 ++++++++++-------- 3 files changed, 108 insertions(+), 84 deletions(-) diff --git a/frontend/appflowy_flutter/lib/workspace/application/appearance.dart b/frontend/appflowy_flutter/lib/workspace/application/appearance.dart index 8093456ea1..714d9a951d 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/appearance.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/appearance.dart @@ -242,6 +242,12 @@ class AppearanceSettingsState with _$AppearanceSettingsState { shadow: theme.shadow, ); + const Set scrollbarInteractiveStates = { + MaterialState.pressed, + MaterialState.hovered, + MaterialState.dragged, + }; + return ThemeData( brightness: brightness, textTheme: _getTextTheme(fontFamily: fontFamily, fontColor: theme.text), @@ -264,15 +270,15 @@ class AppearanceSettingsState with _$AppearanceSettingsState { contentTextStyle: TextStyle(color: colorScheme.onSurface), ), 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) { - const Set interactiveStates = { - MaterialState.pressed, - MaterialState.hovered, - MaterialState.dragged, - }; - if (states.any(interactiveStates.contains)) { - return 5.0; + if (states.any(scrollbarInteractiveStates.contains)) { + return 4; } return 3.0; }), diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_appearance_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_appearance_view.dart index acbec83aa2..57c2d2a789 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_appearance_view.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_appearance_view.dart @@ -77,8 +77,8 @@ class ThemeSetting extends StatelessWidget { child: FlowyButton( text: FlowyText.medium(theme), rightIcon: currentTheme == theme - ? svgWidget("grid/checkmark") - : const SizedBox(), + ? const FlowySvg(name: 'grid/checkmark') + : null, onTap: () { if (currentTheme != theme) { context.read().setTheme(theme); @@ -134,8 +134,8 @@ class ThemeModeSetting extends StatelessWidget { child: FlowyButton( text: FlowyText.medium(_themeModeLabelText(themeMode)), rightIcon: currentThemeMode == themeMode - ? svgWidget("grid/checkmark") - : const SizedBox(), + ? const FlowySvg(name: 'grid/checkmark') + : null, onTap: () { if (currentThemeMode != themeMode) { context.read().setThemeMode(themeMode); diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_language_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_language_view.dart index 2807554195..23fb31fbc8 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_language_view.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_language_view.dart @@ -1,7 +1,9 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/workspace/application/appearance.dart'; +import 'package:appflowy_popover/appflowy_popover.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:flowy_infra/language.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -12,85 +14,101 @@ class SettingsLanguageView extends StatelessWidget { @override Widget build(BuildContext context) { return SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - FlowyText.medium(LocaleKeys.settings_menu_language.tr()), - const LanguageSelectorDropdown(), - ], - ), - ], + child: BlocBuilder( + builder: (context, state) => Row( + children: [ + Expanded( + child: FlowyText.medium( + LocaleKeys.settings_menu_language.tr(), + ), + ), + LanguageSelector(currentLocale: state.locale), + ], + ), ), ); } } -class LanguageSelectorDropdown extends StatefulWidget { - const LanguageSelectorDropdown({ - Key? key, - }) : super(key: key); - - @override - State createState() => - _LanguageSelectorDropdownState(); -} - -class _LanguageSelectorDropdownState extends State { - 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; - }); - } +class LanguageSelector extends StatelessWidget { + final Locale currentLocale; + const LanguageSelector({ + super.key, + required this.currentLocale, + }); @override Widget build(BuildContext context) { - return MouseRegion( - onEnter: (_) => hoverEnterLanguage(), - onExit: (_) => hoverExitLanguage(), - child: Container( - margin: const EdgeInsets.symmetric(horizontal: 8), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - color: currHoverColor, - ), - child: DropdownButtonHideUnderline( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 6), - child: DropdownButton( - value: context.locale, - dropdownColor: Theme.of(context).cardColor, - onChanged: (locale) { - context - .read() - .setLocale(context, locale!); - }, - autofocus: true, - borderRadius: BorderRadius.circular(8), - items: - EasyLocalization.of(context)!.supportedLocales.map((locale) { - return DropdownMenuItem( - value: locale, - child: Padding( - padding: const EdgeInsets.all(12.0), - child: FlowyText.medium( - languageFromLocale(locale), - color: Theme.of(context).colorScheme.tertiary, - ), - ), - ); - }).toList(), - ), - ), - ), + return AppFlowyPopover( + direction: PopoverDirection.bottomWithRightAligned, + child: FlowyTextButton( + languageFromLocale(currentLocale), + fontColor: Theme.of(context).colorScheme.onBackground, + fillColor: Colors.transparent, + onPressed: () {}, + ), + popupBuilder: (BuildContext context) { + final allLocales = EasyLocalization.of(context)!.supportedLocales; + + return LanguageItemsListView( + allLocales: allLocales, + currentLocale: currentLocale, + ); + }, + ); + } +} + +class LanguageItemsListView extends StatelessWidget { + const LanguageItemsListView({ + super.key, + required this.allLocales, + required this.currentLocale, + }); + + final List 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), + ), + rightIcon: currentLocale == locale + ? const FlowySvg(name: 'grid/checkmark') + : null, + onTap: () { + if (currentLocale != locale) { + context.read().setLocale(context, locale); + } + }, ), ); }