save theme setting

This commit is contained in:
appflowy 2022-01-28 18:34:21 +08:00
parent 8449f736e7
commit 1c2c1e6250
17 changed files with 163 additions and 80 deletions

View File

@ -1,5 +1,6 @@
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/presentation/theme/theme_model.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/theme.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
@ -15,9 +16,14 @@ class AppWidgetTask extends LaunchTask {
LaunchTaskType get type => LaunchTaskType.appLauncher;
@override
Future<void> initialize(LaunchContext context) {
Future<void> initialize(LaunchContext context) async {
final widget = context.getIt<EntryPoint>().create();
final app = ApplicationWidget(child: widget);
final setting = await UserSettingReppsitory().getAppearanceSettings();
final settingModel = AppearanceSettingModel(setting);
final app = ApplicationWidget(
child: widget,
settingModel: settingModel,
);
BlocOverrides.runZoned(
() {
runApp(
@ -37,36 +43,40 @@ class AppWidgetTask extends LaunchTask {
class ApplicationWidget extends StatelessWidget {
final Widget child;
final AppearanceSettingModel settingModel;
const ApplicationWidget({
Key? key,
required this.child,
required this.settingModel,
}) : super(key: key);
@override
Widget build(BuildContext context) => ChangeNotifierProvider(
create: (context) => ThemeModel(),
builder: (context, _) {
const ratio = 1.73;
const minWidth = 800.0;
setWindowMinSize(const Size(minWidth, minWidth / ratio));
Widget build(BuildContext context) => ChangeNotifierProvider.value(
value: settingModel,
builder: (context, _) {
const ratio = 1.73;
const minWidth = 800.0;
setWindowMinSize(const Size(minWidth, minWidth / ratio));
AppTheme theme = context.select<AppearanceSettingModel, AppTheme>(
(value) => value.theme,
);
ThemeType themeType = context.select<ThemeModel, ThemeType>((value) => value.theme);
AppTheme theme = AppTheme.fromType(themeType);
return Provider.value(
value: theme,
child: MaterialApp(
builder: overlayManagerBuilder(),
debugShowCheckedModeBanner: false,
theme: theme.themeData,
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
navigatorKey: AppGlobals.rootNavKey,
home: child,
),
);
});
return Provider.value(
value: theme,
child: MaterialApp(
builder: overlayManagerBuilder(),
debugShowCheckedModeBanner: false,
theme: theme.themeData,
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
navigatorKey: AppGlobals.rootNavKey,
home: child,
),
);
},
);
}
class AppGlobals {

View File

@ -0,0 +1,24 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/flowy_sdk.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_setting.pb.dart';
class UserSettingReppsitory {
Future<AppearanceSettings> getAppearanceSettings() async {
final result = await UserEventGetAppearanceSetting().send();
return result.fold(
(AppearanceSettings setting) {
return setting;
},
(error) {
throw FlowySDKException(ExceptionType.AppearanceSettingsIsEmpty);
},
);
}
Future<Either<Unit, FlowyError>> setAppearanceSettings(AppearanceSettings settings) {
return UserEventSetAppearanceSetting(settings).send();
}
}

View File

@ -0,0 +1,37 @@
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_sdk/protobuf/flowy-user-data-model/user_setting.pb.dart';
import 'package:flutter/material.dart';
class AppearanceSettingModel extends ChangeNotifier with EquatableMixin {
AppearanceSettings setting;
AppTheme _theme;
AppearanceSettingModel(this.setting) : _theme = AppTheme.fromName(name: setting.theme);
AppTheme get theme => _theme;
Future<void> save() async {
await UserSettingReppsitory().setAppearanceSettings(setting);
}
@override
List<Object> get props {
return [setting.hashCode];
}
void swapTheme() {
final themeType = (_theme.ty == ThemeType.light ? ThemeType.dark : ThemeType.light);
if (_theme.ty != themeType) {
_theme = AppTheme.fromType(themeType);
setting.theme = themeTypeToString(themeType);
notifyListeners();
save();
}
}
void setLanguage(String language) {
// TODO: save the language settings
}
}

View File

@ -1,5 +1,5 @@
import 'package:app_flowy/generated/locale_keys.g.dart';
import 'package:app_flowy/workspace/presentation/theme/theme_model.dart';
import 'package:app_flowy/workspace/application/appearance.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flutter/material.dart';
@ -31,7 +31,7 @@ class SettingsAppearanceView extends StatelessWidget {
Switch(
value: theme.isDark,
onChanged: (val) {
context.read<ThemeModel>().swapTheme();
context.read<AppearanceSettingModel>().swapTheme();
},
),
Text(

View File

@ -1,25 +0,0 @@
import 'package:equatable/equatable.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flutter/material.dart';
class ThemeModel extends ChangeNotifier with EquatableMixin {
ThemeType _theme = ThemeType.light;
@override
List<Object> get props {
return [_theme];
}
ThemeType get theme => _theme;
set theme(ThemeType value) {
if (_theme != value) {
_theme = value;
notifyListeners();
}
}
void swapTheme() {
theme = (theme == ThemeType.light ? ThemeType.dark : ThemeType.light);
}
}

View File

@ -6,14 +6,30 @@ enum ThemeType {
dark,
}
ThemeType themeTypeFromString(String name) {
ThemeType themeType = ThemeType.light;
if (name == "dark") {
themeType = ThemeType.dark;
}
return themeType;
}
String themeTypeToString(ThemeType ty) {
switch (ty) {
case ThemeType.light:
return "light";
case ThemeType.dark:
return "dark";
}
}
//Color Pallettes
const _black = Color(0xff000000);
const _grey = Color(0xff808080);
const _white = Color(0xFFFFFFFF);
class AppTheme {
static ThemeType defaultTheme = ThemeType.light;
ThemeType ty;
bool isDark;
late Color surface; //
late Color hover;
@ -53,13 +69,17 @@ class AppTheme {
late Color shadowColor;
/// Default constructor
AppTheme({this.isDark = false});
AppTheme({required this.ty, this.isDark = false});
factory AppTheme.fromName({required String name}) {
return AppTheme.fromType(themeTypeFromString(name));
}
/// fromType factory constructor
factory AppTheme.fromType(ThemeType t) {
switch (t) {
factory AppTheme.fromType(ThemeType themeType) {
switch (themeType) {
case ThemeType.light:
return AppTheme(isDark: false)
return AppTheme(ty: themeType, isDark: false)
..surface = Colors.white
..hover = const Color(0xFFe0f8ff) //
..selector = const Color(0xfff2fcff)
@ -93,7 +113,7 @@ class AppTheme {
..shadowColor = _black;
case ThemeType.dark:
return AppTheme(isDark: true)
return AppTheme(ty: themeType, isDark: true)
..surface = const Color(0xff292929)
..hover = const Color(0xff1f1f1f)
..selector = const Color(0xff333333)

View File

@ -536,13 +536,13 @@ class UserEventCheckUser {
}
}
class UserEventUpdateAppearanceSetting {
class UserEventSetAppearanceSetting {
AppearanceSettings request;
UserEventUpdateAppearanceSetting(this.request);
UserEventSetAppearanceSetting(this.request);
Future<Either<Unit, FlowyError>> send() {
final request = FFIRequest.create()
..event = UserEvent.UpdateAppearanceSetting.toString()
..event = UserEvent.SetAppearanceSetting.toString()
..payload = requestToBytes(this.request);
return Dispatch.asyncRequest(request)

View File

@ -26,6 +26,7 @@ import 'package:flowy_sdk/protobuf/flowy-collaboration/protobuf.dart';
import 'package:flowy_sdk/protobuf/lib-infra/protobuf.dart';
import 'package:protobuf/protobuf.dart';
import 'dart:convert' show utf8;
import '../protobuf/flowy-user-data-model/user_setting.pb.dart';
import 'error.dart';
part 'code_gen.dart';

View File

@ -7,6 +7,15 @@ import 'dart:ffi';
import 'ffi.dart' as ffi;
import 'package:ffi/ffi.dart';
enum ExceptionType {
AppearanceSettingsIsEmpty,
}
class FlowySDKException implements Exception {
ExceptionType type;
FlowySDKException(this.type);
}
class FlowySDK {
static const MethodChannel _channel = MethodChannel('flowy_sdk');
static Future<String> get platformVersion async {

View File

@ -17,7 +17,7 @@ class UserEvent extends $pb.ProtobufEnum {
static const UserEvent UpdateUser = UserEvent._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateUser');
static const UserEvent GetUserProfile = UserEvent._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetUserProfile');
static const UserEvent CheckUser = UserEvent._(6, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CheckUser');
static const UserEvent UpdateAppearanceSetting = UserEvent._(7, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateAppearanceSetting');
static const UserEvent SetAppearanceSetting = UserEvent._(7, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SetAppearanceSetting');
static const UserEvent GetAppearanceSetting = UserEvent._(8, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetAppearanceSetting');
static const $core.List<UserEvent> values = <UserEvent> [
@ -28,7 +28,7 @@ class UserEvent extends $pb.ProtobufEnum {
UpdateUser,
GetUserProfile,
CheckUser,
UpdateAppearanceSetting,
SetAppearanceSetting,
GetAppearanceSetting,
];

View File

@ -19,10 +19,10 @@ const UserEvent$json = const {
const {'1': 'UpdateUser', '2': 4},
const {'1': 'GetUserProfile', '2': 5},
const {'1': 'CheckUser', '2': 6},
const {'1': 'UpdateAppearanceSetting', '2': 7},
const {'1': 'SetAppearanceSetting', '2': 7},
const {'1': 'GetAppearanceSetting', '2': 8},
],
};
/// Descriptor for `UserEvent`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List userEventDescriptor = $convert.base64Decode('CglVc2VyRXZlbnQSDAoISW5pdFVzZXIQABIKCgZTaWduSW4QARIKCgZTaWduVXAQAhILCgdTaWduT3V0EAMSDgoKVXBkYXRlVXNlchAEEhIKDkdldFVzZXJQcm9maWxlEAUSDQoJQ2hlY2tVc2VyEAYSGwoXVXBkYXRlQXBwZWFyYW5jZVNldHRpbmcQBxIYChRHZXRBcHBlYXJhbmNlU2V0dGluZxAI');
final $typed_data.Uint8List userEventDescriptor = $convert.base64Decode('CglVc2VyRXZlbnQSDAoISW5pdFVzZXIQABIKCgZTaWduSW4QARIKCgZTaWduVXAQAhILCgdTaWduT3V0EAMSDgoKVXBkYXRlVXNlchAEEhIKDkdldFVzZXJQcm9maWxlEAUSDQoJQ2hlY2tVc2VyEAYSGAoUU2V0QXBwZWFyYW5jZVNldHRpbmcQBxIYChRHZXRBcHBlYXJhbmNlU2V0dGluZxAI');

View File

@ -688,6 +688,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.11"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.2"
meta:
dependency: transitive
description:
@ -1077,7 +1084,7 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.3"
version: "0.4.8"
textstyle_extensions:
dependency: transitive
description:

View File

@ -17,7 +17,7 @@ pub fn create(user_session: Arc<UserSession>) -> Module {
.event(UserEvent::SignOut, sign_out)
.event(UserEvent::UpdateUser, update_user_handler)
.event(UserEvent::CheckUser, check_user_handler)
.event(UserEvent::UpdateAppearanceSetting, update_appearance_setting)
.event(UserEvent::SetAppearanceSetting, set_appearance_setting)
.event(UserEvent::GetAppearanceSetting, get_appearance_setting)
}
@ -58,7 +58,7 @@ pub enum UserEvent {
CheckUser = 6,
#[event(input = "AppearanceSettings")]
UpdateAppearanceSetting = 7,
SetAppearanceSetting = 7,
#[event(output = "AppearanceSettings")]
GetAppearanceSetting = 8,

View File

@ -44,7 +44,7 @@ pub async fn update_user_handler(
const APPEARANCE_SETTING_CACHE_KEY: &str = "appearance_settings";
#[tracing::instrument(skip(data), err)]
pub async fn update_appearance_setting(data: Data<AppearanceSettings>) -> Result<(), FlowyError> {
pub async fn set_appearance_setting(data: Data<AppearanceSettings>) -> Result<(), FlowyError> {
let mut setting = data.into_inner();
if setting.theme.is_empty() {
setting.theme = APPEARANCE_DEFAULT_THEME.to_string();

View File

@ -32,7 +32,7 @@ pub enum UserEvent {
UpdateUser = 4,
GetUserProfile = 5,
CheckUser = 6,
UpdateAppearanceSetting = 7,
SetAppearanceSetting = 7,
GetAppearanceSetting = 8,
}
@ -50,7 +50,7 @@ impl ::protobuf::ProtobufEnum for UserEvent {
4 => ::std::option::Option::Some(UserEvent::UpdateUser),
5 => ::std::option::Option::Some(UserEvent::GetUserProfile),
6 => ::std::option::Option::Some(UserEvent::CheckUser),
7 => ::std::option::Option::Some(UserEvent::UpdateAppearanceSetting),
7 => ::std::option::Option::Some(UserEvent::SetAppearanceSetting),
8 => ::std::option::Option::Some(UserEvent::GetAppearanceSetting),
_ => ::std::option::Option::None
}
@ -65,7 +65,7 @@ impl ::protobuf::ProtobufEnum for UserEvent {
UserEvent::UpdateUser,
UserEvent::GetUserProfile,
UserEvent::CheckUser,
UserEvent::UpdateAppearanceSetting,
UserEvent::SetAppearanceSetting,
UserEvent::GetAppearanceSetting,
];
values
@ -95,10 +95,10 @@ impl ::protobuf::reflect::ProtobufValue for UserEvent {
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x0fevent_map.proto*\xa8\x01\n\tUserEvent\x12\x0c\n\x08InitUser\x10\0\
\n\x0fevent_map.proto*\xa5\x01\n\tUserEvent\x12\x0c\n\x08InitUser\x10\0\
\x12\n\n\x06SignIn\x10\x01\x12\n\n\x06SignUp\x10\x02\x12\x0b\n\x07SignOu\
t\x10\x03\x12\x0e\n\nUpdateUser\x10\x04\x12\x12\n\x0eGetUserProfile\x10\
\x05\x12\r\n\tCheckUser\x10\x06\x12\x1b\n\x17UpdateAppearanceSetting\x10\
\x05\x12\r\n\tCheckUser\x10\x06\x12\x18\n\x14SetAppearanceSetting\x10\
\x07\x12\x18\n\x14GetAppearanceSetting\x10\x08J\x9b\x03\n\x06\x12\x04\0\
\0\x0c\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x05\0\x12\x04\x02\0\
\x0c\x01\n\n\n\x03\x05\0\x01\x12\x03\x02\x05\x0e\n\x0b\n\x04\x05\0\x02\0\
@ -116,8 +116,8 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\x04\x12\n\x0c\n\x05\x05\0\x02\x05\x02\x12\x03\x08\x15\x16\n\x0b\n\x04\
\x05\0\x02\x06\x12\x03\t\x04\x12\n\x0c\n\x05\x05\0\x02\x06\x01\x12\x03\t\
\x04\r\n\x0c\n\x05\x05\0\x02\x06\x02\x12\x03\t\x10\x11\n\x0b\n\x04\x05\0\
\x02\x07\x12\x03\n\x04\x20\n\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\n\x04\
\x1b\n\x0c\n\x05\x05\0\x02\x07\x02\x12\x03\n\x1e\x1f\n\x0b\n\x04\x05\0\
\x02\x07\x12\x03\n\x04\x1d\n\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\n\x04\
\x18\n\x0c\n\x05\x05\0\x02\x07\x02\x12\x03\n\x1b\x1c\n\x0b\n\x04\x05\0\
\x02\x08\x12\x03\x0b\x04\x1d\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\x0b\
\x04\x18\n\x0c\n\x05\x05\0\x02\x08\x02\x12\x03\x0b\x1b\x1cb\x06proto3\
";

View File

@ -8,6 +8,6 @@ enum UserEvent {
UpdateUser = 4;
GetUserProfile = 5;
CheckUser = 6;
UpdateAppearanceSetting = 7;
SetAppearanceSetting = 7;
GetAppearanceSetting = 8;
}

View File

@ -19,7 +19,7 @@ pub struct AppearanceSettings {
pub language: String,
}
pub const APPEARANCE_DEFAULT_THEME: &str = "light";
pub const APPEARANCE_DEFAULT_THEME: &str = "dark";
pub const APPEARANCE_DEFAULT_LANGUAGE: &str = "en";
impl std::default::Default for AppearanceSettings {