From 177ed8d51a21a16bb1753aa2e318817d5dbdafd6 Mon Sep 17 00:00:00 2001 From: Lays Rodrigues Date: Wed, 2 Feb 2022 17:22:29 -0300 Subject: [PATCH 01/14] fix appflowy version in dockerfile Signed-off-by: Lays Rodrigues --- frontend/scripts/docker-buildfiles/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/scripts/docker-buildfiles/Dockerfile b/frontend/scripts/docker-buildfiles/Dockerfile index 86dc80e77b..620fbb046d 100644 --- a/frontend/scripts/docker-buildfiles/Dockerfile +++ b/frontend/scripts/docker-buildfiles/Dockerfile @@ -35,4 +35,4 @@ cargo install --force cargo-make && \ cargo install --force duckscript_cli && \ cargo make flowy_dev && \ cargo make -p production-linux-x86 appflowy-linux -CMD ["appflowy/frontend/app_flowy/product/0.0.2/linux/Release/AppFlowy/app_flowy"] +CMD ["appflowy/frontend/app_flowy/product/0.0.3/linux/Release/AppFlowy/app_flowy"] From ea0179536d7d1de8499ba09060c011923f3b9a87 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 2 Feb 2022 22:21:31 +0800 Subject: [PATCH 02/14] fix: show_menu icon on dark mode --- .../lib/workspace/presentation/home/navigation.dart | 4 +++- .../flowy_infra_ui/lib/style_widget/icon_button.dart | 12 ++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart b/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart index 069c0ee6e7..80e5e8c2de 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart @@ -1,6 +1,7 @@ import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/notifier.dart'; +import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; @@ -81,6 +82,7 @@ class FlowyNavigation extends StatelessWidget { } Widget _renderCollapse(BuildContext context, PublishNotifier collapsedNotifier) { + final theme = context.watch(); return ChangeNotifierProvider.value( value: collapsedNotifier, child: Consumer( @@ -94,7 +96,7 @@ class FlowyNavigation extends StatelessWidget { notifier.value = false; }, iconPadding: const EdgeInsets.fromLTRB(2, 2, 2, 2), - icon: svg("home/hide_menu"), + icon: svg("home/hide_menu", color: theme.iconColor), ), ); } else { diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/icon_button.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/icon_button.dart index 0b960a7abb..4087ccf25d 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/icon_button.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/icon_button.dart @@ -1,7 +1,9 @@ import 'dart:math'; import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class FlowyIconButton extends StatelessWidget { final double width; @@ -30,16 +32,6 @@ class FlowyIconButton extends StatelessWidget { @override Widget build(BuildContext context) { Widget child = icon; - - // if (onPressed == null) { - // child = ColorFiltered( - // colorFilter: ColorFilter.mode( - // Colors.grey, - // BlendMode.saturation, - // ), - // child: child, - // ); - // } final size = Size(width, height ?? width); assert(size.width > iconPadding.horizontal); From ef1d10b377fc1e7a0e66598420209608f7c28f76 Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 4 Feb 2022 15:48:12 +0800 Subject: [PATCH 03/14] ci: add commit lint --- .github/workflows/commitlint.yml | 12 ++++++++++++ .husky/commit-msg | 4 ++++ commitlint.config.js | 1 + 3 files changed, 17 insertions(+) create mode 100644 .github/workflows/commitlint.yml create mode 100755 .husky/commit-msg create mode 100644 commitlint.config.js diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml new file mode 100644 index 0000000000..6151362d49 --- /dev/null +++ b/.github/workflows/commitlint.yml @@ -0,0 +1,12 @@ +name: Lint Commit Messages +on: [pull_request, push] + +jobs: + commitlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - uses: wagoid/commitlint-github-action@v4 + diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100755 index 0000000000..7fed48507b --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx --no -- commitlint --edit diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000000..28fe5c5bf9 --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1 @@ +module.exports = {extends: ['@commitlint/config-conventional']} From 5519dcd525c124900a90a03f7e789784e9960561 Mon Sep 17 00:00:00 2001 From: MikeWallaceDev Date: Fri, 4 Feb 2022 15:45:06 -0500 Subject: [PATCH 04/14] refactor: language settings to remove applanguage enum Fixes: #290 app now uses Locale directly list of languages is now generated from EasyLocalization --- .../lib/startup/tasks/application_widget.dart | 8 +- .../lib/workspace/application/appearance.dart | 24 +- .../widgets/settings_language_view.dart | 16 +- .../stack_page/doc/doc_stack_page.dart | 4 +- .../widgets/menu/widget/menu_trash.dart | 5 +- .../packages/flowy_infra/lib/language.dart | 71 ++-- .../user_setting.pb.dart | 79 ++++- .../user_setting.pbjson.dart | 15 +- .../flowy-user/src/handlers/user_handler.rs | 7 +- .../src/derive_cache/derive_cache.rs | 83 ++--- .../src/entities/user_setting.rs | 23 +- .../src/protobuf/model/user_setting.rs | 310 +++++++++++++++--- .../src/protobuf/proto/user_setting.proto | 6 +- 13 files changed, 465 insertions(+), 186 deletions(-) diff --git a/frontend/app_flowy/lib/startup/tasks/application_widget.dart b/frontend/app_flowy/lib/startup/tasks/application_widget.dart index eed93eee3c..ceee515c60 100644 --- a/frontend/app_flowy/lib/startup/tasks/application_widget.dart +++ b/frontend/app_flowy/lib/startup/tasks/application_widget.dart @@ -63,14 +63,14 @@ class ApplicationWidget extends StatelessWidget { AppTheme theme = context.select( (value) => value.theme, ); - AppLanguage language = context.select( - (value) => value.language, + Locale locale = context.select( + (value) => value.locale, ); return MultiProvider( providers: [ Provider.value(value: theme), - Provider.value(value: language), + Provider.value(value: locale), ], builder: (context, _) { return MaterialApp( @@ -79,7 +79,7 @@ class ApplicationWidget extends StatelessWidget { theme: theme.themeData, localizationsDelegates: context.localizationDelegates, supportedLocales: context.supportedLocales, - locale: localeFromLanguageName(language), + locale: locale, navigatorKey: AppGlobals.rootNavKey, home: child, ); diff --git a/frontend/app_flowy/lib/workspace/application/appearance.dart b/frontend/app_flowy/lib/workspace/application/appearance.dart index 8f7a66563a..c59e9ac390 100644 --- a/frontend/app_flowy/lib/workspace/application/appearance.dart +++ b/frontend/app_flowy/lib/workspace/application/appearance.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/user/infrastructure/repos/user_setting_repo.dart'; import 'package:equatable/equatable.dart'; import 'package:flowy_infra/theme.dart'; -import 'package:flowy_infra/language.dart'; +import 'package:flowy_infra/language.dart' as Language; import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_setting.pb.dart'; import 'package:flutter/material.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -10,15 +10,15 @@ import 'package:async/async.dart'; class AppearanceSettingModel extends ChangeNotifier with EquatableMixin { AppearanceSettings setting; AppTheme _theme; - AppLanguage _language; + Locale _locale; CancelableOperation? _saveOperation; AppearanceSettingModel(this.setting) : _theme = AppTheme.fromName(name: setting.theme), - _language = languageFromString(setting.language); + _locale = Locale(setting.locale.languageCode, setting.locale.countryCode); AppTheme get theme => _theme; - AppLanguage get language => _language; + Locale get locale => _locale; Future save() async { _saveOperation?.cancel; @@ -45,13 +45,12 @@ class AppearanceSettingModel extends ChangeNotifier with EquatableMixin { } } - void setLanguage(BuildContext context, AppLanguage language) { - String languageString = stringFromLanguage(language); - - if (setting.language != languageString) { - context.setLocale(localeFromLanguageName(language)); - _language = language; - setting.language = languageString; + void setLocale(BuildContext context, Locale newLocale) { + if (_locale != newLocale) { + context.setLocale(newLocale); + _locale = newLocale; + setting.locale.languageCode = _locale.languageCode; + setting.locale.countryCode = _locale.countryCode ?? ""; notifyListeners(); save(); } @@ -62,8 +61,7 @@ class AppearanceSettingModel extends ChangeNotifier with EquatableMixin { setting.resetAsDefault = false; save(); - final language = languageFromLocale(context.deviceLocale); - setLanguage(context, language); + setLocale(context, context.deviceLocale); } } } diff --git a/frontend/app_flowy/lib/workspace/presentation/settings/widgets/settings_language_view.dart b/frontend/app_flowy/lib/workspace/presentation/settings/widgets/settings_language_view.dart index 34beba38f5..5617750a77 100644 --- a/frontend/app_flowy/lib/workspace/presentation/settings/widgets/settings_language_view.dart +++ b/frontend/app_flowy/lib/workspace/presentation/settings/widgets/settings_language_view.dart @@ -1,5 +1,5 @@ import 'package:app_flowy/workspace/application/appearance.dart'; -import 'package:flutter/foundation.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flowy_infra/language.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -30,18 +30,18 @@ class LanguageSelectorDropdown extends StatefulWidget { class _LanguageSelectorDropdownState extends State { @override Widget build(BuildContext context) { - return DropdownButton( - value: context.read().language, + return DropdownButton( + value: context.read().locale, onChanged: (val) { setState(() { - context.read().setLanguage(context, val!); + context.read().setLocale(context, val!); }); }, autofocus: true, - items: AppLanguage.values.map((language) { - return DropdownMenuItem( - value: language, - child: Text(describeEnum(language)), + items: EasyLocalization.of(context)!.supportedLocales.map((locale) { + return DropdownMenuItem( + value: locale, + child: Text(languageFromLocale(locale)), ); }).toList(), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart index 18fe04257b..b257c8000d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart @@ -175,8 +175,8 @@ class DocumentShareButton extends StatelessWidget { builder: (context, state) { return ChangeNotifierProvider.value( value: Provider.of(context, listen: true), - child: Selector( - selector: (ctx, notifier) => notifier.language, + child: Selector( + selector: (ctx, notifier) => notifier.locale, builder: (ctx, _, child) => ConstrainedBox( constraints: const BoxConstraints.expand( height: 30, diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart index 52c82b97d7..85178de0b6 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart @@ -5,7 +5,6 @@ import 'package:app_flowy/workspace/presentation/stack_page/trash/trash_page.dar import 'package:app_flowy/workspace/presentation/widgets/menu/menu.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; -import 'package:flowy_infra/language.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; @@ -43,8 +42,8 @@ class MenuTrash extends StatelessWidget { const HSpace(6), ChangeNotifierProvider.value( value: Provider.of(context, listen: true), - child: Selector( - selector: (ctx, notifier) => notifier.language, + child: Selector( + selector: (ctx, notifier) => notifier.locale, builder: (ctx, _, child) => FlowyText.medium(LocaleKeys.trash_text.tr(), fontSize: 12), ), ), diff --git a/frontend/app_flowy/packages/flowy_infra/lib/language.dart b/frontend/app_flowy/packages/flowy_infra/lib/language.dart index 0109bf6e9a..091151bc57 100644 --- a/frontend/app_flowy/packages/flowy_infra/lib/language.dart +++ b/frontend/app_flowy/packages/flowy_infra/lib/language.dart @@ -1,60 +1,27 @@ import 'package:flutter/material.dart'; -enum AppLanguage { - english, - chinese, - italian, - french, -} - -String stringFromLanguage(AppLanguage language) { - switch (language) { - case AppLanguage.english: - return "en"; - case AppLanguage.chinese: - return "ch"; - case AppLanguage.italian: - return "it"; - case AppLanguage.french: - return "fr"; - } -} - -AppLanguage languageFromString(String name) { - AppLanguage language = AppLanguage.english; - if (name == "ch") { - language = AppLanguage.chinese; - } else if (name == "it") { - language = AppLanguage.italian; - } else if (name == "fr") { - language = AppLanguage.french; - } - - return language; -} - -Locale localeFromLanguageName(AppLanguage language) { - switch (language) { - case AppLanguage.english: - return const Locale('en'); - case AppLanguage.chinese: - return const Locale('zh', 'CN'); - case AppLanguage.italian: - return const Locale('it', 'IT'); - case AppLanguage.french: - return const Locale('fr', 'CA'); - } -} - -AppLanguage languageFromLocale(Locale locale) { +String languageFromLocale(Locale locale) { switch (locale.languageCode) { + // Most often used languages + case "en": + return "English"; case "zh": - return AppLanguage.chinese; - case "it": - return AppLanguage.italian; + return "简体中文"; + + // Then in alphabetical order + case "de": + return "Deutsch"; + case "es": + return "Español"; case "fr": - return AppLanguage.french; + return "Français"; + case "it": + return "Italiano"; + case "ru": + return "русский"; + + // If not found then the language code will be displayed default: - return AppLanguage.english; + return locale.languageCode; } } diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user-data-model/user_setting.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user-data-model/user_setting.pb.dart index 665671d849..797412e68b 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user-data-model/user_setting.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user-data-model/user_setting.pb.dart @@ -75,7 +75,7 @@ class UserPreferences extends $pb.GeneratedMessage { class AppearanceSettings extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'AppearanceSettings', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'theme') - ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'language') + ..aOM(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'locale', subBuilder: LocaleSettings.create) ..aOB(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'resetAsDefault') ..hasRequiredFields = false ; @@ -83,15 +83,15 @@ class AppearanceSettings extends $pb.GeneratedMessage { AppearanceSettings._() : super(); factory AppearanceSettings({ $core.String? theme, - $core.String? language, + LocaleSettings? locale, $core.bool? resetAsDefault, }) { final _result = create(); if (theme != null) { _result.theme = theme; } - if (language != null) { - _result.language = language; + if (locale != null) { + _result.locale = locale; } if (resetAsDefault != null) { _result.resetAsDefault = resetAsDefault; @@ -129,13 +129,15 @@ class AppearanceSettings extends $pb.GeneratedMessage { void clearTheme() => clearField(1); @$pb.TagNumber(2) - $core.String get language => $_getSZ(1); + LocaleSettings get locale => $_getN(1); @$pb.TagNumber(2) - set language($core.String v) { $_setString(1, v); } + set locale(LocaleSettings v) { setField(2, v); } @$pb.TagNumber(2) - $core.bool hasLanguage() => $_has(1); + $core.bool hasLocale() => $_has(1); @$pb.TagNumber(2) - void clearLanguage() => clearField(2); + void clearLocale() => clearField(2); + @$pb.TagNumber(2) + LocaleSettings ensureLocale() => $_ensure(1); @$pb.TagNumber(3) $core.bool get resetAsDefault => $_getBF(2); @@ -147,3 +149,64 @@ class AppearanceSettings extends $pb.GeneratedMessage { void clearResetAsDefault() => clearField(3); } +class LocaleSettings extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'LocaleSettings', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'languageCode') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'countryCode') + ..hasRequiredFields = false + ; + + LocaleSettings._() : super(); + factory LocaleSettings({ + $core.String? languageCode, + $core.String? countryCode, + }) { + final _result = create(); + if (languageCode != null) { + _result.languageCode = languageCode; + } + if (countryCode != null) { + _result.countryCode = countryCode; + } + return _result; + } + factory LocaleSettings.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory LocaleSettings.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + LocaleSettings clone() => LocaleSettings()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + LocaleSettings copyWith(void Function(LocaleSettings) updates) => super.copyWith((message) => updates(message as LocaleSettings)) as LocaleSettings; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static LocaleSettings create() => LocaleSettings._(); + LocaleSettings createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static LocaleSettings getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static LocaleSettings? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get languageCode => $_getSZ(0); + @$pb.TagNumber(1) + set languageCode($core.String v) { $_setString(0, v); } + @$pb.TagNumber(1) + $core.bool hasLanguageCode() => $_has(0); + @$pb.TagNumber(1) + void clearLanguageCode() => clearField(1); + + @$pb.TagNumber(2) + $core.String get countryCode => $_getSZ(1); + @$pb.TagNumber(2) + set countryCode($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasCountryCode() => $_has(1); + @$pb.TagNumber(2) + void clearCountryCode() => clearField(2); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user-data-model/user_setting.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user-data-model/user_setting.pbjson.dart index 8e401e3665..1a315f62dd 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user-data-model/user_setting.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user-data-model/user_setting.pbjson.dart @@ -24,10 +24,21 @@ const AppearanceSettings$json = const { '1': 'AppearanceSettings', '2': const [ const {'1': 'theme', '3': 1, '4': 1, '5': 9, '10': 'theme'}, - const {'1': 'language', '3': 2, '4': 1, '5': 9, '10': 'language'}, + const {'1': 'locale', '3': 2, '4': 1, '5': 11, '6': '.LocaleSettings', '10': 'locale'}, const {'1': 'reset_as_default', '3': 3, '4': 1, '5': 8, '10': 'resetAsDefault'}, ], }; /// Descriptor for `AppearanceSettings`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List appearanceSettingsDescriptor = $convert.base64Decode('ChJBcHBlYXJhbmNlU2V0dGluZ3MSFAoFdGhlbWUYASABKAlSBXRoZW1lEhoKCGxhbmd1YWdlGAIgASgJUghsYW5ndWFnZRIoChByZXNldF9hc19kZWZhdWx0GAMgASgIUg5yZXNldEFzRGVmYXVsdA=='); +final $typed_data.Uint8List appearanceSettingsDescriptor = $convert.base64Decode('ChJBcHBlYXJhbmNlU2V0dGluZ3MSFAoFdGhlbWUYASABKAlSBXRoZW1lEicKBmxvY2FsZRgCIAEoCzIPLkxvY2FsZVNldHRpbmdzUgZsb2NhbGUSKAoQcmVzZXRfYXNfZGVmYXVsdBgDIAEoCFIOcmVzZXRBc0RlZmF1bHQ='); +@$core.Deprecated('Use localeSettingsDescriptor instead') +const LocaleSettings$json = const { + '1': 'LocaleSettings', + '2': const [ + const {'1': 'language_code', '3': 1, '4': 1, '5': 9, '10': 'languageCode'}, + const {'1': 'country_code', '3': 2, '4': 1, '5': 9, '10': 'countryCode'}, + ], +}; + +/// Descriptor for `LocaleSettings`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List localeSettingsDescriptor = $convert.base64Decode('Cg5Mb2NhbGVTZXR0aW5ncxIjCg1sYW5ndWFnZV9jb2RlGAEgASgJUgxsYW5ndWFnZUNvZGUSIQoMY291bnRyeV9jb2RlGAIgASgJUgtjb3VudHJ5Q29kZQ=='); diff --git a/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs b/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs index 933d5b1fd5..1af32ab72a 100644 --- a/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs +++ b/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs @@ -1,8 +1,7 @@ use crate::{errors::FlowyError, services::UserSession}; use flowy_database::kv::KV; use flowy_user_data_model::entities::{ - AppearanceSettings, UpdateUserParams, UpdateUserRequest, UserProfile, APPEARANCE_DEFAULT_LANGUAGE, - APPEARANCE_DEFAULT_THEME, + AppearanceSettings, UpdateUserParams, UpdateUserRequest, UserProfile, APPEARANCE_DEFAULT_THEME, }; use lib_dispatch::prelude::*; use std::{convert::TryInto, sync::Arc}; @@ -50,10 +49,6 @@ pub async fn set_appearance_setting(data: Data) -> Result<() setting.theme = APPEARANCE_DEFAULT_THEME.to_string(); } - if setting.language.is_empty() { - setting.theme = APPEARANCE_DEFAULT_LANGUAGE.to_string(); - } - let s = serde_json::to_string(&setting)?; KV::set_str(APPEARANCE_SETTING_CACHE_KEY, s); Ok(()) diff --git a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs index 971070f351..7c99aaa1db 100644 --- a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs +++ b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs @@ -18,48 +18,22 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { "String" => TypeCategory::Str, "FFIRequest" | "FFIResponse" - | "FlowyError" | "SubscribeObject" + | "FlowyError" | "NetworkState" + | "UserToken" + | "UserProfile" + | "UpdateUserRequest" + | "UpdateUserParams" | "SignInRequest" | "SignInParams" | "SignInResponse" | "SignUpRequest" | "SignUpParams" | "SignUpResponse" - | "UserToken" - | "UserProfile" - | "UpdateUserRequest" - | "UpdateUserParams" | "UserPreferences" | "AppearanceSettings" - | "ClientRevisionWSData" - | "ServerRevisionWSData" - | "NewDocumentUser" - | "FolderInfo" - | "Revision" - | "RepeatedRevision" - | "RevId" - | "RevisionRange" - | "CreateDocParams" - | "DocumentInfo" - | "ResetDocumentParams" - | "DocumentDelta" - | "NewDocUser" - | "DocumentId" - | "WSError" - | "WebSocketRawMessage" - | "Workspace" - | "RepeatedWorkspace" - | "CreateWorkspaceRequest" - | "CreateWorkspaceParams" - | "QueryWorkspaceRequest" - | "WorkspaceId" - | "CurrentWorkspaceSetting" - | "UpdateWorkspaceRequest" - | "UpdateWorkspaceParams" - | "ExportRequest" - | "ExportData" + | "LocaleSettings" | "App" | "RepeatedApp" | "CreateAppRequest" @@ -69,10 +43,8 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "AppId" | "UpdateAppRequest" | "UpdateAppParams" - | "Trash" - | "RepeatedTrash" - | "RepeatedTrashId" - | "TrashId" + | "ExportRequest" + | "ExportData" | "View" | "RepeatedView" | "CreateViewRequest" @@ -82,23 +54,52 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "RepeatedViewId" | "UpdateViewRequest" | "UpdateViewParams" + | "Trash" + | "RepeatedTrash" + | "RepeatedTrashId" + | "TrashId" + | "Workspace" + | "RepeatedWorkspace" + | "CreateWorkspaceRequest" + | "CreateWorkspaceParams" + | "QueryWorkspaceRequest" + | "WorkspaceId" + | "CurrentWorkspaceSetting" + | "UpdateWorkspaceRequest" + | "UpdateWorkspaceParams" + | "ClientRevisionWSData" + | "ServerRevisionWSData" + | "NewDocumentUser" + | "CreateDocParams" + | "DocumentInfo" + | "ResetDocumentParams" + | "DocumentDelta" + | "NewDocUser" + | "DocumentId" + | "Revision" + | "RepeatedRevision" + | "RevId" + | "RevisionRange" + | "FolderInfo" + | "WSError" + | "WebSocketRawMessage" => TypeCategory::Protobuf, "FFIStatusCode" | "FolderEvent" | "FolderNotification" - | "NetworkEvent" - | "NetworkType" | "UserEvent" | "UserNotification" + | "NetworkEvent" + | "NetworkType" + | "ExportType" + | "ViewType" + | "TrashType" | "ClientRevisionWSDataType" | "ServerRevisionWSDataType" | "RevisionState" | "RevType" | "ErrorCode" | "WSChannel" - | "ExportType" - | "TrashType" - | "ViewType" => TypeCategory::Enum, "Option" => TypeCategory::Opt, diff --git a/shared-lib/flowy-user-data-model/src/entities/user_setting.rs b/shared-lib/flowy-user-data-model/src/entities/user_setting.rs index 8502361178..f7ad2ae05b 100644 --- a/shared-lib/flowy-user-data-model/src/entities/user_setting.rs +++ b/shared-lib/flowy-user-data-model/src/entities/user_setting.rs @@ -16,26 +16,43 @@ pub struct AppearanceSettings { pub theme: String, #[pb(index = 2)] - pub language: String, + pub locale: LocaleSettings, #[pb(index = 3)] #[serde(default = "reset_default_value")] pub reset_as_default: bool, } +#[derive(ProtoBuf, Serialize, Deserialize, Debug, Clone)] +pub struct LocaleSettings { + #[pb(index = 1)] + pub language_code: String, + + #[pb(index = 2)] + pub country_code: String, +} + +impl std::default::Default for LocaleSettings { + fn default() -> Self { + Self { + language_code: "en".to_owned(), + country_code: "".to_owned(), + } + } +} + fn reset_default_value() -> bool { APPEARANCE_RESET_AS_DEFAULT } pub const APPEARANCE_DEFAULT_THEME: &str = "light"; -pub const APPEARANCE_DEFAULT_LANGUAGE: &str = "en"; pub const APPEARANCE_RESET_AS_DEFAULT: bool = true; impl std::default::Default for AppearanceSettings { fn default() -> Self { AppearanceSettings { theme: APPEARANCE_DEFAULT_THEME.to_owned(), - language: APPEARANCE_DEFAULT_LANGUAGE.to_owned(), + locale: LocaleSettings::default(), reset_as_default: APPEARANCE_RESET_AS_DEFAULT, } } diff --git a/shared-lib/flowy-user-data-model/src/protobuf/model/user_setting.rs b/shared-lib/flowy-user-data-model/src/protobuf/model/user_setting.rs index c3c9b86c4d..400fa0686f 100644 --- a/shared-lib/flowy-user-data-model/src/protobuf/model/user_setting.rs +++ b/shared-lib/flowy-user-data-model/src/protobuf/model/user_setting.rs @@ -243,7 +243,7 @@ impl ::protobuf::reflect::ProtobufValue for UserPreferences { pub struct AppearanceSettings { // message fields pub theme: ::std::string::String, - pub language: ::std::string::String, + pub locale: ::protobuf::SingularPtrField, pub reset_as_default: bool, // special fields pub unknown_fields: ::protobuf::UnknownFields, @@ -287,30 +287,37 @@ impl AppearanceSettings { ::std::mem::replace(&mut self.theme, ::std::string::String::new()) } - // string language = 2; + // .LocaleSettings locale = 2; - pub fn get_language(&self) -> &str { - &self.language + pub fn get_locale(&self) -> &LocaleSettings { + self.locale.as_ref().unwrap_or_else(|| ::default_instance()) } - pub fn clear_language(&mut self) { - self.language.clear(); + pub fn clear_locale(&mut self) { + self.locale.clear(); + } + + pub fn has_locale(&self) -> bool { + self.locale.is_some() } // Param is passed by value, moved - pub fn set_language(&mut self, v: ::std::string::String) { - self.language = v; + pub fn set_locale(&mut self, v: LocaleSettings) { + self.locale = ::protobuf::SingularPtrField::some(v); } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_language(&mut self) -> &mut ::std::string::String { - &mut self.language + pub fn mut_locale(&mut self) -> &mut LocaleSettings { + if self.locale.is_none() { + self.locale.set_default(); + } + self.locale.as_mut().unwrap() } // Take field - pub fn take_language(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.language, ::std::string::String::new()) + pub fn take_locale(&mut self) -> LocaleSettings { + self.locale.take().unwrap_or_else(|| LocaleSettings::new()) } // bool reset_as_default = 3; @@ -331,6 +338,11 @@ impl AppearanceSettings { impl ::protobuf::Message for AppearanceSettings { fn is_initialized(&self) -> bool { + for v in &self.locale { + if !v.is_initialized() { + return false; + } + }; true } @@ -342,7 +354,7 @@ impl ::protobuf::Message for AppearanceSettings { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.theme)?; }, 2 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.language)?; + ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.locale)?; }, 3 => { if wire_type != ::protobuf::wire_format::WireTypeVarint { @@ -366,8 +378,9 @@ impl ::protobuf::Message for AppearanceSettings { if !self.theme.is_empty() { my_size += ::protobuf::rt::string_size(1, &self.theme); } - if !self.language.is_empty() { - my_size += ::protobuf::rt::string_size(2, &self.language); + if let Some(ref v) = self.locale.as_ref() { + let len = v.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; } if self.reset_as_default != false { my_size += 2; @@ -381,8 +394,10 @@ impl ::protobuf::Message for AppearanceSettings { if !self.theme.is_empty() { os.write_string(1, &self.theme)?; } - if !self.language.is_empty() { - os.write_string(2, &self.language)?; + if let Some(ref v) = self.locale.as_ref() { + os.write_tag(2, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; } if self.reset_as_default != false { os.write_bool(3, self.reset_as_default)?; @@ -430,10 +445,10 @@ impl ::protobuf::Message for AppearanceSettings { |m: &AppearanceSettings| { &m.theme }, |m: &mut AppearanceSettings| { &mut m.theme }, )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "language", - |m: &AppearanceSettings| { &m.language }, - |m: &mut AppearanceSettings| { &mut m.language }, + fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "locale", + |m: &AppearanceSettings| { &m.locale }, + |m: &mut AppearanceSettings| { &mut m.locale }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>( "reset_as_default", @@ -457,7 +472,7 @@ impl ::protobuf::Message for AppearanceSettings { impl ::protobuf::Clear for AppearanceSettings { fn clear(&mut self) { self.theme.clear(); - self.language.clear(); + self.locale.clear(); self.reset_as_default = false; self.unknown_fields.clear(); } @@ -475,30 +490,239 @@ impl ::protobuf::reflect::ProtobufValue for AppearanceSettings { } } +#[derive(PartialEq,Clone,Default)] +pub struct LocaleSettings { + // message fields + pub language_code: ::std::string::String, + pub country_code: ::std::string::String, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a LocaleSettings { + fn default() -> &'a LocaleSettings { + ::default_instance() + } +} + +impl LocaleSettings { + pub fn new() -> LocaleSettings { + ::std::default::Default::default() + } + + // string language_code = 1; + + + pub fn get_language_code(&self) -> &str { + &self.language_code + } + pub fn clear_language_code(&mut self) { + self.language_code.clear(); + } + + // Param is passed by value, moved + pub fn set_language_code(&mut self, v: ::std::string::String) { + self.language_code = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_language_code(&mut self) -> &mut ::std::string::String { + &mut self.language_code + } + + // Take field + pub fn take_language_code(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.language_code, ::std::string::String::new()) + } + + // string country_code = 2; + + + pub fn get_country_code(&self) -> &str { + &self.country_code + } + pub fn clear_country_code(&mut self) { + self.country_code.clear(); + } + + // Param is passed by value, moved + pub fn set_country_code(&mut self, v: ::std::string::String) { + self.country_code = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_country_code(&mut self) -> &mut ::std::string::String { + &mut self.country_code + } + + // Take field + pub fn take_country_code(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.country_code, ::std::string::String::new()) + } +} + +impl ::protobuf::Message for LocaleSettings { + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.language_code)?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.country_code)?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + if !self.language_code.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.language_code); + } + if !self.country_code.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.country_code); + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { + if !self.language_code.is_empty() { + os.write_string(1, &self.language_code)?; + } + if !self.country_code.is_empty() { + os.write_string(2, &self.country_code)?; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &dyn (::std::any::Any) { + self as &dyn (::std::any::Any) + } + fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { + self as &mut dyn (::std::any::Any) + } + fn into_any(self: ::std::boxed::Box) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> LocaleSettings { + LocaleSettings::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "language_code", + |m: &LocaleSettings| { &m.language_code }, + |m: &mut LocaleSettings| { &mut m.language_code }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "country_code", + |m: &LocaleSettings| { &m.country_code }, + |m: &mut LocaleSettings| { &mut m.country_code }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "LocaleSettings", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static LocaleSettings { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(LocaleSettings::new) + } +} + +impl ::protobuf::Clear for LocaleSettings { + fn clear(&mut self) { + self.language_code.clear(); + self.country_code.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for LocaleSettings { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for LocaleSettings { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + static file_descriptor_proto_data: &'static [u8] = b"\ \n\x12user_setting.proto\"n\n\x0fUserPreferences\x12\x17\n\x07user_id\ \x18\x01\x20\x01(\tR\x06userId\x12B\n\x12appearance_setting\x18\x02\x20\ - \x01(\x0b2\x13.AppearanceSettingsR\x11appearanceSetting\"p\n\x12Appearan\ - ceSettings\x12\x14\n\x05theme\x18\x01\x20\x01(\tR\x05theme\x12\x1a\n\x08\ - language\x18\x02\x20\x01(\tR\x08language\x12(\n\x10reset_as_default\x18\ - \x03\x20\x01(\x08R\x0eresetAsDefaultJ\xd5\x02\n\x06\x12\x04\0\0\n\x01\n\ - \x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x05\x01\n\n\ - \n\x03\x04\0\x01\x12\x03\x02\x08\x17\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\ - \x04\x17\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\ - \x02\0\x01\x12\x03\x03\x0b\x12\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\ - \x15\x16\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04.\n\x0c\n\x05\x04\0\ - \x02\x01\x06\x12\x03\x04\x04\x16\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\ - \x04\x17)\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04,-\n\n\n\x02\x04\x01\ - \x12\x04\x06\0\n\x01\n\n\n\x03\x04\x01\x01\x12\x03\x06\x08\x1a\n\x0b\n\ - \x04\x04\x01\x02\0\x12\x03\x07\x04\x15\n\x0c\n\x05\x04\x01\x02\0\x05\x12\ - \x03\x07\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x07\x0b\x10\n\x0c\n\ - \x05\x04\x01\x02\0\x03\x12\x03\x07\x13\x14\n\x0b\n\x04\x04\x01\x02\x01\ - \x12\x03\x08\x04\x18\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\x08\x04\n\n\ - \x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\x08\x0b\x13\n\x0c\n\x05\x04\x01\ - \x02\x01\x03\x12\x03\x08\x16\x17\n\x0b\n\x04\x04\x01\x02\x02\x12\x03\t\ - \x04\x1e\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\t\x04\x08\n\x0c\n\x05\ - \x04\x01\x02\x02\x01\x12\x03\t\t\x19\n\x0c\n\x05\x04\x01\x02\x02\x03\x12\ - \x03\t\x1c\x1db\x06proto3\ + \x01(\x0b2\x13.AppearanceSettingsR\x11appearanceSetting\"}\n\x12Appearan\ + ceSettings\x12\x14\n\x05theme\x18\x01\x20\x01(\tR\x05theme\x12'\n\x06loc\ + ale\x18\x02\x20\x01(\x0b2\x0f.LocaleSettingsR\x06locale\x12(\n\x10reset_\ + as_default\x18\x03\x20\x01(\x08R\x0eresetAsDefault\"X\n\x0eLocaleSetting\ + s\x12#\n\rlanguage_code\x18\x01\x20\x01(\tR\x0clanguageCode\x12!\n\x0cco\ + untry_code\x18\x02\x20\x01(\tR\x0bcountryCodeJ\xdb\x03\n\x06\x12\x04\0\0\ + \x0e\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\ + \x05\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x17\n\x0b\n\x04\x04\0\x02\0\ + \x12\x03\x03\x04\x17\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\ + \n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\x12\n\x0c\n\x05\x04\0\x02\0\x03\ + \x12\x03\x03\x15\x16\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04.\n\x0c\n\ + \x05\x04\0\x02\x01\x06\x12\x03\x04\x04\x16\n\x0c\n\x05\x04\0\x02\x01\x01\ + \x12\x03\x04\x17)\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04,-\n\n\n\x02\ + \x04\x01\x12\x04\x06\0\n\x01\n\n\n\x03\x04\x01\x01\x12\x03\x06\x08\x1a\n\ + \x0b\n\x04\x04\x01\x02\0\x12\x03\x07\x04\x15\n\x0c\n\x05\x04\x01\x02\0\ + \x05\x12\x03\x07\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x07\x0b\x10\ + \n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\x07\x13\x14\n\x0b\n\x04\x04\x01\ + \x02\x01\x12\x03\x08\x04\x1e\n\x0c\n\x05\x04\x01\x02\x01\x06\x12\x03\x08\ + \x04\x12\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\x08\x13\x19\n\x0c\n\x05\ + \x04\x01\x02\x01\x03\x12\x03\x08\x1c\x1d\n\x0b\n\x04\x04\x01\x02\x02\x12\ + \x03\t\x04\x1e\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\t\x04\x08\n\x0c\n\ + \x05\x04\x01\x02\x02\x01\x12\x03\t\t\x19\n\x0c\n\x05\x04\x01\x02\x02\x03\ + \x12\x03\t\x1c\x1d\n\n\n\x02\x04\x02\x12\x04\x0b\0\x0e\x01\n\n\n\x03\x04\ + \x02\x01\x12\x03\x0b\x08\x16\n\x0b\n\x04\x04\x02\x02\0\x12\x03\x0c\x04\ + \x1d\n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\x0c\x04\n\n\x0c\n\x05\x04\x02\ + \x02\0\x01\x12\x03\x0c\x0b\x18\n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\x0c\ + \x1b\x1c\n\x0b\n\x04\x04\x02\x02\x01\x12\x03\r\x04\x1c\n\x0c\n\x05\x04\ + \x02\x02\x01\x05\x12\x03\r\x04\n\n\x0c\n\x05\x04\x02\x02\x01\x01\x12\x03\ + \r\x0b\x17\n\x0c\n\x05\x04\x02\x02\x01\x03\x12\x03\r\x1a\x1bb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-user-data-model/src/protobuf/proto/user_setting.proto b/shared-lib/flowy-user-data-model/src/protobuf/proto/user_setting.proto index 3165dafeb7..958ada4c42 100644 --- a/shared-lib/flowy-user-data-model/src/protobuf/proto/user_setting.proto +++ b/shared-lib/flowy-user-data-model/src/protobuf/proto/user_setting.proto @@ -6,6 +6,10 @@ message UserPreferences { } message AppearanceSettings { string theme = 1; - string language = 2; + LocaleSettings locale = 2; bool reset_as_default = 3; } +message LocaleSettings { + string language_code = 1; + string country_code = 2; +} From ec4d69e5b8120bedee7175db65f19891347ae556 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 5 Feb 2022 10:26:51 +0800 Subject: [PATCH 05/14] fix: collapse button display color in dark mode --- .../lib/workspace/presentation/home/navigation.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart b/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart index 80e5e8c2de..1b5ddacc90 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/navigation.dart @@ -53,6 +53,8 @@ class FlowyNavigation extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = context.watch(); + return ChangeNotifierProxyProvider( create: (_) { final notifier = Provider.of(context, listen: false); @@ -66,7 +68,7 @@ class FlowyNavigation extends StatelessWidget { child: Row(children: [ Selector>( selector: (context, notifier) => notifier.collapasedNotifier, - builder: (ctx, collapsedNotifier, child) => _renderCollapse(ctx, collapsedNotifier)), + builder: (ctx, collapsedNotifier, child) => _renderCollapse(ctx, collapsedNotifier, theme)), Selector>( selector: (context, notifier) => notifier.navigationItems, builder: (ctx, items, child) => Expanded( @@ -81,8 +83,7 @@ class FlowyNavigation extends StatelessWidget { ); } - Widget _renderCollapse(BuildContext context, PublishNotifier collapsedNotifier) { - final theme = context.watch(); + Widget _renderCollapse(BuildContext context, PublishNotifier collapsedNotifier, AppTheme theme) { return ChangeNotifierProvider.value( value: collapsedNotifier, child: Consumer( From a6f675c1d951316d2c7e9376b54f19cde5d151c0 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 5 Feb 2022 10:27:43 +0800 Subject: [PATCH 06/14] fix: locale data deserializere error --- shared-lib/flowy-user-data-model/src/entities/user_setting.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/shared-lib/flowy-user-data-model/src/entities/user_setting.rs b/shared-lib/flowy-user-data-model/src/entities/user_setting.rs index f7ad2ae05b..f4543b6b5c 100644 --- a/shared-lib/flowy-user-data-model/src/entities/user_setting.rs +++ b/shared-lib/flowy-user-data-model/src/entities/user_setting.rs @@ -16,6 +16,7 @@ pub struct AppearanceSettings { pub theme: String, #[pb(index = 2)] + #[serde(default)] pub locale: LocaleSettings, #[pb(index = 3)] From cb57d20bfbd1dcb496bd66c809d5ad8a280c87f9 Mon Sep 17 00:00:00 2001 From: Daniil Golubev Date: Sat, 5 Feb 2022 05:46:57 +0300 Subject: [PATCH 07/14] Added russian translations (#287) * Added russian translations * Register russian locale --- .../app_flowy/assets/translations/ru-RU.json | 146 ++++++++++++++++++ .../lib/startup/tasks/application_widget.dart | 2 +- 2 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 frontend/app_flowy/assets/translations/ru-RU.json diff --git a/frontend/app_flowy/assets/translations/ru-RU.json b/frontend/app_flowy/assets/translations/ru-RU.json new file mode 100644 index 0000000000..9fe2980639 --- /dev/null +++ b/frontend/app_flowy/assets/translations/ru-RU.json @@ -0,0 +1,146 @@ +{ + "appName": "AppFlowy", + "defaultUsername": "Я", + "welcomeText": "Добро пожаловать в @:appName", + "githubStarText": "Поставить звезду на GitHub", + "subscribeNewsletterText": "Подписаться на рассылку", + "letsGoButtonText": "Начнём", + "title": "Заголовок", + "signUp": { + "buttonText": "Зарегистрироваться", + "title": "Регистрация в @:appName", + "getStartedText": "Начать", + "emptyPasswordError": "Пароль не может быть пустым", + "repeatPasswordEmptyError": "Повтор пароля не может быть пустым", + "unmatchedPasswordError": "Пароли не совпадают", + "alreadyHaveAnAccount": "Уже есть аккаунт?", + "emailHint": "Электронная почта", + "passwordHint": "Пароль", + "repeatPasswordHint": "Повторите пароль" + }, + "signIn": { + "loginTitle": "Войти в @:appName", + "loginButtonText": "Войти", + "buttonText": "Авторизация", + "forgotPassword": "Забыли пароль?", + "emailHint": "Электронная почта", + "passwordHint": "Пароль", + "dontHaveAnAccount": "Нет аккаунта?", + "repeatPasswordEmptyError": "Повтор пароля не может быть пустым", + "unmatchedPasswordError": "Пароли не совпадают" + }, + "workspace": { + "create": "Создать рабочее пространство", + "hint": "рабочее пространство", + "notFoundError": "Нет такого рабочего пространства" + }, + "shareAction": { + "buttonText": "Поделиться", + "workInProgress": "В разработке", + "markdown": "Markdown", + "copyLink": "Скопировать ссылку" + }, + "disclosureAction": { + "rename": "Переименовать", + "delete": "Удалить", + "duplicate": "Дублировать" + }, + "blankPageTitle": "Пустая страница", + "newPageText": "Новая страница", + "trash": { + "text": "Корзина", + "restoreAll": "Восстановить всё", + "deleteAll": "Очистить", + "pageHeader": { + "fileName": "Имя", + "lastModified": "Последнее изменение", + "created": "Создан" + } + }, + "deletePagePrompt": { + "text": "Эта страница в Корзине", + "restore": "Восстановить страницу", + "deletePermanent": "Удалить навсегда" + }, + "dialogCreatePageNameHint": "Имя", + "questionBubble": { + "whatsNew": "Что нового?", + "help": "Помощь", + "debug": { + "name": "Отладочная информация", + "success": "Скопировано в буфер обмена!", + "fail": "Не получилось скопировать" + } + }, + "menuAppHeader": { + "addPageTooltip": "Быстро добавить новую страницу", + "defaultNewPageName": "Без заголовка", + "renameDialog": "Переименовать" + }, + "toolbar": { + "undo": "Отменить", + "redo": "Повторить", + "bold": "Жирный", + "italic": "Курсив", + "underline": "Подчёркнутый", + "strike": "Зачёркнутый", + "numList": "Нумерованный список", + "bulletList": "Маркированный список", + "checkList": "Список To-Do", + "inlineCode": "Код", + "quote": "Цитата", + "header": "Заголовок", + "highlight": "Выделение" + }, + "tooltip": { + "lightMode": "Переключиться в светлую тему", + "darkMode": "Переключиться в тёмную тему" + }, + "contactsPage": { + "title": "Контакты", + "whatsHappening": "Что происходит на этой неделе?", + "addContact": "Новый контакт", + "editContact": "Редактировать" + }, + "button": { + "OK": "OK", + "Cancel": "Отмена", + "signIn": "Войти", + "signOut": "Выйти", + "complete": "Завершить", + "save": "Сохранить" + }, + "label": { + "welcome": "Добро пожаловать!", + "firstName": "Имя", + "middleName": "Отчество", + "lastName": "Фамилия", + "stepX": "Этап {X}" + }, + "oAuth": { + "err": { + "failedTitle": "Ошибка подключения к аккаунту.", + "failedMsg": "Убедитесь, что вы завершили вход в своём браузере." + }, + "google": { + "title": "Вход через Google", + "instruction1": "Чтобы импортировать ваши Google Контакты, вам нужно будет авторизовать приложение через браузер.", + "instruction2": "Скопируйте этот код в буфер обмена (нажав кнопку или выделив текст):", + "instruction3": "Пройдите по ссылке и введите этот код:", + "instruction4": "Нажмите на кнопку, когда завершите вход:" + } + }, + "settings": { + "title": "Настройки", + "menu": { + "appearance": "Внешнией вид", + "language": "Язык", + "open": "Открыть настройки" + }, + "appearance": { + "lightLabel": "Светлая тема", + "darkLabel": "Тёмная тема" + } + } + } + \ No newline at end of file diff --git a/frontend/app_flowy/lib/startup/tasks/application_widget.dart b/frontend/app_flowy/lib/startup/tasks/application_widget.dart index ceee515c60..1867c79cda 100644 --- a/frontend/app_flowy/lib/startup/tasks/application_widget.dart +++ b/frontend/app_flowy/lib/startup/tasks/application_widget.dart @@ -29,7 +29,7 @@ class AppWidgetTask extends LaunchTask { () { runApp( EasyLocalization( - supportedLocales: const [Locale('en'), Locale('zh', 'CN'), Locale('it', 'IT'), Locale('fr', 'CA')], + supportedLocales: const [Locale('en'), Locale('zh', 'CN'), Locale('it', 'IT'), Locale('fr', 'CA'), Locale('ru', 'RU')], path: 'assets/translations', fallbackLocale: const Locale('en'), child: app), From 18407a0e470a59c0b63c58e0251435f3de8c663c Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 5 Feb 2022 11:05:06 +0800 Subject: [PATCH 08/14] fix: new doc button's langauge display issue --- .../presentation/widgets/menu/widget/app/header/header.dart | 2 +- .../presentation/widgets/menu/widget/app/menu_app.dart | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart index f3d782f853..795de8d5a7 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart @@ -26,7 +26,7 @@ class MenuAppHeader extends StatelessWidget { @override Widget build(BuildContext context) { - final theme = context.watch(); + final theme = context.read(); return SizedBox( height: MenuAppSizes.headerHeight, child: Row( diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart index 7dab60cf88..f5de26dc13 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/workspace/application/appearance.dart'; import 'package:app_flowy/workspace/presentation/widgets/menu/menu.dart'; import 'package:app_flowy/workspace/presentation/widgets/menu/widget/app/header/header.dart'; import 'package:expandable/expandable.dart'; @@ -79,7 +80,10 @@ class _MenuAppState extends State { iconPadding: EdgeInsets.zero, hasIcon: false, ), - header: MenuAppHeader(widget.app), + header: ChangeNotifierProvider.value( + value: Provider.of(context, listen: true), + child: MenuAppHeader(widget.app), + ), expanded: _renderViewSection(notifier), collapsed: const SizedBox(), ), From 662220ab8a0bedef1b1014df3ac0ff56d8b82069 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 5 Feb 2022 11:15:24 +0800 Subject: [PATCH 09/14] fix: add toolbar tooltip language display issue --- .../workspace/presentation/stack_page/doc/doc_page.dart | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_page.dart index 52b85e108e..35f1ff0364 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_page.dart @@ -1,4 +1,5 @@ import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/application/appearance.dart'; import 'package:app_flowy/workspace/application/doc/doc_bloc.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; @@ -7,6 +8,7 @@ import 'package:flowy_infra_ui/widget/error_page.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:provider/provider.dart'; import 'package:styled_widget/styled_widget.dart'; import 'styles.dart'; import 'widget/banner.dart'; @@ -119,8 +121,11 @@ class _DocPageState extends State { } Widget _renderToolbar(quill.QuillController controller) { - return EditorToolbar.basic( - controller: controller, + return ChangeNotifierProvider.value( + value: Provider.of(context, listen: true), + child: EditorToolbar.basic( + controller: controller, + ), ); } From 0758db971bad971881cd3326acef41d987e1cc13 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 5 Feb 2022 11:16:29 +0800 Subject: [PATCH 10/14] refactor: remove unuse imports --- .../packages/flowy_infra_ui/lib/style_widget/icon_button.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/icon_button.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/icon_button.dart index 4087ccf25d..79e9c648ea 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/icon_button.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/icon_button.dart @@ -1,9 +1,7 @@ import 'dart:math'; import 'package:flowy_infra/image.dart'; -import 'package:flowy_infra/theme.dart'; import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; class FlowyIconButton extends StatelessWidget { final double width; From 592e91bed48bb5101b07d7d4f5af5699c63c369c Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 5 Feb 2022 11:23:10 +0800 Subject: [PATCH 11/14] style: supportedLocales list --- .../lib/startup/tasks/application_widget.dart | 15 ++++++++++----- .../lib/workspace/application/appearance.dart | 1 - .../stack_page/doc/doc_stack_page.dart | 1 - 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/frontend/app_flowy/lib/startup/tasks/application_widget.dart b/frontend/app_flowy/lib/startup/tasks/application_widget.dart index 1867c79cda..d9523fc49e 100644 --- a/frontend/app_flowy/lib/startup/tasks/application_widget.dart +++ b/frontend/app_flowy/lib/startup/tasks/application_widget.dart @@ -2,7 +2,6 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/user/infrastructure/repos/user_setting_repo.dart'; import 'package:app_flowy/workspace/application/appearance.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:flowy_infra/language.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; @@ -29,10 +28,16 @@ class AppWidgetTask extends LaunchTask { () { runApp( EasyLocalization( - supportedLocales: const [Locale('en'), Locale('zh', 'CN'), Locale('it', 'IT'), Locale('fr', 'CA'), Locale('ru', 'RU')], - path: 'assets/translations', - fallbackLocale: const Locale('en'), - child: app), + supportedLocales: const [ + Locale('en'), + Locale('zh', 'CN'), + Locale('it', 'IT'), + Locale('fr', 'CA'), + ], + path: 'assets/translations', + fallbackLocale: const Locale('en'), + child: app, + ), ); }, blocObserver: ApplicationBlocObserver(), diff --git a/frontend/app_flowy/lib/workspace/application/appearance.dart b/frontend/app_flowy/lib/workspace/application/appearance.dart index c59e9ac390..8303912fc0 100644 --- a/frontend/app_flowy/lib/workspace/application/appearance.dart +++ b/frontend/app_flowy/lib/workspace/application/appearance.dart @@ -1,7 +1,6 @@ import 'package:app_flowy/user/infrastructure/repos/user_setting_repo.dart'; import 'package:equatable/equatable.dart'; import 'package:flowy_infra/theme.dart'; -import 'package:flowy_infra/language.dart' as Language; import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_setting.pb.dart'; import 'package:flutter/material.dart'; import 'package:easy_localization/easy_localization.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart index b257c8000d..3e0475c307 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart @@ -7,7 +7,6 @@ import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart'; import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart'; import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:flowy_infra/language.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; From 0d473978515db677eae3505c91bbee107b3db613 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 5 Feb 2022 16:14:15 +0800 Subject: [PATCH 12/14] feat: config commitlint & ignore commitlint auto generated files --- .gitignore | 3 +++ Makefile.toml | 32 ++++++++++++++++++++++++++++++++ commitlint.config.js | 21 ++++++++++++++++++++- package.json | 7 +++++++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 Makefile.toml create mode 100644 package.json diff --git a/.gitignore b/.gitignore index 0d9faef146..8f201fa699 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,6 @@ Cargo.lock .idea/ **/temp/** .ruby-version +package-lock.json +yarn.lock +node_modules diff --git a/Makefile.toml b/Makefile.toml new file mode 100644 index 0000000000..72e65cad91 --- /dev/null +++ b/Makefile.toml @@ -0,0 +1,32 @@ +[tasks.install-commitlint] +mac_alias = "install-commitlint-macos" +windows_alias = "install-commitlint-windows" +linux_alias = "install-commitlint-linux" + +[tasks.install-commitlint-macos] +script = [ + """ + brew install npm + yarn install + yarn husky install + """, +] +script_runner = "@shell" + +[tasks.install-commitlint-windows] +script = [ + """ + echo "WIP" + """, +] +script_runner = "@duckscript" + +[tasks.install-commitlint-linux] +script = [ + """ + sudo apt install nodejs + yarn install + yarn husky install + """, +] +script_runner = "@duckscript" \ No newline at end of file diff --git a/commitlint.config.js b/commitlint.config.js index 28fe5c5bf9..285c34d445 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -1 +1,20 @@ -module.exports = {extends: ['@commitlint/config-conventional']} +// module.exports = {extends: ['@commitlint/config-conventional']} +module.exports = { + rules: { + 'type-enum': [2, 'always', ['feat', 'refactor', 'style', 'fix', 'ci']], + 'body-leading-blank': [1, 'always'], + 'body-max-line-length': [2, 'always', 100], + 'footer-leading-blank': [1, 'always'], + 'footer-max-line-length': [2, 'always', 100], + 'header-max-length': [2, 'always', 100], + 'subject-case': [ + 2, + 'never', + ['sentence-case', 'start-case', 'pascal-case', 'upper-case'], + ], + 'subject-empty': [2, 'never'], + 'type-empty': [2, 'never'], + 'type-case': [2, 'always', 'lower-case'], + 'body-case': [2, 'never', []] + }, +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000000..c891bb7d81 --- /dev/null +++ b/package.json @@ -0,0 +1,7 @@ +{ + "devDependencies": { + "@commitlint/cli": "16.1.0", + "@commitlint/config-conventional": "16.0.0", + "husky": "7.0.4" + } +} From e9ba1e18860dc1abd26c42e1ed64b1b31f2d4192 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 5 Feb 2022 21:50:49 +0800 Subject: [PATCH 13/14] fix: fallback to supported locale if easy_localization doesn't support device locale --- .../app_flowy/lib/workspace/application/appearance.dart | 7 +++++++ frontend/rust-lib/flowy-user/src/handlers/user_handler.rs | 8 +++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/frontend/app_flowy/lib/workspace/application/appearance.dart b/frontend/app_flowy/lib/workspace/application/appearance.dart index 8303912fc0..77f3ec567a 100644 --- a/frontend/app_flowy/lib/workspace/application/appearance.dart +++ b/frontend/app_flowy/lib/workspace/application/appearance.dart @@ -1,6 +1,7 @@ import 'package:app_flowy/user/infrastructure/repos/user_setting_repo.dart'; import 'package:equatable/equatable.dart'; import 'package:flowy_infra/theme.dart'; +import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_setting.pb.dart'; import 'package:flutter/material.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -46,6 +47,12 @@ class AppearanceSettingModel extends ChangeNotifier with EquatableMixin { void setLocale(BuildContext context, Locale newLocale) { if (_locale != newLocale) { + if (context.supportedLocales.contains(newLocale)) { + Log.error("Unsupported locale: $newLocale"); + newLocale = const Locale('en'); + Log.debug("Fall back to locale: $newLocale"); + } + context.setLocale(newLocale); _locale = newLocale; setting.locale.languageCode = _locale.languageCode; diff --git a/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs b/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs index 1af32ab72a..ae6794542c 100644 --- a/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs +++ b/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs @@ -59,7 +59,13 @@ pub async fn get_appearance_setting() -> DataResult data_result(AppearanceSettings::default()), Some(s) => { - let setting: AppearanceSettings = serde_json::from_str(&s)?; + let setting = match serde_json::from_str(&s) { + Ok(setting) => setting, + Err(e) => { + tracing::error!("Deserialize AppearanceSettings failed: {:?}, fallback to default", e); + AppearanceSettings::default() + } + }; data_result(setting) } } From 62bafce0b2382cafbe0d68fdc0118f47b9aa0b67 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 5 Feb 2022 21:50:49 +0800 Subject: [PATCH 14/14] fix: fallback to supported locale if easy_localization doesn't support device locale --- frontend/app_flowy/lib/workspace/application/appearance.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/app_flowy/lib/workspace/application/appearance.dart b/frontend/app_flowy/lib/workspace/application/appearance.dart index 77f3ec567a..266ab1a5c5 100644 --- a/frontend/app_flowy/lib/workspace/application/appearance.dart +++ b/frontend/app_flowy/lib/workspace/application/appearance.dart @@ -47,10 +47,10 @@ class AppearanceSettingModel extends ChangeNotifier with EquatableMixin { void setLocale(BuildContext context, Locale newLocale) { if (_locale != newLocale) { - if (context.supportedLocales.contains(newLocale)) { + if (!context.supportedLocales.contains(newLocale)) { Log.error("Unsupported locale: $newLocale"); newLocale = const Locale('en'); - Log.debug("Fall back to locale: $newLocale"); + Log.debug("Fallback to locale: $newLocale"); } context.setLocale(newLocale);