appearance.dart 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import 'dart:async';
  2. import 'package:app_flowy/user/application/user_settings_service.dart';
  3. import 'package:flowy_infra/theme.dart';
  4. import 'package:flowy_sdk/log.dart';
  5. import 'package:flowy_sdk/protobuf/flowy-user/user_setting.pb.dart';
  6. import 'package:flutter/material.dart';
  7. import 'package:easy_localization/easy_localization.dart';
  8. import 'package:flutter_bloc/flutter_bloc.dart';
  9. import 'package:freezed_annotation/freezed_annotation.dart';
  10. part 'appearance.freezed.dart';
  11. /// [AppearanceSettingsCubit] is used to modify the appear setting of AppFlowy application. Includes the [Locale] and [AppTheme].
  12. class AppearanceSettingsCubit extends Cubit<AppearanceSettingsState> {
  13. final AppearanceSettingsPB _setting;
  14. AppearanceSettingsCubit(AppearanceSettingsPB setting)
  15. : _setting = setting,
  16. super(AppearanceSettingsState.initial(
  17. setting.theme,
  18. setting.themeMode,
  19. setting.font,
  20. setting.monospaceFont,
  21. setting.locale,
  22. ));
  23. /// Updates the current theme and notify the listeners the theme was changed.
  24. /// Do nothing if the passed in themeType equal to the current theme type.
  25. // void setTheme(Brightness brightness) {
  26. // if (state.theme.brightness == brightness) {
  27. // return;
  28. // }
  29. // _setting.theme = themeTypeToString(brightness);
  30. // _saveAppearanceSettings();
  31. // emit(state.copyWith(
  32. // theme: AppTheme.fromBrightness(
  33. // brightness: _setting.themeMode,
  34. // font: state.theme.font,
  35. // monospaceFont: state.theme.monospaceFont,
  36. // ),
  37. // ));
  38. // }
  39. /// Updates the current theme and notify the listeners the theme was changed.
  40. /// Do nothing if the passed in themeType equal to the current theme type.
  41. void setThemeMode(ThemeMode themeMode) {
  42. if (state.themeMode == themeMode) {
  43. return;
  44. }
  45. _setting.themeMode = _themeModeToPB(themeMode);
  46. _saveAppearanceSettings();
  47. emit(state.copyWith(themeMode: themeMode));
  48. }
  49. /// Updates the current locale and notify the listeners the locale was changed
  50. /// Fallback to [en] locale If the newLocale is not supported.
  51. void setLocale(BuildContext context, Locale newLocale) {
  52. if (!context.supportedLocales.contains(newLocale)) {
  53. Log.warn("Unsupported locale: $newLocale, Fallback to locale: en");
  54. newLocale = const Locale('en');
  55. }
  56. context.setLocale(newLocale);
  57. if (state.locale != newLocale) {
  58. _setting.locale.languageCode = newLocale.languageCode;
  59. _setting.locale.countryCode = newLocale.countryCode ?? "";
  60. _saveAppearanceSettings();
  61. emit(state.copyWith(locale: newLocale));
  62. }
  63. }
  64. /// Saves key/value setting to disk.
  65. /// Removes the key if the passed in value is null
  66. void setKeyValue(String key, String? value) {
  67. if (key.isEmpty) {
  68. Log.warn("The key should not be empty");
  69. return;
  70. }
  71. if (value == null) {
  72. _setting.settingKeyValue.remove(key);
  73. }
  74. if (_setting.settingKeyValue[key] != value) {
  75. if (value == null) {
  76. _setting.settingKeyValue.remove(key);
  77. } else {
  78. _setting.settingKeyValue[key] = value;
  79. }
  80. }
  81. _saveAppearanceSettings();
  82. }
  83. String? getValue(String key) {
  84. if (key.isEmpty) {
  85. Log.warn("The key should not be empty");
  86. return null;
  87. }
  88. return _setting.settingKeyValue[key];
  89. }
  90. /// Called when the application launch.
  91. /// Uses the device locale when open the application for the first time
  92. void readLocaleWhenAppLaunch(BuildContext context) {
  93. if (_setting.resetToDefault) {
  94. _setting.resetToDefault = false;
  95. _saveAppearanceSettings();
  96. setLocale(context, context.deviceLocale);
  97. return;
  98. }
  99. setLocale(context, state.locale);
  100. }
  101. Future<void> _saveAppearanceSettings() async {
  102. SettingsFFIService().setAppearanceSetting(_setting).then((result) {
  103. result.fold(
  104. (l) => null,
  105. (error) => Log.error(error),
  106. );
  107. });
  108. }
  109. }
  110. ThemeMode _themeModeFromPB(ThemeModePB themeModePB) {
  111. switch (themeModePB) {
  112. case ThemeModePB.Light:
  113. return ThemeMode.light;
  114. case ThemeModePB.Dark:
  115. return ThemeMode.dark;
  116. case ThemeModePB.System:
  117. default:
  118. return ThemeMode.system;
  119. }
  120. }
  121. ThemeModePB _themeModeToPB(ThemeMode themeMode) {
  122. switch (themeMode) {
  123. case ThemeMode.light:
  124. return ThemeModePB.Light;
  125. case ThemeMode.dark:
  126. return ThemeModePB.Dark;
  127. case ThemeMode.system:
  128. default:
  129. return ThemeModePB.System;
  130. }
  131. }
  132. @freezed
  133. class AppearanceSettingsState with _$AppearanceSettingsState {
  134. const factory AppearanceSettingsState({
  135. required AppTheme theme,
  136. required AppTheme darkTheme,
  137. required ThemeMode themeMode,
  138. required Locale locale,
  139. }) = _AppearanceSettingsState;
  140. factory AppearanceSettingsState.initial(
  141. String themeName,
  142. ThemeModePB themeMode,
  143. String font,
  144. String monospaceFont,
  145. LocaleSettingsPB locale,
  146. ) =>
  147. AppearanceSettingsState(
  148. theme: AppTheme.fromBrightness(
  149. brightness: Brightness.light,
  150. font: font,
  151. monospaceFont: monospaceFont,
  152. ),
  153. darkTheme: AppTheme.fromBrightness(
  154. brightness: Brightness.dark,
  155. font: font,
  156. monospaceFont: monospaceFont,
  157. ),
  158. themeMode: _themeModeFromPB(themeMode),
  159. locale: Locale(locale.languageCode, locale.countryCode),
  160. );
  161. }