Browse Source

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
Yijing Huang 2 years ago
parent
commit
fccd6135f7

+ 14 - 8
frontend/appflowy_flutter/lib/workspace/application/appearance.dart

@@ -242,6 +242,12 @@ class AppearanceSettingsState with _$AppearanceSettingsState {
       shadow: theme.shadow,
     );
 
+    const Set<MaterialState> scrollbarInteractiveStates = <MaterialState>{
+      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<MaterialState> interactiveStates = <MaterialState>{
-            MaterialState.pressed,
-            MaterialState.hovered,
-            MaterialState.dragged,
-          };
-          if (states.any(interactiveStates.contains)) {
-            return 5.0;
+          if (states.any(scrollbarInteractiveStates.contains)) {
+            return 4;
           }
           return 3.0;
         }),

+ 4 - 4
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<AppearanceSettingsCubit>().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<AppearanceSettingsCubit>().setThemeMode(themeMode);

+ 83 - 65
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<AppearanceSettingsCubit, AppearanceSettingsState>(
+        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);
+class LanguageSelector extends StatelessWidget {
+  final Locale currentLocale;
+  const LanguageSelector({
+    super.key,
+    required this.currentLocale,
+  });
 
   @override
-  State<LanguageSelectorDropdown> createState() =>
-      _LanguageSelectorDropdownState();
-}
+  Widget build(BuildContext context) {
+    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;
 
-class _LanguageSelectorDropdownState extends State<LanguageSelectorDropdown> {
-  Color currHoverColor = Colors.white.withOpacity(0.0);
-  void hoverExitLanguage() {
-    setState(() {
-      currHoverColor = Colors.white.withOpacity(0.0);
-    });
+        return LanguageItemsListView(
+          allLocales: allLocales,
+          currentLocale: currentLocale,
+        );
+      },
+    );
   }
+}
+
+class LanguageItemsListView extends StatelessWidget {
+  const LanguageItemsListView({
+    super.key,
+    required this.allLocales,
+    required this.currentLocale,
+  });
+
+  final List<Locale> allLocales;
+  final Locale currentLocale;
 
-  void hoverEnterLanguage() {
-    setState(() {
-      currHoverColor = Theme.of(context).colorScheme.secondaryContainer;
-    });
+  @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 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<Locale>(
-              value: context.locale,
-              dropdownColor: Theme.of(context).cardColor,
-              onChanged: (locale) {
-                context
-                    .read<AppearanceSettingsCubit>()
-                    .setLocale(context, locale!);
-              },
-              autofocus: true,
-              borderRadius: BorderRadius.circular(8),
-              items:
-                  EasyLocalization.of(context)!.supportedLocales.map((locale) {
-                return DropdownMenuItem<Locale>(
-                  value: locale,
-                  child: Padding(
-                    padding: const EdgeInsets.all(12.0),
-                    child: FlowyText.medium(
-                      languageFromLocale(locale),
-                      color: Theme.of(context).colorScheme.tertiary,
-                    ),
-                  ),
-                );
-              }).toList(),
-            ),
-          ),
+    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<AppearanceSettingsCubit>().setLocale(context, locale);
+          }
+        },
       ),
     );
   }