|
@@ -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);
|
|
|
+ }
|
|
|
+ },
|
|
|
),
|
|
|
);
|
|
|
}
|