mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
save theme setting
This commit is contained in:
parent
8449f736e7
commit
1c2c1e6250
@ -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 {
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
37
frontend/app_flowy/lib/workspace/application/appearance.dart
Normal file
37
frontend/app_flowy/lib/workspace/application/appearance.dart
Normal 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
|
||||
}
|
||||
}
|
@ -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(
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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';
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
];
|
||||
|
||||
|
@ -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');
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -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\
|
||||
";
|
||||
|
@ -8,6 +8,6 @@ enum UserEvent {
|
||||
UpdateUser = 4;
|
||||
GetUserProfile = 5;
|
||||
CheckUser = 6;
|
||||
UpdateAppearanceSetting = 7;
|
||||
SetAppearanceSetting = 7;
|
||||
GetAppearanceSetting = 8;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user