diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index b0741e8859..5c66f4c0a3 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -90,6 +90,10 @@ "inlineCode": "Inline Code", "quote": "Quote Block" }, + "tooltip":{ + "lightMode": "Switch to Light mode", + "darkMode": "Switch to Dark mode" + }, "contactsPage": { "title": "Contacts", "whatsHappening": "What's happening this week?", diff --git a/frontend/app_flowy/assets/translations/it_IT.json b/frontend/app_flowy/assets/translations/it_IT.json index 067b0f06b5..0d144ad287 100644 --- a/frontend/app_flowy/assets/translations/it_IT.json +++ b/frontend/app_flowy/assets/translations/it_IT.json @@ -90,6 +90,10 @@ "inlineCode": "Codice in linea", "quote": "Cita Blocco" }, + "tooltip":{ + "lightMode" : "Passa alla modalità Luce", + "darkMode" : "Passa alla modalità Buio" + }, "contactsPage": { "title": "Contatti", "whatsHappening": "Cosa accadrà la prossima settimana?", diff --git a/frontend/app_flowy/assets/translations/zh_CN.json b/frontend/app_flowy/assets/translations/zh_CN.json index 8fc58a0d14..b57bcd8c36 100644 --- a/frontend/app_flowy/assets/translations/zh_CN.json +++ b/frontend/app_flowy/assets/translations/zh_CN.json @@ -90,6 +90,10 @@ "inlineCode": "内联代码", "quote": "块引用" }, + "tooltip":{ + "lightMode" : "切换到灯光模式", + "darkMode" : "切换到暗模式" + }, "contactsPage": { "title": "联系人", "whatsHappening": "这周发生了哪些事?", diff --git a/frontend/app_flowy/lib/startup/tasks/application_widget.dart b/frontend/app_flowy/lib/startup/tasks/application_widget.dart index 09ec989f27..e9541ca068 100644 --- a/frontend/app_flowy/lib/startup/tasks/application_widget.dart +++ b/frontend/app_flowy/lib/startup/tasks/application_widget.dart @@ -1,4 +1,5 @@ import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/workspace/presentation/theme/theme_model.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -39,29 +40,30 @@ class ApplicationWidget extends StatelessWidget { }) : super(key: key); @override - Widget build(BuildContext context) { - const ratio = 1.73; - const minWidth = 800.0; - setWindowMinSize(const Size(minWidth, minWidth / ratio)); - // const launchWidth = 1310.0; - // setWindowFrame(const Rect.fromLTWH(0, 0, launchWidth, launchWidth / ratio)); + Widget build(BuildContext context) => ChangeNotifierProvider( + create: (context) => ThemeModel(), + builder: (context, _) { + const ratio = 1.73; + const minWidth = 800.0; + setWindowMinSize(const Size(minWidth, minWidth / ratio)); - final theme = AppTheme.fromType(ThemeType.light); - theme.isDark = true; - 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, - ), - ); - } + ThemeType themeType = context.select((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, + ), + ); + }); } class AppGlobals { diff --git a/frontend/app_flowy/lib/workspace/presentation/theme/theme_model.dart b/frontend/app_flowy/lib/workspace/presentation/theme/theme_model.dart new file mode 100644 index 0000000000..9853897325 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/presentation/theme/theme_model.dart @@ -0,0 +1,25 @@ +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 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); + } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_user.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_user.dart index 9d08648a41..3ca163efe9 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_user.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_user.dart @@ -1,12 +1,15 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/menu/menu_user_bloc.dart'; import 'package:flowy_infra/size.dart'; +import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-user-data-model/protobuf.dart' show UserProfile; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; -//import 'package:flowy_infra_ui/style_widget/icon_button.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:app_flowy/workspace/presentation/theme/theme_model.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; class MenuUser extends StatelessWidget { final UserProfile user; @@ -14,15 +17,18 @@ class MenuUser extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = context.watch(); return BlocProvider( create: (context) => getIt(param1: user)..add(const MenuUserEvent.initial()), child: BlocBuilder( builder: (context, state) => Row( children: [ _renderAvatar(context), - const HSpace(12), + const HSpace(10), _renderUserName(context), - const HSpace(4), + const HSpace(80), + (theme.isDark ? _renderLightMode(context) : _renderDarkMode(context)), + //ToDo: when the user is allowed to create another workspace, //we get the below block back //_renderDropButton(context), @@ -47,13 +53,39 @@ class MenuUser extends StatelessWidget { style: TextStyle( fontSize: 18, fontWeight: FontWeight.w300, - color: Colors.white, ), ), )), ); } + Widget _renderThemeToggle(BuildContext context) { + final theme = context.watch(); + return CircleAvatar( + backgroundColor: theme.surface, + child: IconButton( + icon: Icon(theme.isDark ? Icons.dark_mode : Icons.light_mode), + color: (theme.textColor), + onPressed: () { + context.read().swapTheme(); + }), + ); + } + + Widget _renderDarkMode(BuildContext context) { + return Tooltip( + message: LocaleKeys.tooltip_darkMode.tr(), + child: _renderThemeToggle(context), + ); + } + + Widget _renderLightMode(BuildContext context) { + return Tooltip( + message: LocaleKeys.tooltip_lightMode.tr(), + child: _renderThemeToggle(context), + ); + } + Widget _renderUserName(BuildContext context) { String name = context.read().state.user.name; if (name.isEmpty) {