Browse Source

Theme Toggle Button for AppFlowy. Created by @rileyhawk1417 (#206)

* Added Theme Toggle
* Modified translations
Mike Wallace 3 years ago
parent
commit
dd5d745c31

+ 4 - 0
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?",

+ 4 - 0
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?",

+ 4 - 0
frontend/app_flowy/assets/translations/zh_CN.json

@@ -90,6 +90,10 @@
     "inlineCode": "内联代码",
     "quote": "块引用"
   },
+  "tooltip":{
+    "lightMode" : "切换到灯光模式",
+    "darkMode" : "切换到暗模式"
+  },
   "contactsPage": {
     "title": "联系人",
     "whatsHappening": "这周发生了哪些事?",

+ 24 - 22
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<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,
+          ),
+        );
+      });
 }
 
 class AppGlobals {

+ 25 - 0
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<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);    
+  }
+}

+ 36 - 4
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<AppTheme>();
     return BlocProvider<MenuUserBloc>(
       create: (context) => getIt<MenuUserBloc>(param1: user)..add(const MenuUserEvent.initial()),
       child: BlocBuilder<MenuUserBloc, MenuUserState>(
         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<AppTheme>();
+    return CircleAvatar(
+      backgroundColor: theme.surface,
+      child: IconButton(
+          icon: Icon(theme.isDark ? Icons.dark_mode : Icons.light_mode),
+          color: (theme.textColor),
+          onPressed: () {
+            context.read<ThemeModel>().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<MenuUserBloc>().state.user.name;
     if (name.isEmpty) {