瀏覽代碼

refactor: appflowy theme system pt. 1 (#1407)

* refactor: port theme provider to bloc

* refactor: port from custom theme type enum to material design's brightness

* chore: add custom color extension to ThemeData

* refactor: use Theme.of(context) when trying to get theme colors

* refactor: toggle widget code refactor

* refactor: flowy hover style refactor

* refactor: flowy icon refactor

* fix: regression on sidebar tooltip text from #1210

* chore: read color from theme.of

* chore: quick access to custom color

* fix: dart test

* fix: scrollbar regression

* chore: fix flutter lint

* chore: fix grid bloc test

Co-authored-by: appflowy <[email protected]>
Richard Shiue 2 年之前
父節點
當前提交
bbd64fae81
共有 87 個文件被更改,包括 831 次插入920 次删除
  1. 23 40
      frontend/app_flowy/lib/plugins/board/presentation/board_page.dart
  2. 1 2
      frontend/app_flowy/lib/plugins/board/presentation/card/board_date_cell.dart
  3. 1 3
      frontend/app_flowy/lib/plugins/board/presentation/card/board_url_cell.dart
  4. 5 4
      frontend/app_flowy/lib/plugins/board/presentation/card/card.dart
  5. 7 9
      frontend/app_flowy/lib/plugins/board/presentation/card/container/accessory.dart
  6. 4 4
      frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_setting.dart
  7. 5 6
      frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart
  8. 8 22
      frontend/app_flowy/lib/plugins/doc/document.dart
  9. 1 3
      frontend/app_flowy/lib/plugins/doc/document_page.dart
  10. 9 10
      frontend/app_flowy/lib/plugins/doc/editor_styles.dart
  11. 13 14
      frontend/app_flowy/lib/plugins/doc/presentation/banner.dart
  12. 1 4
      frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart
  13. 6 8
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/cell_accessory.dart
  14. 8 5
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/cell_container.dart
  15. 2 1
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checkbox_cell.dart
  16. 26 26
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_editor.dart
  17. 10 14
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/extension.dart
  18. 3 5
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart
  19. 9 8
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart
  20. 8 6
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/text_field.dart
  21. 9 7
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart
  22. 2 10
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/common/text_field.dart
  23. 6 4
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/footer/grid_footer.dart
  24. 11 10
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart
  25. 4 8
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell_action_sheet.dart
  26. 1 9
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_editor.dart
  27. 4 6
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_list.dart
  28. 5 5
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart
  29. 6 9
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart
  30. 9 13
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/date.dart
  31. 4 6
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/number.dart
  32. 6 11
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option.dart
  33. 5 8
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option_editor.dart
  34. 0 5
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart
  35. 5 6
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_action_sheet.dart
  36. 11 12
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart
  37. 1 5
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart
  38. 10 12
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart
  39. 9 6
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart
  40. 1 5
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart
  41. 13 23
      frontend/app_flowy/lib/plugins/trash/menu.dart
  42. 8 7
      frontend/app_flowy/lib/plugins/trash/src/trash_cell.dart
  43. 13 9
      frontend/app_flowy/lib/plugins/trash/src/trash_header.dart
  44. 10 8
      frontend/app_flowy/lib/plugins/trash/trash_page.dart
  45. 25 39
      frontend/app_flowy/lib/startup/tasks/app_widget.dart
  46. 6 21
      frontend/app_flowy/lib/user/presentation/sign_in_screen.dart
  47. 12 18
      frontend/app_flowy/lib/user/presentation/sign_up_screen.dart
  48. 1 4
      frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart
  49. 10 10
      frontend/app_flowy/lib/user/presentation/welcome_screen.dart
  50. 38 40
      frontend/app_flowy/lib/workspace/application/appearance.dart
  51. 2 5
      frontend/app_flowy/lib/workspace/presentation/home/home_stack.dart
  52. 1 0
      frontend/app_flowy/lib/workspace/presentation/home/menu/app/create_button.dart
  53. 4 11
      frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/add_button.dart
  54. 5 9
      frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart
  55. 1 5
      frontend/app_flowy/lib/workspace/presentation/home/menu/app/menu_app.dart
  56. 10 6
      frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart
  57. 21 16
      frontend/app_flowy/lib/workspace/presentation/home/menu/menu.dart
  58. 4 3
      frontend/app_flowy/lib/workspace/presentation/home/menu/menu_user.dart
  59. 12 10
      frontend/app_flowy/lib/workspace/presentation/home/navigation.dart
  60. 37 45
      frontend/app_flowy/lib/workspace/presentation/settings/settings_dialog.dart
  61. 5 9
      frontend/app_flowy/lib/workspace/presentation/settings/widgets/settings_appearance_view.dart
  62. 20 27
      frontend/app_flowy/lib/workspace/presentation/settings/widgets/settings_language_view.dart
  63. 6 6
      frontend/app_flowy/lib/workspace/presentation/settings/widgets/settings_menu_element.dart
  64. 9 9
      frontend/app_flowy/lib/workspace/presentation/widgets/dialogs.dart
  65. 7 10
      frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart
  66. 1 5
      frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_action.dart
  67. 13 3
      frontend/app_flowy/lib/workspace/presentation/widgets/toggle/toggle.dart
  68. 4 24
      frontend/app_flowy/lib/workspace/presentation/widgets/toggle/toggle_style.dart
  69. 70 0
      frontend/app_flowy/packages/flowy_infra/lib/color_extension.dart
  70. 66 47
      frontend/app_flowy/packages/flowy_infra/lib/theme.dart
  71. 2 5
      frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/appflowy_popover.dart
  72. 2 6
      frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/list_overlay.dart
  73. 4 4
      frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart
  74. 16 13
      frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/hover.dart
  75. 8 5
      frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/icon_button.dart
  76. 7 7
      frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart
  77. 1 4
      frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/text.dart
  78. 3 5
      frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/text_input.dart
  79. 17 15
      frontend/app_flowy/packages/flowy_infra_ui/lib/widget/buttons/base_styled_button.dart
  80. 4 8
      frontend/app_flowy/packages/flowy_infra_ui/lib/widget/buttons/primary_button.dart
  81. 5 9
      frontend/app_flowy/packages/flowy_infra_ui/lib/widget/buttons/secondary_button.dart
  82. 1 5
      frontend/app_flowy/packages/flowy_infra_ui/lib/widget/dialog/styled_dialogs.dart
  83. 3 3
      frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_button.dart
  84. 14 11
      frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart
  85. 35 24
      frontend/app_flowy/test/bloc_test/app_setting_test/appearance_test.dart
  86. 15 15
      frontend/app_flowy/test/bloc_test/grid_test/grid_bloc_test.dart
  87. 1 1
      frontend/app_flowy/test/widget_test/select_option_text_field_test.dart

+ 23 - 40
frontend/app_flowy/lib/plugins/board/presentation/board_page.dart

@@ -9,11 +9,9 @@ import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
 import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart';
 import 'package:app_flowy/plugins/grid/presentation/widgets/cell/cell_builder.dart';
 import 'package:app_flowy/plugins/grid/presentation/widgets/row/row_detail.dart';
-import 'package:app_flowy/workspace/application/appearance.dart';
 import 'package:appflowy_board/appflowy_board.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui_web.dart';
 import 'package:flowy_infra_ui/widget/error_page.dart';
@@ -22,7 +20,6 @@ import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:provider/provider.dart';
 import '../../grid/application/row/row_cache.dart';
 import '../application/board_bloc.dart';
 import 'card/card.dart';
@@ -102,27 +99,21 @@ class _BoardContentState extends State<BoardContent> {
   }
 
   Widget _buildBoard(BuildContext context) {
-    return ChangeNotifierProvider.value(
-      value: Provider.of<AppearanceSetting>(context, listen: true),
-      child: Selector<AppearanceSetting, AppTheme>(
-        selector: (ctx, notifier) => notifier.theme,
-        builder: (ctx, theme, child) => Expanded(
-          child: AppFlowyBoard(
-            boardScrollController: scrollManager,
-            scrollController: ScrollController(),
-            controller: context.read<BoardBloc>().boardController,
-            headerBuilder: _buildHeader,
-            footerBuilder: _buildFooter,
-            cardBuilder: (_, column, columnItem) => _buildCard(
-              context,
-              column,
-              columnItem,
-            ),
-            groupConstraints: const BoxConstraints.tightFor(width: 300),
-            config: AppFlowyBoardConfig(
-              groupBackgroundColor: theme.bg1,
-            ),
-          ),
+    return Expanded(
+      child: AppFlowyBoard(
+        boardScrollController: scrollManager,
+        scrollController: ScrollController(),
+        controller: context.read<BoardBloc>().boardController,
+        headerBuilder: _buildHeader,
+        footerBuilder: _buildFooter,
+        cardBuilder: (_, column, columnItem) => _buildCard(
+          context,
+          column,
+          columnItem,
+        ),
+        groupConstraints: const BoxConstraints.tightFor(width: 300),
+        config: AppFlowyBoardConfig(
+          groupBackgroundColor: Theme.of(context).colorScheme.surfaceVariant,
         ),
       ),
     );
@@ -159,7 +150,6 @@ class _BoardContentState extends State<BoardContent> {
           groupData.headerData.groupName,
           fontSize: 14,
           overflow: TextOverflow.clip,
-          color: context.read<AppTheme>().textColor,
         ),
       ),
       icon: _buildHeaderIcon(boardCustomData),
@@ -168,7 +158,7 @@ class _BoardContentState extends State<BoardContent> {
         width: 20,
         child: svgWidget(
           "home/add",
-          color: context.read<AppTheme>().iconColor,
+          color: Theme.of(context).colorScheme.onSurface,
         ),
       ),
       onAddButtonClick: () {
@@ -191,13 +181,12 @@ class _BoardContentState extends State<BoardContent> {
         width: 20,
         child: svgWidget(
           "home/add",
-          color: context.read<AppTheme>().iconColor,
+          color: Theme.of(context).colorScheme.onSurface,
         ),
       ),
       title: FlowyText.medium(
         LocaleKeys.board_column_create_new_card.tr(),
         fontSize: 14,
-        color: context.read<AppTheme>().textColor,
       ),
       height: 50,
       margin: config.footerPadding,
@@ -276,10 +265,12 @@ class _BoardContentState extends State<BoardContent> {
   }
 
   BoxDecoration _makeBoxDecoration(BuildContext context) {
-    final theme = context.read<AppTheme>();
-    final borderSide = BorderSide(color: theme.shader6, width: 1.0);
+    final borderSide = BorderSide(
+      color: Theme.of(context).dividerColor,
+      width: 1.0,
+    );
     return BoxDecoration(
-      color: theme.surface,
+      color: Theme.of(context).colorScheme.surface,
       border: Border.fromBorderSide(borderSide),
       borderRadius: const BorderRadius.all(Radius.circular(6)),
     );
@@ -329,15 +320,7 @@ class _ToolbarBlocAdaptor extends StatelessWidget {
           fieldController: bloc.fieldController,
         );
 
-        return ChangeNotifierProvider.value(
-          value: Provider.of<AppearanceSetting>(context, listen: true),
-          child: Selector<AppearanceSetting, AppTheme>(
-            selector: (ctx, notifier) => notifier.theme,
-            builder: (ctx, theme, child) {
-              return BoardToolbar(toolbarContext: toolbarContext);
-            },
-          ),
-        );
+        return BoardToolbar(toolbarContext: toolbarContext);
       },
     );
   }

+ 1 - 2
frontend/app_flowy/lib/plugins/board/presentation/card/board_date_cell.dart

@@ -1,6 +1,5 @@
 import 'package:app_flowy/plugins/board/application/card/board_date_cell_bloc.dart';
 import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
@@ -53,7 +52,7 @@ class _BoardDateCellState extends State<BoardDateCell> {
                 child: FlowyText.regular(
                   state.dateStr,
                   fontSize: 13,
-                  color: context.read<AppTheme>().shader3,
+                  color: Theme.of(context).hintColor,
                 ),
               ),
             );

+ 1 - 3
frontend/app_flowy/lib/plugins/board/presentation/card/board_url_cell.dart

@@ -2,7 +2,6 @@ import 'package:app_flowy/plugins/board/application/card/board_url_cell_bloc.dar
 import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:textstyle_extensions/textstyle_extensions.dart';
@@ -37,7 +36,6 @@ class _BoardUrlCellState extends State<BoardUrlCell> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return BlocProvider.value(
       value: _cellBloc,
       child: BlocBuilder<BoardURLCellBloc, BoardURLCellState>(
@@ -58,7 +56,7 @@ class _BoardUrlCellState extends State<BoardUrlCell> {
                     text: state.content,
                     style: TextStyles.general(
                       fontSize: FontSizes.s14,
-                      color: theme.main2,
+                      color: Theme.of(context).colorScheme.onPrimaryContainer,
                     ).underline,
                   ),
                 ),

+ 5 - 4
frontend/app_flowy/lib/plugins/board/presentation/card/card.dart

@@ -3,7 +3,6 @@ import 'package:app_flowy/plugins/board/application/card/card_data_controller.da
 import 'package:app_flowy/plugins/grid/presentation/widgets/row/row_action_sheet.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
@@ -221,8 +220,10 @@ class _CardMoreOption extends StatelessWidget with CardAccessory {
   Widget build(BuildContext context) {
     return Padding(
       padding: const EdgeInsets.all(3.0),
-      child:
-          svgWidget('grid/details', color: context.read<AppTheme>().iconColor),
+      child: svgWidget(
+        'grid/details',
+        color: Theme.of(context).colorScheme.onSurface,
+      ),
     );
   }
 
@@ -243,7 +244,7 @@ class _CardEditOption extends StatelessWidget with CardAccessory {
       padding: const EdgeInsets.all(3.0),
       child: svgWidget(
         'editor/edit',
-        color: context.read<AppTheme>().iconColor,
+        color: Theme.of(context).colorScheme.onSurface,
       ),
     );
   }

+ 7 - 9
frontend/app_flowy/lib/plugins/board/presentation/card/container/accessory.dart

@@ -1,7 +1,5 @@
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
 
 enum AccessoryType {
   edit,
@@ -28,7 +26,6 @@ class CardAccessoryContainer extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.read<AppTheme>();
     final children = accessories.map((accessory) {
       return GestureDetector(
         behavior: HitTestBehavior.opaque,
@@ -36,17 +33,16 @@ class CardAccessoryContainer extends StatelessWidget {
           accessory.onTap(context);
           onTapAccessory(accessory.type);
         },
-        child: _wrapHover(theme, accessory),
+        child: _wrapHover(context, accessory),
       );
     }).toList();
     return _wrapDecoration(context, Row(children: children));
   }
 
-  FlowyHover _wrapHover(AppTheme theme, CardAccessory accessory) {
+  FlowyHover _wrapHover(BuildContext context, CardAccessory accessory) {
     return FlowyHover(
       style: HoverStyle(
-        hoverColor: theme.hover,
-        backgroundColor: theme.surface,
+        backgroundColor: Theme.of(context).colorScheme.surface,
         borderRadius: BorderRadius.zero,
       ),
       builder: (_, onHover) => SizedBox(
@@ -58,8 +54,10 @@ class CardAccessoryContainer extends StatelessWidget {
   }
 
   Widget _wrapDecoration(BuildContext context, Widget child) {
-    final theme = context.read<AppTheme>();
-    final borderSide = BorderSide(color: theme.shader6, width: 1.0);
+    final borderSide = BorderSide(
+      color: Theme.of(context).dividerColor,
+      width: 1.0,
+    );
     final decoration = BoxDecoration(
       color: Colors.transparent,
       border: Border.fromBorderSide(borderSide),

+ 4 - 4
frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_setting.dart

@@ -8,7 +8,6 @@ import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/size.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
@@ -96,7 +95,6 @@ class _SettingItem extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.read<AppTheme>();
     final isSelected = context
         .read<BoardSettingBloc>()
         .state
@@ -111,13 +109,15 @@ class _SettingItem extends StatelessWidget {
           action.title(),
           fontSize: FontSizes.s12,
         ),
-        hoverColor: theme.hover,
         onTap: () {
           context
               .read<BoardSettingBloc>()
               .add(BoardSettingEvent.performAction(action));
         },
-        leftIcon: svgWidget(action.iconName(), color: theme.iconColor),
+        leftIcon: svgWidget(
+          action.iconName(),
+          color: Theme.of(context).colorScheme.onSurface,
+        ),
       ),
     );
   }

+ 5 - 6
frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart

@@ -1,11 +1,9 @@
 import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
-import 'package:flutter/widgets.dart';
-import 'package:provider/provider.dart';
+import 'package:flutter/material.dart';
 
 import 'board_setting.dart';
 
@@ -61,16 +59,17 @@ class _SettingButtonState extends State<_SettingButton> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.read<AppTheme>();
     return AppFlowyPopover(
       controller: popoverController,
       constraints: BoxConstraints.loose(const Size(260, 400)),
       child: FlowyIconButton(
-        hoverColor: theme.hover,
         width: 22,
         icon: Padding(
           padding: const EdgeInsets.symmetric(vertical: 3.0, horizontal: 3.0),
-          child: svgWidget("grid/setting/setting", color: theme.iconColor),
+          child: svgWidget(
+            "grid/setting/setting",
+            color: Theme.of(context).colorScheme.onSurface,
+          ),
         ),
       ),
       popupBuilder: (BuildContext popoverContext) {

+ 8 - 22
frontend/app_flowy/lib/plugins/doc/document.dart

@@ -4,7 +4,6 @@ import 'package:app_flowy/generated/locale_keys.g.dart';
 import 'package:app_flowy/plugins/util.dart';
 import 'package:app_flowy/startup/plugin/plugin.dart';
 import 'package:app_flowy/startup/startup.dart';
-import 'package:app_flowy/workspace/application/appearance.dart';
 import 'package:app_flowy/plugins/doc/application/share_bloc.dart';
 import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
 import 'package:app_flowy/workspace/presentation/home/toast.dart';
@@ -16,7 +15,6 @@ import 'package:clipboard/clipboard.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:file_picker/file_picker.dart';
 import 'package:flowy_infra/size.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/widget/rounded_button.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
@@ -24,7 +22,6 @@ import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-document/entities.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:provider/provider.dart';
 
 import 'document_page.dart';
 
@@ -129,23 +126,13 @@ class DocumentShareButton extends StatelessWidget {
           );
         },
         child: BlocBuilder<DocShareBloc, DocShareState>(
-          builder: (context, state) {
-            return ChangeNotifierProvider.value(
-              value: Provider.of<AppearanceSetting>(context, listen: true),
-              child: Selector<AppearanceSetting, Locale>(
-                selector: (ctx, notifier) => notifier.locale,
-                builder: (ctx, _, child) => ConstrainedBox(
-                  constraints: const BoxConstraints.expand(
-                    height: 30,
-                    width: 100,
-                  ),
-                  child: ShareActionList(
-                    view: view,
-                  ),
-                ),
-              ),
-            );
-          },
+          builder: (context, state) => ConstrainedBox(
+            constraints: const BoxConstraints.expand(
+              height: 30,
+              width: 100,
+            ),
+            child: ShareActionList(view: view),
+          ),
         ),
       ),
     );
@@ -177,7 +164,6 @@ class ShareActionList extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     final docShareBloc = context.read<DocShareBloc>();
     return PopoverActionList<ShareActionWrapper>(
       direction: PopoverDirection.bottomWithCenterAligned,
@@ -189,7 +175,7 @@ class ShareActionList extends StatelessWidget {
           title: LocaleKeys.shareAction_buttonText.tr(),
           fontSize: FontSizes.s12,
           borderRadius: Corners.s6Border,
-          color: theme.main1,
+          color: Theme.of(context).colorScheme.primary,
           onPressed: () => controller.show(),
         );
       },

+ 1 - 3
frontend/app_flowy/lib/plugins/doc/document_page.dart

@@ -3,7 +3,6 @@ import 'package:app_flowy/plugins/doc/presentation/plugins/horizontal_rule_node_
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/plugins/doc/presentation/banner.dart';
 import 'package:appflowy_editor/appflowy_editor.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/widget/error_page.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flutter/material.dart';
@@ -74,9 +73,8 @@ class _DocumentPageState extends State<DocumentPage> {
   }
 
   Widget _renderDocument(BuildContext context, DocumentState state) {
-    final theme = context.watch<AppTheme>();
     return Container(
-      color: theme.surface,
+      color: Theme.of(context).colorScheme.surface,
       child: Column(
         children: [
           if (state.isDeleted) _renderBanner(context),

+ 9 - 10
frontend/app_flowy/lib/plugins/doc/editor_styles.dart

@@ -1,14 +1,12 @@
 import 'package:appflowy_editor/appflowy_editor.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
 
 const _baseFontSize = 14.0;
 
 EditorStyle customEditorTheme(BuildContext context) {
-  final theme = context.watch<AppTheme>();
-
-  var editorStyle = theme.isDark ? EditorStyle.dark : EditorStyle.light;
+  var editorStyle = Theme.of(context).brightness == Brightness.dark
+      ? EditorStyle.dark
+      : EditorStyle.light;
   editorStyle = editorStyle.copyWith(
     textStyle: editorStyle.textStyle?.copyWith(
       fontFamily: 'poppins',
@@ -26,10 +24,10 @@ EditorStyle customEditorTheme(BuildContext context) {
 }
 
 Iterable<ThemeExtension<dynamic>> customPluginTheme(BuildContext context) {
-  final theme = context.watch<AppTheme>();
   const basePadding = 12.0;
-  var headingPluginStyle =
-      theme.isDark ? HeadingPluginStyle.dark : HeadingPluginStyle.light;
+  var headingPluginStyle = Theme.of(context).brightness == Brightness.dark
+      ? HeadingPluginStyle.dark
+      : HeadingPluginStyle.light;
   headingPluginStyle = headingPluginStyle.copyWith(
     textStyle: (EditorState editorState, Node node) {
       final headingToFontSize = {
@@ -57,8 +55,9 @@ Iterable<ThemeExtension<dynamic>> customPluginTheme(BuildContext context) {
       return EdgeInsets.only(bottom: padding);
     },
   );
-  final pluginTheme =
-      theme.isDark ? darkPlguinStyleExtension : lightPlguinStyleExtension;
+  final pluginTheme = Theme.of(context).brightness == Brightness.dark
+      ? darkPlguinStyleExtension
+      : lightPlguinStyleExtension;
   return pluginTheme.toList()
     ..removeWhere((element) => element is HeadingPluginStyle)
     ..add(headingPluginStyle);

+ 13 - 14
frontend/app_flowy/lib/plugins/doc/presentation/banner.dart

@@ -1,11 +1,9 @@
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/size.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/buttons/base_styled_button.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
 import 'package:app_flowy/generated/locale_keys.g.dart';
 
 class DocumentBanner extends StatelessWidget {
@@ -17,12 +15,11 @@ class DocumentBanner extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return ConstrainedBox(
       constraints: const BoxConstraints(minHeight: 60),
       child: Container(
         width: double.infinity,
-        color: theme.main1,
+        color: Theme.of(context).colorScheme.primary,
         child: FittedBox(
           alignment: Alignment.center,
           fit: BoxFit.scaleDown,
@@ -36,30 +33,32 @@ class DocumentBanner extends StatelessWidget {
                   minHeight: 40,
                   contentPadding: EdgeInsets.zero,
                   bgColor: Colors.transparent,
-                  hoverColor: theme.main2,
-                  downColor: theme.main1,
+                  hoverColor: Theme.of(context).colorScheme.primary,
+                  downColor: Theme.of(context).colorScheme.primaryContainer,
                   outlineColor: Colors.white,
                   borderRadius: Corners.s8Border,
                   onPressed: onRestore,
                   child: FlowyText.medium(
-                      LocaleKeys.deletePagePrompt_restore.tr(),
-                      color: Colors.white,
-                      fontSize: 14)),
+                    LocaleKeys.deletePagePrompt_restore.tr(),
+                    color: Theme.of(context).colorScheme.onPrimary,
+                    fontSize: 14,
+                  )),
               const HSpace(20),
               BaseStyledButton(
                   minWidth: 220,
                   minHeight: 40,
                   contentPadding: EdgeInsets.zero,
                   bgColor: Colors.transparent,
-                  hoverColor: theme.main2,
-                  downColor: theme.main1,
+                  hoverColor: Theme.of(context).colorScheme.primaryContainer,
+                  downColor: Theme.of(context).colorScheme.primary,
                   outlineColor: Colors.white,
                   borderRadius: Corners.s8Border,
                   onPressed: onDelete,
                   child: FlowyText.medium(
-                      LocaleKeys.deletePagePrompt_deletePermanent.tr(),
-                      color: Colors.white,
-                      fontSize: 14)),
+                    LocaleKeys.deletePagePrompt_deletePermanent.tr(),
+                    color: Theme.of(context).colorScheme.onPrimary,
+                    fontSize: 14,
+                  )),
             ],
           ),
         ),

+ 1 - 4
frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart

@@ -4,7 +4,6 @@ import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart'
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/plugins/grid/application/grid_bloc.dart';
 import 'package:easy_localization/easy_localization.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui_web.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart';
@@ -335,8 +334,6 @@ class RowCountBadge extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
     return BlocSelector<GridBloc, GridState, int>(
       selector: (state) => state.rowCount,
       builder: (context, rowCount) {
@@ -348,7 +345,7 @@ class RowCountBadge extends StatelessWidget {
               FlowyText.regular(
                 '${LocaleKeys.grid_row_count.tr()} : ',
                 fontSize: 13,
-                color: theme.shader3,
+                color: Theme.of(context).hintColor,
               ),
               FlowyText.regular(rowCount.toString(), fontSize: 13),
             ],

+ 6 - 8
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/cell_accessory.dart

@@ -1,7 +1,7 @@
+import 'package:flowy_infra/color_extension.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/text_style.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
 import 'package:flowy_infra/size.dart';
@@ -71,13 +71,12 @@ class _PrimaryCellAccessoryState extends State<PrimaryCellAccessory>
     if (widget.isCellEditing) {
       return const SizedBox();
     } else {
-      final theme = context.watch<AppTheme>();
       return Tooltip(
         message: LocaleKeys.tooltip_openAsPage.tr(),
         textStyle: TextStyles.caption.textColor(Colors.white),
         child: svgWidget(
           "grid/expander",
-          color: theme.main1,
+          color: Theme.of(context).colorScheme.primary,
         ),
       );
     }
@@ -184,13 +183,14 @@ class _Background extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return Consumer<AccessoryHoverState>(
       builder: (context, state, child) {
         if (state.onHover) {
           return FlowyHoverContainer(
             style: HoverStyle(
-                borderRadius: Corners.s6Border, hoverColor: theme.shader6),
+              borderRadius: Corners.s6Border,
+              hoverColor: CustomColors.of(context).lightGreyHover,
+            ),
           );
         } else {
           return const SizedBox();
@@ -207,12 +207,10 @@ class CellAccessoryContainer extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     final children =
         accessories.where((accessory) => accessory.enable()).map((accessory) {
       final hover = FlowyHover(
-        style:
-            HoverStyle(hoverColor: theme.bg3, backgroundColor: theme.surface),
+        style: HoverStyle(hoverColor: CustomColors.of(context).lightGreyHover),
         builder: (_, onHover) => Container(
           width: 26,
           height: 26,

+ 8 - 5
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/cell_container.dart

@@ -1,6 +1,4 @@
-import 'package:flowy_infra/theme.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter/widgets.dart';
 import 'package:provider/provider.dart';
 import 'package:styled_widget/styled_widget.dart';
 
@@ -66,12 +64,17 @@ class CellContainer extends StatelessWidget {
   }
 
   BoxDecoration _makeBoxDecoration(BuildContext context, bool isFocus) {
-    final theme = context.watch<AppTheme>();
     if (isFocus) {
-      final borderSide = BorderSide(color: theme.main1, width: 1.0);
+      final borderSide = BorderSide(
+        color: Theme.of(context).colorScheme.primary,
+        width: 1.0,
+      );
       return BoxDecoration(border: Border.fromBorderSide(borderSide));
     } else {
-      final borderSide = BorderSide(color: theme.shader5, width: 1.0);
+      final borderSide = BorderSide(
+        color: Theme.of(context).dividerColor,
+        width: 1.0,
+      );
       return BoxDecoration(
           border: Border(right: borderSide, bottom: borderSide));
     }

+ 2 - 1
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checkbox_cell.dart

@@ -2,7 +2,7 @@ import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/plugins/grid/application/prelude.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
-import 'package:flutter/widgets.dart';
+import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import '../../layout/sizes.dart';
 import 'cell_builder.dart';
@@ -44,6 +44,7 @@ class _CheckboxCellState extends GridCellState<GridCheckboxCell> {
             child: Padding(
               padding: GridSize.cellContentInsets,
               child: FlowyIconButton(
+                hoverColor: Colors.transparent,
                 onPressed: () => context
                     .read<CheckboxCellBloc>()
                     .add(const CheckboxCellEvent.select()),

+ 26 - 26
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_editor.dart

@@ -6,10 +6,10 @@ import 'package:app_flowy/workspace/presentation/widgets/toggle/toggle_style.dar
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:dartz/dartz.dart' show Either;
 import 'package:easy_localization/easy_localization.dart';
+import 'package:flowy_infra/color_extension.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
@@ -113,19 +113,18 @@ class _CellCalendarWidgetState extends State<_CellCalendarWidget> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return BlocProvider.value(
       value: bloc,
       child: BlocBuilder<DateCalBloc, DateCalState>(
         buildWhen: (p, c) => false,
         builder: (context, state) {
           List<Widget> children = [
-            _buildCalendar(theme, context),
+            _buildCalendar(context),
             _TimeTextField(
               bloc: context.read<DateCalBloc>(),
               popoverMutex: popoverMutex,
             ),
-            Divider(height: 1, color: theme.shader5),
+            Divider(height: 1, color: Theme.of(context).dividerColor),
             const _IncludeTimeButton(),
             _DateTypeOptionButton(popoverMutex: popoverMutex)
           ];
@@ -153,7 +152,7 @@ class _CellCalendarWidgetState extends State<_CellCalendarWidget> {
     super.dispose();
   }
 
-  Widget _buildCalendar(AppTheme theme, BuildContext context) {
+  Widget _buildCalendar(BuildContext context) {
     return BlocBuilder<DateCalBloc, DateCalState>(
       builder: (context, state) {
         return TableCalendar(
@@ -181,38 +180,38 @@ class _CellCalendarWidgetState extends State<_CellCalendarWidget> {
             weekdayStyle: TextStyles.general(
               fontSize: 13,
               fontWeight: FontWeight.w400,
-              color: theme.shader3,
+              color: Theme.of(context).hintColor,
             ),
             weekendStyle: TextStyles.general(
               fontSize: 13,
               fontWeight: FontWeight.w400,
-              color: theme.shader3,
+              color: Theme.of(context).hintColor,
             ),
           ),
           calendarStyle: CalendarStyle(
             cellMargin: const EdgeInsets.all(3),
             defaultDecoration: BoxDecoration(
-              color: theme.surface,
+              color: Theme.of(context).colorScheme.surface,
               shape: BoxShape.rectangle,
               borderRadius: const BorderRadius.all(Radius.circular(6)),
             ),
             selectedDecoration: BoxDecoration(
-              color: theme.main1,
+              color: Theme.of(context).colorScheme.primary,
               shape: BoxShape.rectangle,
               borderRadius: const BorderRadius.all(Radius.circular(6)),
             ),
             todayDecoration: BoxDecoration(
-              color: theme.shader4,
+              color: CustomColors.of(context).lightGreyHover,
               shape: BoxShape.rectangle,
               borderRadius: const BorderRadius.all(Radius.circular(6)),
             ),
             weekendDecoration: BoxDecoration(
-              color: theme.surface,
+              color: Theme.of(context).colorScheme.surface,
               shape: BoxShape.rectangle,
               borderRadius: const BorderRadius.all(Radius.circular(6)),
             ),
             outsideDecoration: BoxDecoration(
-              color: theme.surface,
+              color: Theme.of(context).colorScheme.surface,
               shape: BoxShape.rectangle,
               borderRadius: const BorderRadius.all(Radius.circular(6)),
             ),
@@ -220,15 +219,14 @@ class _CellCalendarWidgetState extends State<_CellCalendarWidget> {
             weekendTextStyle: TextStyles.body1.size(FontSizes.s14),
             selectedTextStyle: TextStyles.general(
               fontSize: FontSizes.s14,
-              color: theme.surface,
+              color: Theme.of(context).colorScheme.surface,
             ),
             todayTextStyle: TextStyles.general(
               fontSize: FontSizes.s14,
-              color: theme.surface,
             ),
             outsideTextStyle: TextStyles.general(
               fontSize: FontSizes.s14,
-              color: theme.shader4,
+              color: Theme.of(context).disabledColor,
             ),
           ),
           selectedDayPredicate: (day) {
@@ -261,7 +259,6 @@ class _IncludeTimeButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return BlocSelector<DateCalBloc, DateCalState, bool>(
       selector: (state) => state.dateTypeOptionPB.includeTime,
       builder: (context, includeTime) {
@@ -271,7 +268,10 @@ class _IncludeTimeButton extends StatelessWidget {
             padding: kMargin,
             child: Row(
               children: [
-                svgWidget("grid/clock", color: theme.iconColor),
+                svgWidget(
+                  "grid/clock",
+                  color: Theme.of(context).colorScheme.onSurface,
+                ),
                 const HSpace(4),
                 FlowyText.medium(
                   LocaleKeys.grid_field_includeTime.tr(),
@@ -283,7 +283,7 @@ class _IncludeTimeButton extends StatelessWidget {
                   onChanged: (value) => context
                       .read<DateCalBloc>()
                       .add(DateCalEvent.setIncludeTime(!value)),
-                  style: ToggleStyle.big(theme),
+                  style: ToggleStyle.big,
                   padding: EdgeInsets.zero,
                 ),
               ],
@@ -338,7 +338,6 @@ class _TimeTextFieldState extends State<_TimeTextField> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return BlocConsumer<DateCalBloc, DateCalState>(
       listener: (context, state) {
         _controller.text = state.time ?? "";
@@ -355,10 +354,10 @@ class _TimeTextFieldState extends State<_TimeTextField> {
               hintText: state.timeHintText,
               controller: _controller,
               style: TextStyles.body1.size(FontSizes.s14),
-              normalBorderColor: theme.shader4,
-              errorBorderColor: theme.red,
-              focusBorderColor: theme.main1,
-              cursorColor: theme.main1,
+              normalBorderColor: Theme.of(context).colorScheme.outline,
+              errorBorderColor: Theme.of(context).colorScheme.error,
+              focusBorderColor: Theme.of(context).colorScheme.primary,
+              cursorColor: Theme.of(context).colorScheme.primary,
               errorText: state.timeFormatError.fold(() => "", (error) => error),
               onEditingComplete: (value) {
                 widget.bloc.add(DateCalEvent.setTime(value));
@@ -388,7 +387,6 @@ class _DateTypeOptionButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     final title =
         "${LocaleKeys.grid_field_dateFormat.tr()} &${LocaleKeys.grid_field_timeFormat.tr()}";
     return BlocSelector<DateCalBloc, DateCalState, DateTypeOptionPB>(
@@ -401,9 +399,11 @@ class _DateTypeOptionButton extends StatelessWidget {
           constraints: BoxConstraints.loose(const Size(140, 100)),
           child: FlowyButton(
             text: FlowyText.medium(title, fontSize: 14),
-            hoverColor: theme.hover,
             margin: kMargin,
-            rightIcon: svgWidget("grid/more", color: theme.iconColor),
+            rightIcon: svgWidget(
+              "grid/more",
+              color: Theme.of(context).colorScheme.onSurface,
+            ),
           ),
           popupBuilder: (BuildContext popContext) {
             return _CalDateTimeSetting(

+ 10 - 14
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/extension.dart

@@ -1,34 +1,32 @@
-import 'package:flowy_infra/theme.dart';
+import 'package:flowy_infra/color_extension.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:app_flowy/generated/locale_keys.g.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
 
 extension SelectOptionColorExtension on SelectOptionColorPB {
   Color make(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     switch (this) {
       case SelectOptionColorPB.Purple:
-        return theme.tint1;
+        return CustomColors.tint1;
       case SelectOptionColorPB.Pink:
-        return theme.tint2;
+        return CustomColors.tint2;
       case SelectOptionColorPB.LightPink:
-        return theme.tint3;
+        return CustomColors.tint3;
       case SelectOptionColorPB.Orange:
-        return theme.tint4;
+        return CustomColors.tint4;
       case SelectOptionColorPB.Yellow:
-        return theme.tint5;
+        return CustomColors.tint5;
       case SelectOptionColorPB.Lime:
-        return theme.tint6;
+        return CustomColors.tint6;
       case SelectOptionColorPB.Green:
-        return theme.tint7;
+        return CustomColors.tint7;
       case SelectOptionColorPB.Aqua:
-        return theme.tint8;
+        return CustomColors.tint8;
       case SelectOptionColorPB.Blue:
-        return theme.tint9;
+        return CustomColors.tint9;
       default:
         throw ArgumentError;
     }
@@ -118,12 +116,10 @@ class SelectOptionTagCell extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return Stack(
       fit: StackFit.expand,
       children: [
         FlowyHover(
-          style: HoverStyle(hoverColor: theme.hover),
           child: InkWell(
             child: Padding(
               padding: const EdgeInsets.symmetric(horizontal: 3),

+ 3 - 5
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart

@@ -2,7 +2,6 @@ import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/plugins/grid/application/prelude.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 // ignore: unused_import
@@ -164,8 +163,7 @@ class _SelectOptionWrapState extends State<SelectOptionWrap> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-    Widget child = _buildOptions(theme, context);
+    Widget child = _buildOptions(context);
 
     return Stack(
       alignment: AlignmentDirectional.center,
@@ -203,13 +201,13 @@ class _SelectOptionWrapState extends State<SelectOptionWrap> {
     );
   }
 
-  Widget _buildOptions(AppTheme theme, BuildContext context) {
+  Widget _buildOptions(BuildContext context) {
     final Widget child;
     if (widget.selectOptions.isEmpty && widget.cellStyle != null) {
       child = FlowyText.medium(
         widget.cellStyle!.placeholder,
         fontSize: 14,
-        color: theme.shader3,
+        color: Theme.of(context).hintColor,
       );
     } else {
       final children = widget.selectOptions.map(

+ 9 - 8
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart

@@ -2,9 +2,9 @@ import 'dart:collection';
 import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
 import 'package:app_flowy/plugins/grid/application/cell/select_option_editor_bloc.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
+import 'package:flowy_infra/color_extension.dart';
 
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
@@ -184,7 +184,6 @@ class _Title extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return SizedBox(
       height: GridSize.typeOptionItemHeight,
       child: Padding(
@@ -192,7 +191,7 @@ class _Title extends StatelessWidget {
         child: FlowyText.medium(
           LocaleKeys.grid_selectOption_panelTitle.tr(),
           fontSize: 12,
-          color: theme.shader3,
+          color: Theme.of(context).hintColor,
         ),
       ),
     );
@@ -205,18 +204,17 @@ class _CreateOptionCell extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return Row(
       children: [
         FlowyText.medium(
           LocaleKeys.grid_selectOption_create.tr(),
           fontSize: 12,
-          color: theme.shader3,
+          color: Theme.of(context).hintColor,
         ),
         const HSpace(10),
         SelectOptionTag(
           name: name,
-          color: theme.shader6,
+          color: CustomColors.of(context).lightGreyHover,
           onSelected: () => context
               .read<SelectOptionCellEditorBloc>()
               .add(SelectOptionEditorEvent.newOption(name)),
@@ -252,7 +250,6 @@ class _SelectOptionCellState extends State<_SelectOptionCell> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return AppFlowyPopover(
       controller: _popoverController,
       offset: const Offset(20, 0),
@@ -283,8 +280,12 @@ class _SelectOptionCellState extends State<_SelectOptionCell> {
             FlowyIconButton(
               width: 30,
               onPressed: () => _popoverController.show(),
+              hoverColor: Colors.transparent,
               iconPadding: const EdgeInsets.fromLTRB(4, 4, 4, 4),
-              icon: svgWidget("editor/details", color: theme.iconColor),
+              icon: svgWidget(
+                "editor/details",
+                color: Theme.of(context).colorScheme.onSurface,
+              ),
             ),
           ],
         ),

+ 8 - 6
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/text_field.dart

@@ -2,14 +2,12 @@ import 'dart:collection';
 
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
 import 'package:flutter/gestures.dart';
 import 'package:flutter/material.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:app_flowy/generated/locale_keys.g.dart';
 import 'package:flutter/services.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:textfield_tags/textfield_tags.dart';
 import 'package:textstyle_extensions/textstyle_extensions.dart';
 
@@ -65,8 +63,6 @@ class _SelectOptionTextFieldState extends State<SelectOptionTextField> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
     return TextFieldTags(
       textEditingController: controller,
       textfieldTagsController: widget.tagController,
@@ -109,7 +105,10 @@ class _SelectOptionTextFieldState extends State<SelectOptionTextField> {
             style: TextStyles.body1.size(FontSizes.s14),
             decoration: InputDecoration(
               enabledBorder: OutlineInputBorder(
-                borderSide: BorderSide(color: theme.main1, width: 1.0),
+                borderSide: BorderSide(
+                  color: Theme.of(context).colorScheme.primary,
+                  width: 1.0,
+                ),
                 borderRadius: Corners.s10Border,
               ),
               isDense: true,
@@ -118,7 +117,10 @@ class _SelectOptionTextFieldState extends State<SelectOptionTextField> {
               prefixIconConstraints:
                   BoxConstraints(maxWidth: widget.distanceToText),
               focusedBorder: OutlineInputBorder(
-                borderSide: BorderSide(color: theme.main1, width: 1.0),
+                borderSide: BorderSide(
+                  color: Theme.of(context).colorScheme.primary,
+                  width: 1.0,
+                ),
                 borderRadius: Corners.s10Border,
               ),
             ),

+ 9 - 7
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart

@@ -7,7 +7,6 @@ import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
@@ -114,7 +113,6 @@ class _GridURLCellState extends GridCellState<GridURLCell> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return BlocProvider.value(
       value: _cellBloc,
       child: BlocBuilder<URLCellBloc, URLCellState>(
@@ -127,7 +125,7 @@ class _GridURLCellState extends GridCellState<GridURLCell> {
                 text: state.content,
                 style: TextStyles.general(
                   fontSize: FontSizes.s14,
-                  color: theme.main2,
+                  color: Theme.of(context).colorScheme.primaryContainer,
                 ).underline,
               ),
             ),
@@ -216,13 +214,15 @@ class _EditURLAccessoryState extends State<_EditURLAccessory>
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return AppFlowyPopover(
       constraints: BoxConstraints.loose(const Size(300, 160)),
       controller: _popoverController,
       direction: PopoverDirection.bottomWithLeftAligned,
       offset: const Offset(0, 20),
-      child: svgWidget("editor/edit", color: theme.iconColor),
+      child: svgWidget(
+        "editor/edit",
+        color: Theme.of(context).colorScheme.onSurface,
+      ),
       popupBuilder: (BuildContext popoverContext) {
         return URLEditorPopover(
           cellController:
@@ -251,8 +251,10 @@ class _CopyURLAccessoryState extends State<_CopyURLAccessory>
     with GridCellAccessoryState {
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-    return svgWidget("editor/copy", color: theme.iconColor);
+    return svgWidget(
+      "editor/copy",
+      color: Theme.of(context).colorScheme.onSurface,
+    );
   }
 
   @override

+ 2 - 10
frontend/app_flowy/lib/plugins/grid/presentation/widgets/common/text_field.dart

@@ -1,9 +1,7 @@
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/scheduler.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:textstyle_extensions/textstyle_extensions.dart';
 
 class InputTextField extends StatefulWidget {
@@ -49,8 +47,6 @@ class _InputTextFieldState extends State<InputTextField> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
     final height = widget.maxLength == null ? 36.0 : 56.0;
 
     return RoundedInputField(
@@ -60,9 +56,6 @@ class _InputTextFieldState extends State<InputTextField> {
       height: height,
       maxLength: widget.maxLength,
       style: TextStyles.body1.size(13),
-      normalBorderColor: theme.shader4,
-      focusBorderColor: theme.main1,
-      cursorColor: theme.main1,
       onChanged: (text) {
         if (widget.onChanged != null) {
           widget.onChanged!(text);
@@ -108,12 +101,11 @@ class TypeOptionSeparator extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return Padding(
       padding: const EdgeInsets.symmetric(vertical: 6),
       child: Container(
-        color: theme.shader4,
-        height: 0.25,
+        color: Theme.of(context).dividerColor,
+        height: 1.0,
       ),
     );
   }

+ 6 - 4
frontend/app_flowy/lib/plugins/grid/presentation/widgets/footer/grid_footer.dart

@@ -1,8 +1,8 @@
 import 'package:app_flowy/generated/locale_keys.g.dart';
 import 'package:app_flowy/plugins/grid/application/grid_bloc.dart';
 import 'package:easy_localization/easy_localization.dart';
+import 'package:flowy_infra/color_extension.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flutter/material.dart';
@@ -13,12 +13,14 @@ class GridAddRowButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return FlowyButton(
       text: FlowyText.medium(LocaleKeys.grid_row_newRow.tr(), fontSize: 12),
-      hoverColor: theme.shader6,
+      hoverColor: CustomColors.of(context).lightGreyHover,
       onTap: () => context.read<GridBloc>().add(const GridEvent.createRow()),
-      leftIcon: svgWidget("home/add", color: theme.iconColor),
+      leftIcon: svgWidget(
+        "home/add",
+        color: Theme.of(context).colorScheme.onSurface,
+      ),
     );
   }
 }

+ 11 - 10
frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart

@@ -1,8 +1,8 @@
 import 'package:app_flowy/plugins/grid/application/field/field_cell_bloc.dart';
 import 'package:app_flowy/plugins/grid/application/field/field_service.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
+import 'package:flowy_infra/color_extension.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
@@ -91,8 +91,10 @@ class _GridHeaderCellContainer extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-    final borderSide = BorderSide(color: theme.shader5, width: 1.0);
+    final borderSide = BorderSide(
+      color: Theme.of(context).dividerColor,
+      width: 1.0,
+    );
     final decoration = BoxDecoration(
         border: Border(
       top: borderSide,
@@ -116,8 +118,6 @@ class _DragToExpandLine extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
     return InkWell(
       onTap: () {},
       child: GestureDetector(
@@ -136,7 +136,7 @@ class _DragToExpandLine extends StatelessWidget {
         child: FlowyHover(
           cursor: SystemMouseCursors.resizeLeftRight,
           style: HoverStyle(
-            hoverColor: theme.main1,
+            hoverColor: Theme.of(context).colorScheme.primary,
             borderRadius: BorderRadius.zero,
             contentMargin: const EdgeInsets.only(left: 6),
           ),
@@ -160,17 +160,18 @@ class FieldCellButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
     // Using this technique to have proper text ellipsis
     // https://github.com/flutter/flutter/issues/18761#issuecomment-812390920
     final text = Characters(field.name)
         .replaceAll(Characters(''), Characters('\u{200B}'))
         .toString();
     return FlowyButton(
-      hoverColor: theme.shader6,
+      hoverColor: CustomColors.of(context).lightGreyHover,
       onTap: onTap,
-      leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor),
+      leftIcon: svgWidget(
+        field.fieldType.iconName(),
+        color: Theme.of(context).colorScheme.onSurface,
+      ),
       text: FlowyText.medium(
         text,
         fontSize: 12,

+ 4 - 8
frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell_action_sheet.dart

@@ -5,7 +5,6 @@ import 'package:app_flowy/plugins/grid/application/prelude.dart';
 import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
@@ -72,8 +71,6 @@ class _EditFieldButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
     return BlocBuilder<FieldActionSheetBloc, FieldActionSheetState>(
       builder: (context, state) {
         return SizedBox(
@@ -83,7 +80,6 @@ class _EditFieldButton extends StatelessWidget {
               LocaleKeys.grid_field_editProperty.tr(),
               fontSize: 12,
             ),
-            hoverColor: theme.hover,
             onTap: onTap,
           ),
         );
@@ -151,14 +147,12 @@ class FieldActionCell extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return FlowyButton(
       text: FlowyText.medium(
         action.title(),
         fontSize: 12,
-        color: enable ? null : theme.shader4,
+        color: enable ? null : Theme.of(context).disabledColor,
       ),
-      hoverColor: theme.hover,
       onTap: () {
         if (enable) {
           action.run(context, fieldContext);
@@ -167,7 +161,9 @@ class FieldActionCell extends StatelessWidget {
       },
       leftIcon: svgWidget(
         action.iconName(),
-        color: enable ? theme.iconColor : theme.disableIconColor,
+        color: enable
+            ? Theme.of(context).colorScheme.onSurface
+            : Theme.of(context).disabledColor,
       ),
     );
   }

+ 1 - 9
frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_editor.dart

@@ -5,7 +5,6 @@ import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:dartz/dartz.dart' show none;
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
@@ -166,7 +165,6 @@ class _FieldNameTextFieldState extends State<_FieldNameTextField> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return MultiBlocListener(
       listeners: [
         BlocListener<FieldEditorBloc, FieldEditorState>(
@@ -193,10 +191,6 @@ class _FieldNameTextFieldState extends State<_FieldNameTextField> {
               fontSize: 13,
             ),
             controller: controller,
-            normalBorderColor: theme.shader4,
-            errorBorderColor: theme.red,
-            focusBorderColor: theme.main1,
-            cursorColor: theme.main1,
             errorText: context.read<FieldEditorBloc>().state.errorText,
             onChanged: (newName) {
               context
@@ -222,7 +216,6 @@ class _DeleteFieldButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return BlocBuilder<FieldEditorBloc, FieldEditorState>(
       buildWhen: (previous, current) => previous != current,
       builder: (context, state) {
@@ -231,10 +224,9 @@ class _DeleteFieldButton extends StatelessWidget {
           text: FlowyText.medium(
             LocaleKeys.grid_field_delete.tr(),
             fontSize: 12,
-            color: enable ? null : theme.shader4,
+            color: enable ? null : Theme.of(context).disabledColor,
           ),
           onTap: () => onDeleted?.call(),
-          hoverColor: theme.hover,
           onHover: (_) => popoverMutex.close(),
         );
         return SizedBox(height: 36, child: button);

+ 4 - 6
frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_list.dart

@@ -1,6 +1,5 @@
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
@@ -10,7 +9,6 @@ import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter/material.dart';
 import '../../layout/sizes.dart';
 import 'field_type_extension.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
 
 typedef SelectFieldCallback = void Function(FieldType);
 
@@ -60,15 +58,15 @@ class FieldTypeCell extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
     return SizedBox(
       height: GridSize.typeOptionItemHeight,
       child: FlowyButton(
         text: FlowyText.medium(fieldType.title(), fontSize: 12),
-        hoverColor: theme.hover,
         onTap: () => onSelectField(fieldType),
-        leftIcon: svgWidget(fieldType.iconName(), color: theme.iconColor),
+        leftIcon: svgWidget(
+          fieldType.iconName(),
+          color: Theme.of(context).colorScheme.onSurface,
+        ),
       ),
     );
   }

+ 5 - 5
frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_type_option_editor.dart

@@ -3,7 +3,6 @@ import 'package:app_flowy/plugins/grid/application/field/type_option/type_option
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:dartz/dartz.dart' show Either;
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
@@ -108,7 +107,6 @@ class _SwitchFieldButton extends StatelessWidget {
   }
 
   Widget _buildMoreButton(BuildContext context) {
-    final theme = context.read<AppTheme>();
     final bloc = context.read<FieldTypeOptionEditBloc>();
     return FlowyButton(
       text: FlowyText.medium(
@@ -116,12 +114,14 @@ class _SwitchFieldButton extends StatelessWidget {
         fontSize: 12,
       ),
       margin: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
-      hoverColor: theme.hover,
       leftIcon: svgWidget(
         bloc.state.field.fieldType.iconName(),
-        color: theme.iconColor,
+        color: Theme.of(context).colorScheme.onSurface,
+      ),
+      rightIcon: svgWidget(
+        "grid/more",
+        color: Theme.of(context).colorScheme.onSurface,
       ),
-      rightIcon: svgWidget("grid/more", color: theme.iconColor),
     );
   }
 }

+ 6 - 9
frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart

@@ -5,8 +5,8 @@ import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/plugins/grid/application/prelude.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
+import 'package:flowy_infra/color_extension.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
@@ -94,7 +94,6 @@ class _GridHeaderState extends State<_GridHeader> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return BlocBuilder<GridHeaderBloc, GridHeaderState>(
       buildWhen: (previous, current) => previous.fields != current.fields,
       builder: (context, state) {
@@ -107,7 +106,7 @@ class _GridHeaderState extends State<_GridHeader> {
             .toList();
 
         return Container(
-          color: theme.surface,
+          color: Theme.of(context).colorScheme.surface,
           child: RepaintBoundary(
             child: ReorderableRow(
               crossAxisAlignment: CrossAxisAlignment.stretch,
@@ -154,8 +153,8 @@ class _CellTrailing extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-    final borderSide = BorderSide(color: theme.shader4, width: 0.4);
+    final borderSide =
+        BorderSide(color: Theme.of(context).dividerColor, width: 1.0);
     return Container(
       width: GridSize.trailHeaderPadding,
       decoration: BoxDecoration(
@@ -173,8 +172,6 @@ class CreateFieldButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
     return AppFlowyPopover(
       direction: PopoverDirection.bottomWithRightAligned,
       asBarrier: true,
@@ -185,11 +182,11 @@ class CreateFieldButton extends StatelessWidget {
           LocaleKeys.grid_field_newColumn.tr(),
           fontSize: 12,
         ),
-        hoverColor: theme.shader6,
+        hoverColor: CustomColors.of(context).lightGreyHover,
         onTap: () {},
         leftIcon: svgWidget(
           "home/add",
-          color: theme.iconColor,
+          color: Theme.of(context).colorScheme.onSurface,
         ),
       ),
       popupBuilder: (BuildContext popover) {

+ 9 - 13
frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/date.dart

@@ -5,7 +5,6 @@ import 'package:app_flowy/workspace/presentation/widgets/toggle/toggle_style.dar
 import 'package:easy_localization/easy_localization.dart' hide DateFormat;
 import 'package:app_flowy/generated/locale_keys.g.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
@@ -120,17 +119,18 @@ class DateFormatButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return SizedBox(
       height: GridSize.typeOptionItemHeight,
       child: FlowyButton(
         text: FlowyText.medium(LocaleKeys.grid_field_dateFormat.tr(),
             fontSize: 12),
         margin: GridSize.typeOptionContentInsets,
-        hoverColor: theme.hover,
         onTap: onTap,
         onHover: onHover,
-        rightIcon: svgWidget("grid/more", color: theme.iconColor),
+        rightIcon: svgWidget(
+          "grid/more",
+          color: Theme.of(context).colorScheme.onSurface,
+        ),
       ),
     );
   }
@@ -146,17 +146,18 @@ class TimeFormatButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return SizedBox(
       height: GridSize.typeOptionItemHeight,
       child: FlowyButton(
         text: FlowyText.medium(LocaleKeys.grid_field_timeFormat.tr(),
             fontSize: 12),
         margin: GridSize.typeOptionContentInsets,
-        hoverColor: theme.hover,
         onTap: onTap,
         onHover: onHover,
-        rightIcon: svgWidget("grid/more", color: theme.iconColor),
+        rightIcon: svgWidget(
+          "grid/more",
+          color: Theme.of(context).colorScheme.onSurface,
+        ),
       ),
     );
   }
@@ -167,7 +168,6 @@ class _IncludeTimeButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return BlocSelector<DateTypeOptionBloc, DateTypeOptionState, bool>(
       selector: (state) => state.typeOption.includeTime,
       builder: (context, includeTime) {
@@ -187,7 +187,7 @@ class _IncludeTimeButton extends StatelessWidget {
                         .read<DateTypeOptionBloc>()
                         .add(DateTypeOptionEvent.includeTime(!value));
                   },
-                  style: ToggleStyle.big(theme),
+                  style: ToggleStyle.big,
                   padding: EdgeInsets.zero,
                 ),
               ],
@@ -246,7 +246,6 @@ class DateFormatCell extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     Widget? checkmark;
     if (isSelected) {
       checkmark = svgWidget("grid/checkmark");
@@ -256,7 +255,6 @@ class DateFormatCell extends StatelessWidget {
       height: GridSize.typeOptionItemHeight,
       child: FlowyButton(
         text: FlowyText.medium(dateFormat.title(), fontSize: 12),
-        hoverColor: theme.hover,
         rightIcon: checkmark,
         onTap: () => onSelected(dateFormat),
       ),
@@ -330,7 +328,6 @@ class TimeFormatCell extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     Widget? checkmark;
     if (isSelected) {
       checkmark = svgWidget("grid/checkmark");
@@ -340,7 +337,6 @@ class TimeFormatCell extends StatelessWidget {
       height: GridSize.typeOptionItemHeight,
       child: FlowyButton(
         text: FlowyText.medium(timeFormat.title(), fontSize: 12),
-        hoverColor: theme.hover,
         rightIcon: checkmark,
         onTap: () => onSelected(timeFormat),
       ),

+ 4 - 6
frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/number.dart

@@ -3,7 +3,6 @@ import 'package:app_flowy/plugins/grid/application/field/type_option/number_form
 import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
@@ -50,7 +49,6 @@ class NumberTypeOptionWidget extends TypeOptionWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return BlocProvider(
       create: (context) =>
           NumberTypeOptionBloc(typeOptionContext: typeOptionContext),
@@ -68,8 +66,10 @@ class NumberTypeOptionWidget extends TypeOptionWidget {
               constraints: BoxConstraints.loose(const Size(460, 440)),
               child: FlowyButton(
                 margin: GridSize.typeOptionContentInsets,
-                hoverColor: theme.hover,
-                rightIcon: svgWidget("grid/more", color: theme.iconColor),
+                rightIcon: svgWidget(
+                  "grid/more",
+                  color: Theme.of(context).colorScheme.onSurface,
+                ),
                 text: Row(
                   children: [
                     FlowyText.medium(LocaleKeys.grid_field_numberFormat.tr(),
@@ -165,7 +165,6 @@ class NumberFormatCell extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     Widget? checkmark;
     if (isSelected) {
       checkmark = svgWidget("grid/checkmark");
@@ -175,7 +174,6 @@ class NumberFormatCell extends StatelessWidget {
       height: GridSize.typeOptionItemHeight,
       child: FlowyButton(
         text: FlowyText.medium(format.title(), fontSize: 12),
-        hoverColor: theme.hover,
         onTap: () => onSelected(format),
         rightIcon: checkmark,
       ),

+ 6 - 11
frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option.dart

@@ -1,7 +1,6 @@
 import 'package:app_flowy/plugins/grid/application/field/type_option/select_option_type_option_bloc.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
@@ -68,14 +67,13 @@ class OptionTitle extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.read<AppTheme>();
     return BlocBuilder<SelectOptionTypeOptionBloc, SelectOptionTypeOptionState>(
       builder: (context, state) {
         List<Widget> children = [
           FlowyText.medium(
             LocaleKeys.grid_field_optionTitle.tr(),
             fontSize: 12,
-            color: theme.shader3,
+            color: Theme.of(context).hintColor,
           )
         ];
         if (state.options.isNotEmpty && !state.isEditingOption) {
@@ -97,7 +95,6 @@ class _OptionTitleButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return SizedBox(
       width: 100,
       height: 26,
@@ -107,7 +104,6 @@ class _OptionTitleButton extends StatelessWidget {
           fontSize: 12,
           textAlign: TextAlign.center,
         ),
-        hoverColor: theme.hover,
         onTap: () {
           context
               .read<SelectOptionTypeOptionBloc>()
@@ -185,8 +181,6 @@ class _OptionCellState extends State<_OptionCell> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
     return AppFlowyPopover(
       controller: _popoverController,
       mutex: widget.popoverMutex,
@@ -203,7 +197,7 @@ class _OptionCellState extends State<_OptionCell> {
           children: [
             svgWidget(
               "grid/details",
-              color: theme.iconColor,
+              color: Theme.of(context).colorScheme.onSurface,
             ),
           ],
         ),
@@ -235,19 +229,20 @@ class _AddOptionButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return SizedBox(
       height: GridSize.typeOptionItemHeight,
       child: FlowyButton(
         text: FlowyText.medium(LocaleKeys.grid_field_addSelectOption.tr(),
             fontSize: 12),
-        hoverColor: theme.hover,
         onTap: () {
           context
               .read<SelectOptionTypeOptionBloc>()
               .add(const SelectOptionTypeOptionEvent.addingOption());
         },
-        leftIcon: svgWidget("home/add", color: theme.iconColor),
+        leftIcon: svgWidget(
+          "home/add",
+          color: Theme.of(context).colorScheme.onSurface,
+        ),
       ),
     );
   }

+ 5 - 8
frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/select_option_editor.dart

@@ -2,7 +2,6 @@ import 'package:app_flowy/plugins/grid/application/field/type_option/edit_select
 import 'package:app_flowy/plugins/grid/presentation/widgets/cell/select_option_cell/extension.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/size.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
@@ -84,14 +83,15 @@ class _DeleteTag extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return SizedBox(
       height: GridSize.typeOptionItemHeight,
       child: FlowyButton(
         text: FlowyText.medium(LocaleKeys.grid_selectOption_deleteTag.tr(),
             fontSize: 12),
-        hoverColor: theme.hover,
-        leftIcon: svgWidget("grid/delete", color: theme.iconColor),
+        leftIcon: svgWidget(
+          "grid/delete",
+          color: Theme.of(context).colorScheme.onSurface,
+        ),
         onTap: () {
           context
               .read<EditSelectOptionBloc>()
@@ -130,7 +130,6 @@ class SelectOptionColorList extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     final cells = SelectOptionColorPB.values.map((color) {
       return _SelectOptionColorCell(
           color: color, isSelected: selectedColor == color);
@@ -148,7 +147,7 @@ class SelectOptionColorList extends StatelessWidget {
               LocaleKeys.grid_selectOption_colorPanelTitle.tr(),
               fontSize: FontSizes.s12,
               textAlign: TextAlign.left,
-              color: theme.shader3,
+              color: Theme.of(context).hintColor,
             ),
           ),
         ),
@@ -178,7 +177,6 @@ class _SelectOptionColorCell extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     Widget? checkmark;
     if (isSelected) {
       checkmark = svgWidget("grid/checkmark");
@@ -198,7 +196,6 @@ class _SelectOptionColorCell extends StatelessWidget {
       height: GridSize.typeOptionItemHeight,
       child: FlowyButton(
         text: FlowyText.medium(color.optionName(), fontSize: 12),
-        hoverColor: theme.hover,
         leftIcon: colorIcon,
         rightIcon: checkmark,
         onTap: () {

+ 0 - 5
frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart

@@ -3,7 +3,6 @@ import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
 import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flutter/foundation.dart';
@@ -152,10 +151,8 @@ class _InsertButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return FlowyIconButton(
       tooltipText: LocaleKeys.tooltip_addNewRow.tr(),
-      hoverColor: theme.hover,
       width: 20,
       height: 30,
       onPressed: () => context.read<RowBloc>().add(const RowEvent.createRow()),
@@ -184,10 +181,8 @@ class _MenuButtonState extends State<_MenuButton> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return FlowyIconButton(
       tooltipText: LocaleKeys.tooltip_openMenu.tr(),
-      hoverColor: theme.hover,
       width: 20,
       height: 30,
       onPressed: () => widget.openMenu(),

+ 5 - 6
frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_action_sheet.dart

@@ -2,7 +2,6 @@ import 'package:app_flowy/plugins/grid/application/row/row_action_sheet_bloc.dar
 import 'package:easy_localization/easy_localization.dart';
 import 'package:app_flowy/generated/locale_keys.g.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
@@ -56,23 +55,23 @@ class _RowActionCell extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
     return SizedBox(
       height: GridSize.typeOptionItemHeight,
       child: FlowyButton(
         text: FlowyText.medium(
           action.title(),
           fontSize: 12,
-          color: action.enable() ? theme.textColor : theme.shader3,
+          color: action.enable() ? null : Theme.of(context).disabledColor,
         ),
-        hoverColor: theme.hover,
         onTap: () {
           if (action.enable()) {
             action.performAction(context);
           }
         },
-        leftIcon: svgWidget(action.iconName(), color: theme.iconColor),
+        leftIcon: svgWidget(
+          action.iconName(),
+          color: Theme.of(context).colorScheme.onSurface,
+        ),
       ),
     );
   }

+ 11 - 12
frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart

@@ -3,8 +3,8 @@ import 'package:app_flowy/plugins/grid/application/field/type_option/type_option
 import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart';
 import 'package:app_flowy/plugins/grid/application/row/row_detail_bloc.dart';
 import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart';
+import 'package:flowy_infra/color_extension.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
@@ -83,14 +83,16 @@ class _CloseButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return FlowyIconButton(
       width: 24,
       onPressed: () {
         FlowyOverlay.pop(context);
       },
       iconPadding: const EdgeInsets.fromLTRB(2, 2, 2, 2),
-      icon: svgWidget("home/close", color: theme.iconColor),
+      icon: svgWidget(
+        "home/close",
+        color: Theme.of(context).colorScheme.onSurface,
+      ),
     );
   }
 }
@@ -187,8 +189,6 @@ class _CreateFieldButtonState extends State<_CreateFieldButton> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.read<AppTheme>();
-
     return AppFlowyPopover(
       constraints: BoxConstraints.loose(const Size(240, 200)),
       controller: popoverController,
@@ -202,7 +202,7 @@ class _CreateFieldButtonState extends State<_CreateFieldButton> {
             LocaleKeys.grid_field_newColumn.tr(),
             fontSize: 12,
           ),
-          hoverColor: theme.shader6,
+          hoverColor: CustomColors.of(context).lightGreyHover,
           onTap: () {},
           leftIcon: svgWidget("home/add"),
         ),
@@ -229,10 +229,10 @@ class _CreateFieldButtonState extends State<_CreateFieldButton> {
   }
 
   BoxDecoration _makeBoxDecoration(BuildContext context) {
-    final theme = context.read<AppTheme>();
-    final borderSide = BorderSide(color: theme.shader6, width: 1.0);
+    final borderSide =
+        BorderSide(color: Theme.of(context).dividerColor, width: 1.0);
     return BoxDecoration(
-      color: theme.surface,
+      color: Theme.of(context).colorScheme.surface,
       border: Border(top: borderSide),
     );
   }
@@ -256,8 +256,7 @@ class _RowDetailCellState extends State<_RowDetailCell> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-    final style = _customCellStyle(theme, widget.cellId.fieldType);
+    final style = _customCellStyle(widget.cellId.fieldType);
     final cell = widget.cellBuilder.build(widget.cellId, style: style);
 
     final gesture = GestureDetector(
@@ -323,7 +322,7 @@ class _RowDetailCellState extends State<_RowDetailCell> {
   }
 }
 
-GridCellStyle? _customCellStyle(AppTheme theme, FieldType fieldType) {
+GridCellStyle? _customCellStyle(FieldType fieldType) {
   switch (fieldType) {
     case FieldType.Checkbox:
       return null;

+ 1 - 5
frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart

@@ -2,7 +2,6 @@ import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
 import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart';
 import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_type_extension.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
@@ -71,8 +70,6 @@ class _GridGroupCell extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.read<AppTheme>();
-
     Widget? rightIcon;
     if (fieldContext.isGroupField) {
       rightIcon = Padding(
@@ -85,10 +82,9 @@ class _GridGroupCell extends StatelessWidget {
       height: GridSize.typeOptionItemHeight,
       child: FlowyButton(
         text: FlowyText.medium(fieldContext.name, fontSize: 12),
-        hoverColor: theme.hover,
         leftIcon: svgWidget(
           fieldContext.fieldType.iconName(),
-          color: theme.iconColor,
+          color: Theme.of(context).colorScheme.onSurface,
         ),
         rightIcon: rightIcon,
         onTap: () {

+ 10 - 12
frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart

@@ -5,7 +5,6 @@ import 'package:app_flowy/plugins/grid/application/setting/property_bloc.dart';
 import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_type_extension.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
@@ -87,22 +86,20 @@ class _GridPropertyCell extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
-    final checkmark = fieldContext.visibility
-        ? svgWidget('home/show', color: theme.iconColor)
-        : svgWidget('home/hide', color: theme.iconColor);
+    final checkmark = svgWidget(
+      fieldContext.visibility ? 'home/show' : 'home/hide',
+      color: Theme.of(context).colorScheme.onSurface,
+    );
 
     return Row(
       children: [
         Expanded(
           child: SizedBox(
             height: GridSize.typeOptionItemHeight,
-            child: _editFieldButton(theme, context),
+            child: _editFieldButton(context),
           ),
         ),
         FlowyIconButton(
-          hoverColor: theme.hover,
           width: GridSize.typeOptionItemHeight,
           onPressed: () {
             context.read<GridPropertyBloc>().add(
@@ -115,16 +112,17 @@ class _GridPropertyCell extends StatelessWidget {
     );
   }
 
-  Widget _editFieldButton(AppTheme theme, BuildContext context) {
+  Widget _editFieldButton(BuildContext context) {
     return AppFlowyPopover(
       mutex: popoverMutex,
       offset: const Offset(20, 0),
       constraints: BoxConstraints.loose(const Size(240, 400)),
       child: FlowyButton(
         text: FlowyText.medium(fieldContext.name, fontSize: 12),
-        hoverColor: theme.hover,
-        leftIcon: svgWidget(fieldContext.fieldType.iconName(),
-            color: theme.iconColor),
+        leftIcon: svgWidget(
+          fieldContext.fieldType.iconName(),
+          color: Theme.of(context).colorScheme.onSurface,
+        ),
       ),
       popupBuilder: (BuildContext context) {
         return FieldEditor(

+ 9 - 6
frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart

@@ -1,7 +1,6 @@
 import 'package:app_flowy/plugins/grid/application/setting/setting_bloc.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
@@ -89,7 +88,6 @@ class _SettingItem extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     final isSelected = context
         .read<GridSettingBloc>()
         .state
@@ -100,15 +98,20 @@ class _SettingItem extends StatelessWidget {
       height: GridSize.typeOptionItemHeight,
       child: FlowyButton(
         isSelected: isSelected,
-        text: FlowyText.medium(action.title(),
-            fontSize: 12, color: action.enable() ? null : theme.shader4),
-        hoverColor: theme.hover,
+        text: FlowyText.medium(
+          action.title(),
+          fontSize: 12,
+          color: action.enable() ? null : Theme.of(context).disabledColor,
+        ),
         onTap: () {
           context
               .read<GridSettingBloc>()
               .add(GridSettingEvent.performAction(action));
         },
-        leftIcon: svgWidget(action.iconName(), color: theme.iconColor),
+        leftIcon: svgWidget(
+          action.iconName(),
+          color: Theme.of(context).colorScheme.onSurface,
+        ),
       ),
     );
   }

+ 1 - 5
frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart

@@ -1,11 +1,9 @@
 import 'package:app_flowy/plugins/grid/application/setting/setting_bloc.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/extension.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
 
 import '../../../application/field/field_controller.dart';
 import '../../layout/sizes.dart';
@@ -51,17 +49,15 @@ class _SettingButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return AppFlowyPopover(
       constraints: BoxConstraints.loose(const Size(260, 400)),
       offset: const Offset(0, 10),
       margin: const EdgeInsets.all(6),
       child: FlowyIconButton(
         width: 22,
-        hoverColor: theme.hover,
         icon: svgWidget(
           "grid/setting/setting",
-          color: theme.iconColor,
+          color: Theme.of(context).colorScheme.onSurface,
         ).padding(horizontal: 3, vertical: 3),
       ),
       popupBuilder: (BuildContext context) {

+ 13 - 23
frontend/app_flowy/lib/plugins/trash/menu.dart

@@ -1,6 +1,5 @@
 import 'package:app_flowy/startup/plugin/plugin.dart';
 import 'package:app_flowy/startup/startup.dart';
-import 'package:app_flowy/workspace/application/appearance.dart';
 import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
 import 'package:app_flowy/workspace/presentation/home/menu/menu.dart';
 import 'package:easy_localization/easy_localization.dart';
@@ -8,9 +7,7 @@ import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
 import 'package:app_flowy/generated/locale_keys.g.dart';
-import 'package:flowy_infra/theme.dart';
 
 class MenuTrash extends StatelessWidget {
   const MenuTrash({Key? key}) : super(key: key);
@@ -31,26 +28,19 @@ class MenuTrash extends StatelessWidget {
   }
 
   Widget _render(BuildContext context) {
-    return Row(children: [
-      ChangeNotifierProvider.value(
-        value: Provider.of<AppearanceSetting>(context, listen: true),
-        child: Selector<AppearanceSetting, AppTheme>(
-          selector: (ctx, notifier) => notifier.theme,
-          builder: (ctx, theme, child) => SizedBox(
-              width: 16,
-              height: 16,
-              child: svgWidget("home/trash", color: theme.iconColor)),
+    return Row(
+      children: [
+        SizedBox(
+          width: 16,
+          height: 16,
+          child: svgWidget(
+            "home/trash",
+            color: Theme.of(context).colorScheme.onSurface,
+          ),
         ),
-      ),
-      const HSpace(6),
-      ChangeNotifierProvider.value(
-        value: Provider.of<AppearanceSetting>(context, listen: true),
-        child: Selector<AppearanceSetting, Locale>(
-          selector: (ctx, notifier) => notifier.locale,
-          builder: (ctx, _, child) =>
-              FlowyText.medium(LocaleKeys.trash_text.tr(), fontSize: 12),
-        ),
-      ),
-    ]);
+        const HSpace(6),
+        FlowyText.medium(LocaleKeys.trash_text.tr(), fontSize: 12),
+      ],
+    );
   }
 }

+ 8 - 7
frontend/app_flowy/lib/plugins/trash/src/trash_cell.dart

@@ -1,5 +1,4 @@
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
@@ -7,7 +6,6 @@ import 'package:flowy_sdk/protobuf/flowy-folder/trash.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:intl/intl.dart';
 import 'package:fixnum/fixnum.dart' as $fixnum;
-import 'package:provider/provider.dart';
 
 import 'sizes.dart';
 
@@ -24,7 +22,6 @@ class TrashCell extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return Row(
       children: [
         SizedBox(
@@ -40,17 +37,21 @@ class TrashCell extends StatelessWidget {
         FlowyIconButton(
           width: 26,
           onPressed: onRestore,
-          hoverColor: theme.hover,
           iconPadding: const EdgeInsets.all(5),
-          icon: svgWidget("editor/restore", color: theme.iconColor),
+          icon: svgWidget(
+            "editor/restore",
+            color: Theme.of(context).colorScheme.onSurface,
+          ),
         ),
         const HSpace(20),
         FlowyIconButton(
           width: 26,
           onPressed: onDelete,
-          hoverColor: theme.hover,
           iconPadding: const EdgeInsets.all(5),
-          icon: svgWidget("editor/delete", color: theme.iconColor),
+          icon: svgWidget(
+            "editor/delete",
+            color: Theme.of(context).colorScheme.onSurface,
+          ),
         ),
       ],
     );

+ 13 - 9
frontend/app_flowy/lib/plugins/trash/src/trash_header.dart

@@ -1,8 +1,6 @@
 import 'package:easy_localization/easy_localization.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
 import 'package:app_flowy/generated/locale_keys.g.dart';
 
 import 'sizes.dart';
@@ -11,7 +9,8 @@ class TrashHeaderDelegate extends SliverPersistentHeaderDelegate {
   TrashHeaderDelegate();
 
   @override
-  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
+  Widget build(
+      BuildContext context, double shrinkOffset, bool overlapsContent) {
     return TrashHeader();
   }
 
@@ -36,16 +35,21 @@ class TrashHeaderItem {
 
 class TrashHeader extends StatelessWidget {
   final List<TrashHeaderItem> items = [
-    TrashHeaderItem(title: LocaleKeys.trash_pageHeader_fileName.tr(), width: TrashSizes.fileNameWidth),
-    TrashHeaderItem(title: LocaleKeys.trash_pageHeader_lastModified.tr(), width: TrashSizes.lashModifyWidth),
-    TrashHeaderItem(title: LocaleKeys.trash_pageHeader_created.tr(), width: TrashSizes.createTimeWidth),
+    TrashHeaderItem(
+        title: LocaleKeys.trash_pageHeader_fileName.tr(),
+        width: TrashSizes.fileNameWidth),
+    TrashHeaderItem(
+        title: LocaleKeys.trash_pageHeader_lastModified.tr(),
+        width: TrashSizes.lashModifyWidth),
+    TrashHeaderItem(
+        title: LocaleKeys.trash_pageHeader_created.tr(),
+        width: TrashSizes.createTimeWidth),
   ];
 
   TrashHeader({Key? key}) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     final headerItems = List<Widget>.empty(growable: true);
     items.asMap().forEach((index, item) {
       headerItems.add(
@@ -54,14 +58,14 @@ class TrashHeader extends StatelessWidget {
           child: FlowyText(
             item.title,
             fontSize: 12,
-            color: theme.shader3,
+            color: Theme.of(context).disabledColor,
           ),
         ),
       );
     });
 
     return Container(
-      color: theme.surface,
+      color: Theme.of(context).colorScheme.surface,
       child: Row(
         crossAxisAlignment: CrossAxisAlignment.stretch,
         children: [

+ 10 - 8
frontend/app_flowy/lib/plugins/trash/trash_page.dart

@@ -4,7 +4,6 @@ import 'package:app_flowy/plugins/trash/src/trash_header.dart';
 import 'package:app_flowy/startup/startup.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart';
@@ -29,7 +28,6 @@ class _TrashPageState extends State<TrashPage> {
   final ScrollController _scrollController = ScrollController();
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     const horizontalPadding = 80.0;
     return BlocProvider(
       create: (context) => getIt<TrashBloc>()..add(const TrashEvent.initial()),
@@ -39,7 +37,7 @@ class _TrashPageState extends State<TrashPage> {
             child: Column(
               mainAxisAlignment: MainAxisAlignment.start,
               children: [
-                _renderTopBar(context, theme, state),
+                _renderTopBar(context, state),
                 const VSpace(32),
                 _renderTrashList(context, state),
               ],
@@ -82,7 +80,7 @@ class _TrashPageState extends State<TrashPage> {
     );
   }
 
-  Widget _renderTopBar(BuildContext context, AppTheme theme, TrashState state) {
+  Widget _renderTopBar(BuildContext context, TrashState state) {
     return SizedBox(
       height: 36,
       child: Row(
@@ -94,8 +92,10 @@ class _TrashPageState extends State<TrashPage> {
             child: FlowyButton(
               text: FlowyText.medium(LocaleKeys.trash_restoreAll.tr(),
                   fontSize: 12),
-              leftIcon: svgWidget('editor/restore', color: theme.iconColor),
-              hoverColor: theme.hover,
+              leftIcon: svgWidget(
+                'editor/restore',
+                color: Theme.of(context).colorScheme.onSurface,
+              ),
               onTap: () => context.read<TrashBloc>().add(
                     const TrashEvent.restoreAll(),
                   ),
@@ -106,8 +106,10 @@ class _TrashPageState extends State<TrashPage> {
             child: FlowyButton(
               text: FlowyText.medium(LocaleKeys.trash_deleteAll.tr(),
                   fontSize: 12),
-              leftIcon: svgWidget('editor/delete', color: theme.iconColor),
-              hoverColor: theme.hover,
+              leftIcon: svgWidget(
+                'editor/delete',
+                color: Theme.of(context).colorScheme.onSurface,
+              ),
               onTap: () =>
                   context.read<TrashBloc>().add(const TrashEvent.deleteAll()),
             ),

+ 25 - 39
frontend/app_flowy/lib/startup/tasks/app_widget.dart

@@ -3,13 +3,12 @@ import 'package:app_flowy/user/application/user_settings_service.dart';
 import 'package:app_flowy/workspace/application/appearance.dart';
 import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
 import 'package:easy_localization/easy_localization.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_sdk/log.dart';
+import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
 import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:window_size/window_size.dart';
-import 'package:bloc/bloc.dart';
 
 class InitAppWidgetTask extends LaunchTask {
   @override
@@ -18,8 +17,7 @@ class InitAppWidgetTask extends LaunchTask {
   @override
   Future<void> initialize(LaunchContext context) async {
     final widget = context.getIt<EntryPoint>().create();
-    final setting = await SettingsFFIService().getAppearanceSetting();
-    final appearanceSetting = AppearanceSetting(setting);
+    final appearanceSetting = await SettingsFFIService().getAppearanceSetting();
     final app = ApplicationWidget(
       appearanceSetting: appearanceSetting,
       child: widget,
@@ -61,7 +59,7 @@ class InitAppWidgetTask extends LaunchTask {
 
 class ApplicationWidget extends StatelessWidget {
   final Widget child;
-  final AppearanceSetting appearanceSetting;
+  final AppearanceSettingsPB appearanceSetting;
 
   const ApplicationWidget({
     Key? key,
@@ -71,40 +69,28 @@ class ApplicationWidget extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return ChangeNotifierProvider.value(
-      value: appearanceSetting,
-      builder: (context, _) {
-        const ratio = 1.73;
-        const minWidth = 600.0;
-        setWindowMinSize(const Size(minWidth, minWidth / ratio));
-        appearanceSetting.readLocaleWhenAppLaunch(context);
-        AppTheme theme = context.select<AppearanceSetting, AppTheme>(
-          (value) => value.theme,
-        );
-        Locale locale = context.select<AppearanceSetting, Locale>(
-          (value) => value.locale,
-        );
+    const ratio = 1.73;
+    const minWidth = 600.0;
+    setWindowMinSize(const Size(minWidth, minWidth / ratio));
 
-        return MultiProvider(
-          providers: [
-            Provider.value(value: theme),
-            Provider.value(value: locale),
-          ],
-          builder: (context, _) {
-            return MaterialApp(
-              builder: overlayManagerBuilder(),
-              debugShowCheckedModeBanner: false,
-              theme: theme.themeData,
-              localizationsDelegates: context.localizationDelegates +
-                  [AppFlowyEditorLocalizations.delegate],
-              supportedLocales: context.supportedLocales,
-              locale: locale,
-              navigatorKey: AppGlobals.rootNavKey,
-              home: child,
-            );
-          },
-        );
-      },
+    final cubit = AppearanceSettingsCubit(appearanceSetting)
+      ..readLocaleWhenAppLaunch(context);
+
+    return BlocProvider(
+      create: (context) => cubit,
+      child: BlocBuilder<AppearanceSettingsCubit, AppearanceSettingsState>(
+        builder: (context, state) => MaterialApp(
+          builder: overlayManagerBuilder(),
+          debugShowCheckedModeBanner: false,
+          theme: state.theme.themeData,
+          localizationsDelegates: context.localizationDelegates +
+              [AppFlowyEditorLocalizations.delegate],
+          supportedLocales: context.supportedLocales,
+          locale: state.locale,
+          navigatorKey: AppGlobals.rootNavKey,
+          home: child,
+        ),
+      ),
     );
   }
 }

+ 6 - 21
frontend/app_flowy/lib/user/presentation/sign_in_screen.dart

@@ -5,7 +5,6 @@ import 'package:app_flowy/user/presentation/widgets/background.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/rounded_button.dart';
 import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
@@ -96,21 +95,20 @@ class SignUpPrompt extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return Row(
       mainAxisAlignment: MainAxisAlignment.center,
       children: [
         FlowyText.medium(
           LocaleKeys.signIn_dontHaveAnAccount.tr(),
           fontSize: FontSizes.s12,
-          color: theme.shader3,
+          color: Theme.of(context).hintColor,
         ),
         TextButton(
           style: TextButton.styleFrom(textStyle: TextStyles.body1),
           onPressed: () => router.pushSignUpScreen(context),
           child: Text(
             LocaleKeys.signUp_buttonText.tr(),
-            style: TextStyle(color: theme.main1),
+            style: TextStyle(color: Theme.of(context).colorScheme.primary),
           ),
         ),
       ],
@@ -125,17 +123,13 @@ class LoginButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return RoundedTextButton(
       title: LocaleKeys.signIn_loginButtonText.tr(),
       height: 48,
       borderRadius: Corners.s10Border,
-      color: theme.main1,
-      onPressed: () {
-        context
-            .read<SignInBloc>()
-            .add(const SignInEvent.signedInWithUserEmailAndPassword());
-      },
+      onPressed: () => context
+          .read<SignInBloc>()
+          .add(const SignInEvent.signedInWithUserEmailAndPassword()),
     );
   }
 }
@@ -150,7 +144,6 @@ class ForgetPasswordButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return TextButton(
       style: TextButton.styleFrom(
         textStyle: TextStyles.body1,
@@ -158,7 +151,7 @@ class ForgetPasswordButton extends StatelessWidget {
       onPressed: () => router.pushForgetPasswordScreen(context),
       child: Text(
         LocaleKeys.signIn_forgotPassword.tr(),
-        style: TextStyle(color: theme.main1),
+        style: TextStyle(color: Theme.of(context).colorScheme.primary),
       ),
     );
   }
@@ -171,7 +164,6 @@ class PasswordTextField extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return BlocBuilder<SignInBloc, SignInState>(
       buildWhen: (previous, current) =>
           previous.passwordError != current.passwordError,
@@ -182,9 +174,6 @@ class PasswordTextField extends StatelessWidget {
           obscureIcon: svgWidget("home/hide"),
           obscureHideIcon: svgWidget("home/show"),
           hintText: LocaleKeys.signIn_passwordHint.tr(),
-          normalBorderColor: theme.shader4,
-          errorBorderColor: theme.red,
-          cursorColor: theme.main1,
           errorText: context
               .read<SignInBloc>()
               .state
@@ -206,7 +195,6 @@ class EmailTextField extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return BlocBuilder<SignInBloc, SignInState>(
       buildWhen: (previous, current) =>
           previous.emailError != current.emailError,
@@ -214,9 +202,6 @@ class EmailTextField extends StatelessWidget {
         return RoundedInputField(
           hintText: LocaleKeys.signIn_emailHint.tr(),
           style: TextStyles.body1.size(FontSizes.s14),
-          normalBorderColor: theme.shader4,
-          errorBorderColor: theme.red,
-          cursorColor: theme.main1,
           errorText: context
               .read<SignInBloc>()
               .state

+ 12 - 18
frontend/app_flowy/lib/user/presentation/sign_up_screen.dart

@@ -5,7 +5,6 @@ import 'package:app_flowy/user/presentation/widgets/background.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/widget/rounded_button.dart';
 import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
@@ -88,19 +87,18 @@ class SignUpPrompt extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return Row(
       mainAxisAlignment: MainAxisAlignment.center,
       children: [
         Text(
           LocaleKeys.signUp_alreadyHaveAnAccount.tr(),
-          style: TextStyle(color: theme.shader3, fontSize: 12),
+          style: TextStyle(color: Theme.of(context).hintColor, fontSize: 12),
         ),
         TextButton(
           style: TextButton.styleFrom(textStyle: TextStyles.body1),
           onPressed: () => Navigator.pop(context),
           child: Text(LocaleKeys.signIn_buttonText.tr(),
-              style: TextStyle(color: theme.main1)),
+              style: TextStyle(color: Theme.of(context).colorScheme.primary)),
         ),
       ],
     );
@@ -114,11 +112,10 @@ class SignUpButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return RoundedTextButton(
       title: LocaleKeys.signUp_getStartedText.tr(),
       height: 48,
-      color: theme.main1,
+      color: Theme.of(context).colorScheme.primary,
       onPressed: () {
         context
             .read<SignUpBloc>()
@@ -135,7 +132,6 @@ class PasswordTextField extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return BlocBuilder<SignUpBloc, SignUpState>(
       buildWhen: (previous, current) =>
           previous.passwordError != current.passwordError,
@@ -146,9 +142,9 @@ class PasswordTextField extends StatelessWidget {
           obscureHideIcon: svgWidget("home/show"),
           style: TextStyles.body1.size(FontSizes.s14),
           hintText: LocaleKeys.signUp_passwordHint.tr(),
-          normalBorderColor: theme.shader4,
-          errorBorderColor: theme.red,
-          cursorColor: theme.main1,
+          normalBorderColor: Theme.of(context).colorScheme.outline,
+          errorBorderColor: Theme.of(context).colorScheme.error,
+          cursorColor: Theme.of(context).colorScheme.primary,
           errorText: context
               .read<SignUpBloc>()
               .state
@@ -170,7 +166,6 @@ class RepeatPasswordTextField extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return BlocBuilder<SignUpBloc, SignUpState>(
       buildWhen: (previous, current) =>
           previous.repeatPasswordError != current.repeatPasswordError,
@@ -181,9 +176,9 @@ class RepeatPasswordTextField extends StatelessWidget {
           obscureHideIcon: svgWidget("home/show"),
           style: TextStyles.body1.size(FontSizes.s14),
           hintText: LocaleKeys.signUp_repeatPasswordHint.tr(),
-          normalBorderColor: theme.shader4,
-          errorBorderColor: theme.red,
-          cursorColor: theme.main1,
+          normalBorderColor: Theme.of(context).colorScheme.outline,
+          errorBorderColor: Theme.of(context).colorScheme.error,
+          cursorColor: Theme.of(context).colorScheme.primary,
           errorText: context
               .read<SignUpBloc>()
               .state
@@ -205,7 +200,6 @@ class EmailTextField extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return BlocBuilder<SignUpBloc, SignUpState>(
       buildWhen: (previous, current) =>
           previous.emailError != current.emailError,
@@ -213,9 +207,9 @@ class EmailTextField extends StatelessWidget {
         return RoundedInputField(
           hintText: LocaleKeys.signUp_emailHint.tr(),
           style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
-          normalBorderColor: theme.shader4,
-          errorBorderColor: theme.red,
-          cursorColor: theme.main1,
+          normalBorderColor: Theme.of(context).colorScheme.outline,
+          errorBorderColor: Theme.of(context).colorScheme.error,
+          cursorColor: Theme.of(context).colorScheme.primary,
           errorText: context
               .read<SignUpBloc>()
               .state

+ 1 - 4
frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart

@@ -4,7 +4,6 @@ import 'package:app_flowy/user/presentation/widgets/background.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra/uuid.dart';
 import 'package:flowy_infra_ui/widget/rounded_button.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
@@ -14,7 +13,6 @@ import 'package:flowy_sdk/protobuf/flowy-folder/protobuf.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:textstyle_extensions/textstyle_extensions.dart';
 import 'package:url_launcher/url_launcher.dart';
 import 'package:dartz/dartz.dart' as dartz;
@@ -141,12 +139,11 @@ class GoButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return RoundedTextButton(
       title: LocaleKeys.letsGoButtonText.tr(),
       height: 50,
       borderRadius: Corners.s10Border,
-      color: theme.main1,
+      color: Theme.of(context).colorScheme.primary,
       onPressed: onPressed,
     );
   }

+ 10 - 10
frontend/app_flowy/lib/user/presentation/welcome_screen.dart

@@ -1,7 +1,7 @@
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/workspace/application/workspace/welcome_bloc.dart';
 import 'package:easy_localization/easy_localization.dart';
-import 'package:flowy_infra/theme.dart';
+import 'package:flowy_infra/color_extension.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/widget/error_page.dart';
@@ -21,7 +21,8 @@ class WelcomeScreen extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     return BlocProvider(
-      create: (_) => getIt<WelcomeBloc>(param1: userProfile)..add(const WelcomeEvent.initial()),
+      create: (_) => getIt<WelcomeBloc>(param1: userProfile)
+        ..add(const WelcomeEvent.initial()),
       child: BlocBuilder<WelcomeBloc, WelcomeState>(
         builder: (context, state) {
           return Scaffold(
@@ -49,17 +50,16 @@ class WelcomeScreen extends StatelessWidget {
   }
 
   Widget _renderCreateButton(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
     return SizedBox(
       width: 200,
       height: 40,
       child: FlowyTextButton(
         LocaleKeys.workspace_create.tr(),
         fontSize: 14,
-        hoverColor: theme.bg3,
+        hoverColor: CustomColors.of(context).lightGreyHover,
         onPressed: () {
-          context.read<WelcomeBloc>().add(WelcomeEvent.createWorkspace(LocaleKeys.workspace_hint.tr(), ""));
+          context.read<WelcomeBloc>().add(
+              WelcomeEvent.createWorkspace(LocaleKeys.workspace_hint.tr(), ""));
         },
       ),
     );
@@ -90,17 +90,17 @@ class WelcomeScreen extends StatelessWidget {
 class WorkspaceItem extends StatelessWidget {
   final WorkspacePB workspace;
   final void Function(WorkspacePB workspace) onPressed;
-  const WorkspaceItem({Key? key, required this.workspace, required this.onPressed}) : super(key: key);
+  const WorkspaceItem(
+      {Key? key, required this.workspace, required this.onPressed})
+      : super(key: key);
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
     return SizedBox(
       height: 46,
       child: FlowyTextButton(
         workspace.name,
-        hoverColor: theme.bg3,
+        hoverColor: CustomColors.of(context).lightGreyHover,
         fontSize: 14,
         onPressed: () => onPressed(workspace),
       ),

+ 38 - 40
frontend/app_flowy/lib/workspace/application/appearance.dart

@@ -1,51 +1,39 @@
 import 'dart:async';
 
 import 'package:app_flowy/user/application/user_settings_service.dart';
-import 'package:equatable/equatable.dart';
 import 'package:flowy_infra/theme.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-user/user_setting.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:freezed_annotation/freezed_annotation.dart';
 
-/// [AppearanceSetting] is used to modify the appear setting of AppFlowy application. Including the [Locale], [AppTheme], etc.
-class AppearanceSetting extends ChangeNotifier with EquatableMixin {
+part 'appearance.freezed.dart';
+
+/// [AppearanceSettingsCubit] is used to modify the appear setting of AppFlowy application. Includes the [Locale] and [AppTheme].
+class AppearanceSettingsCubit extends Cubit<AppearanceSettingsState> {
   final AppearanceSettingsPB _setting;
-  AppTheme _theme;
-  Locale _locale;
 
-  AppearanceSetting(AppearanceSettingsPB setting)
+  AppearanceSettingsCubit(AppearanceSettingsPB setting)
       : _setting = setting,
-        _theme = AppTheme.fromName(name: setting.theme),
-        _locale = Locale(
-          setting.locale.languageCode,
-          setting.locale.countryCode,
-        );
-
-  /// Returns the current [AppTheme]
-  AppTheme get theme => _theme;
-
-  /// Returns the current [Locale]
-  Locale get locale => _locale;
+        super(AppearanceSettingsState.initial(setting.theme, setting.locale));
 
   /// Updates the current theme and notify the listeners the theme was changed.
   /// Do nothing if the passed in themeType equal to the current theme type.
-  ///
-  void setTheme(ThemeType themeType) {
-    if (_theme.ty == themeType) {
+  void setTheme(Brightness brightness) {
+    if (state.theme.brightness == brightness) {
       return;
     }
 
-    _theme = AppTheme.fromType(themeType);
-    _setting.theme = themeTypeToString(themeType);
-    _saveAppearSetting();
+    _setting.theme = themeTypeToString(brightness);
+    _saveAppearanceSettings();
 
-    notifyListeners();
+    emit(state.copyWith(theme: AppTheme.fromType(brightness)));
   }
 
   /// Updates the current locale and notify the listeners the locale was changed
   /// Fallback to [en] locale If the newLocale is not supported.
-  ///
   void setLocale(BuildContext context, Locale newLocale) {
     if (!context.supportedLocales.contains(newLocale)) {
       Log.warn("Unsupported locale: $newLocale, Fallback to locale: en");
@@ -54,13 +42,12 @@ class AppearanceSetting extends ChangeNotifier with EquatableMixin {
 
     context.setLocale(newLocale);
 
-    if (_locale != newLocale) {
-      _locale = newLocale;
-      _setting.locale.languageCode = _locale.languageCode;
-      _setting.locale.countryCode = _locale.countryCode ?? "";
-      _saveAppearSetting();
+    if (state.locale != newLocale) {
+      _setting.locale.languageCode = newLocale.languageCode;
+      _setting.locale.countryCode = newLocale.countryCode ?? "";
+      _saveAppearanceSettings();
 
-      notifyListeners();
+      emit(state.copyWith(locale: newLocale));
     }
   }
 
@@ -83,8 +70,7 @@ class AppearanceSetting extends ChangeNotifier with EquatableMixin {
         _setting.settingKeyValue[key] = value;
       }
     }
-    _saveAppearSetting();
-    notifyListeners();
+    _saveAppearanceSettings();
   }
 
   String? getValue(String key) {
@@ -100,15 +86,15 @@ class AppearanceSetting extends ChangeNotifier with EquatableMixin {
   void readLocaleWhenAppLaunch(BuildContext context) {
     if (_setting.resetToDefault) {
       _setting.resetToDefault = false;
-      _saveAppearSetting();
+      _saveAppearanceSettings();
       setLocale(context, context.deviceLocale);
       return;
     }
 
-    setLocale(context, _locale);
+    setLocale(context, state.locale);
   }
 
-  Future<void> _saveAppearSetting() async {
+  Future<void> _saveAppearanceSettings() async {
     SettingsFFIService().setAppearanceSetting(_setting).then((result) {
       result.fold(
         (l) => null,
@@ -116,9 +102,21 @@ class AppearanceSetting extends ChangeNotifier with EquatableMixin {
       );
     });
   }
+}
 
-  @override
-  List<Object> get props {
-    return [_setting.hashCode];
-  }
+@freezed
+class AppearanceSettingsState with _$AppearanceSettingsState {
+  const factory AppearanceSettingsState({
+    required AppTheme theme,
+    required Locale locale,
+  }) = _AppearanceSettingsState;
+
+  factory AppearanceSettingsState.initial(
+    String themeName,
+    LocaleSettingsPB locale,
+  ) =>
+      AppearanceSettingsState(
+        theme: AppTheme.fromName(name: themeName),
+        locale: Locale(locale.languageCode, locale.countryCode),
+      );
 }

+ 2 - 5
frontend/app_flowy/lib/workspace/presentation/home/home_stack.dart

@@ -1,7 +1,6 @@
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/plugins/blank/blank.dart';
 import 'package:app_flowy/workspace/presentation/home/toast.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
@@ -32,14 +31,13 @@ class HomeStack extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return Column(
       mainAxisAlignment: MainAxisAlignment.start,
       children: [
         getIt<HomeStackManager>().stackTopBar(layout: layout),
         Expanded(
           child: Container(
-            color: theme.surface,
+            color: Theme.of(context).colorScheme.surface,
             child: FocusTraversalGroup(
               child: getIt<HomeStackManager>().stackWidget(
                 onDeleted: (view, index) {
@@ -198,9 +196,8 @@ class HomeTopBar extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return Container(
-      color: theme.surface,
+      color: Theme.of(context).colorScheme.surface,
       height: HomeSizes.topBarHeight,
       child: Row(
         crossAxisAlignment: CrossAxisAlignment.center,

+ 1 - 0
frontend/app_flowy/lib/workspace/presentation/home/menu/app/create_button.dart

@@ -17,6 +17,7 @@ class NewAppButton extends StatelessWidget {
   Widget build(BuildContext context) {
     final child = FlowyTextButton(
       LocaleKeys.newPageText.tr(),
+      hoverColor: Colors.transparent,
       fontSize: FontSizes.s12,
       fontWeight: FontWeight.w500,
       onPressed: () async => await _showCreateAppDialog(context),

+ 4 - 11
frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/add_button.dart

@@ -1,12 +1,10 @@
 import 'package:app_flowy/startup/plugin/plugin.dart';
 import 'package:flowy_infra/image.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:styled_widget/styled_widget.dart';
 
 class AddButton extends StatelessWidget {
@@ -18,9 +16,7 @@ class AddButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return FlowyIconButton(
-      hoverColor: theme.hover,
       width: 22,
       onPressed: () {
         ActionList(
@@ -28,8 +24,10 @@ class AddButton extends StatelessWidget {
           onSelected: onSelected,
         ).show(context);
       },
-      icon: svgWidget("home/add", color: theme.iconColor)
-          .padding(horizontal: 3, vertical: 3),
+      icon: svgWidget(
+        "home/add",
+        color: Theme.of(context).colorScheme.onSurface,
+      ).padding(horizontal: 3, vertical: 3),
     );
   }
 }
@@ -85,11 +83,7 @@ class CreateItem extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-    final config = HoverStyle(hoverColor: theme.hover);
-
     return FlowyHover(
-      style: config,
       child: GestureDetector(
         behavior: HitTestBehavior.opaque,
         onTap: () => onSelected(pluginBuilder),
@@ -102,7 +96,6 @@ class CreateItem extends StatelessWidget {
             alignment: Alignment.centerLeft,
             child: FlowyText.medium(
               pluginBuilder.menuName,
-              color: theme.textColor,
               fontSize: 12,
             ).padding(horizontal: 10),
           ),

+ 5 - 9
frontend/app_flowy/lib/workspace/presentation/home/menu/app/header/header.dart

@@ -5,7 +5,6 @@ import 'package:easy_localization/easy_localization.dart';
 import 'package:expandable/expandable.dart';
 import 'package:flowy_infra/icon_data.dart';
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
 import 'package:flutter/material.dart';
@@ -28,23 +27,22 @@ class MenuAppHeader extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.read<AppTheme>();
     return SizedBox(
       height: MenuAppSizes.headerHeight,
       child: Row(
         mainAxisAlignment: MainAxisAlignment.start,
         crossAxisAlignment: CrossAxisAlignment.center,
         children: [
-          _renderExpandedIcon(context, theme),
+          _renderExpandedIcon(context),
           // HSpace(MenuAppSizes.iconPadding),
-          _renderTitle(context, theme),
+          _renderTitle(context),
           _renderCreateViewButton(context),
         ],
       ),
     );
   }
 
-  Widget _renderExpandedIcon(BuildContext context, AppTheme theme) {
+  Widget _renderExpandedIcon(BuildContext context) {
     return SizedBox(
       width: MenuAppSizes.headerHeight,
       height: MenuAppSizes.headerHeight,
@@ -58,7 +56,7 @@ class MenuAppHeader extends StatelessWidget {
           theme: ExpandableThemeData(
             expandIcon: FlowyIconData.drop_down_show,
             collapseIcon: FlowyIconData.drop_down_hide,
-            iconColor: theme.shader1,
+            iconColor: Theme.of(context).colorScheme.onSurface,
             iconSize: MenuAppSizes.iconSize,
             iconPadding: const EdgeInsets.fromLTRB(0, 0, 10, 0),
             hasIcon: false,
@@ -68,7 +66,7 @@ class MenuAppHeader extends StatelessWidget {
     );
   }
 
-  Widget _renderTitle(BuildContext context, AppTheme theme) {
+  Widget _renderTitle(BuildContext context) {
     return Expanded(
       child: BlocListener<AppBloc, AppState>(
         listenWhen: (p, c) =>
@@ -153,7 +151,6 @@ class AppActionList extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.read<AppTheme>();
     return PopoverActionList<DisclosureActionWrapper>(
       direction: PopoverDirection.bottomWithCenterAligned,
       actions: AppDisclosureAction.values
@@ -173,7 +170,6 @@ class AppActionList extends StatelessWidget {
             builder: (context, app) => FlowyText.medium(
               app.name,
               fontSize: 12,
-              color: theme.textColor,
               overflow: TextOverflow.ellipsis,
             ),
           ),

+ 1 - 5
frontend/app_flowy/lib/workspace/presentation/home/menu/app/menu_app.dart

@@ -1,4 +1,3 @@
-import 'package:app_flowy/workspace/application/appearance.dart';
 import 'package:app_flowy/workspace/presentation/home/menu/menu.dart';
 import 'package:expandable/expandable.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/app.pb.dart';
@@ -87,10 +86,7 @@ class _MenuAppState extends State<MenuApp> {
                 iconPadding: EdgeInsets.zero,
                 hasIcon: false,
               ),
-              header: ChangeNotifierProvider.value(
-                value: Provider.of<AppearanceSetting>(context, listen: true),
-                child: MenuAppHeader(widget.app),
-              ),
+              header: MenuAppHeader(widget.app),
               expanded: ViewSection(appViewData: viewDataContext),
               collapsed: const SizedBox(),
             ),

+ 10 - 6
frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/item.dart

@@ -4,7 +4,7 @@ import 'package:app_flowy/workspace/application/view/view_ext.dart';
 import 'package:app_flowy/workspace/presentation/home/menu/menu.dart';
 import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart';
 import 'package:easy_localization/easy_localization.dart';
-import 'package:flowy_infra/theme.dart';
+import 'package:flowy_infra/color_extension.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
@@ -34,7 +34,6 @@ class ViewSectionItem extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return MultiBlocProvider(
       providers: [
         BlocProvider(
@@ -51,7 +50,9 @@ class ViewSectionItem extends StatelessWidget {
             child: InkWell(
               onTap: () => onSelected(blocContext.read<ViewBloc>().state.view),
               child: FlowyHover(
-                style: HoverStyle(hoverColor: theme.bg3),
+                style: HoverStyle(
+                  hoverColor: CustomColors.of(context).greySelect,
+                ),
                 // If current state.isEditing is true, the hover should not
                 // rebuild when onEnter/onExit events happened.
                 buildWhenOnHover: () => !state.isEditing,
@@ -59,7 +60,7 @@ class ViewSectionItem extends StatelessWidget {
                   blocContext,
                   onHover,
                   state,
-                  theme.iconColor,
+                  Theme.of(context).colorScheme.onSurface,
                 ),
                 isSelected: () => state.isEditing || isSelected,
               ),
@@ -174,7 +175,6 @@ class ViewDisclosureButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return PopoverActionList<ViewDisclosureActionWrapper>(
       direction: PopoverDirection.bottomWithCenterAligned,
       actions: ViewDisclosureAction.values
@@ -182,9 +182,13 @@ class ViewDisclosureButton extends StatelessWidget {
           .toList(),
       buildChild: (controller) {
         return FlowyIconButton(
+          hoverColor: Colors.transparent,
           iconPadding: const EdgeInsets.all(5),
           width: 26,
-          icon: svgWidget("editor/details", color: theme.iconColor),
+          icon: svgWidget(
+            "editor/details",
+            color: Theme.of(context).colorScheme.onSurface,
+          ),
           onPressed: () {
             onEdit(true);
             controller.show();

+ 21 - 16
frontend/app_flowy/lib/workspace/presentation/home/menu/menu.dart

@@ -2,12 +2,13 @@ export './app/header/header.dart';
 export './app/menu_app.dart';
 
 import 'dart:io' show Platform;
+import 'package:app_flowy/generated/locale_keys.g.dart';
 import 'package:app_flowy/plugins/trash/menu.dart';
 import 'package:app_flowy/workspace/presentation/home/home_sizes.dart';
 import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
+import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/notifier.dart';
 import 'package:flowy_infra/size.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart' show UserProfilePB;
@@ -83,9 +84,8 @@ class HomeMenu extends StatelessWidget {
 
   Widget _renderBody(BuildContext context) {
     // nested column: https://siddharthmolleti.com/flutter-box-constraints-nested-column-s-row-s-3dfacada7361
-    final theme = context.watch<AppTheme>();
     return Container(
-      color: theme.bg1,
+      color: Theme.of(context).colorScheme.surfaceVariant,
       child: Column(
         mainAxisAlignment: MainAxisAlignment.start,
         children: [
@@ -202,36 +202,41 @@ class MenuTopBar extends StatelessWidget {
     if (Platform.isMacOS) {
       return Container();
     }
-    final theme = context.watch<AppTheme>();
-    return (theme.isDark
+    return (Theme.of(context).brightness == Brightness.dark
         ? svgWithSize("flowy_logo_dark_mode", const Size(92, 17))
         : svgWithSize("flowy_logo_with_text", const Size(92, 17)));
   }
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return BlocBuilder<MenuBloc, MenuState>(
       builder: (context, state) {
         return SizedBox(
           height: HomeSizes.topBarHeight,
           child: MoveWindowDetector(
-              child: Row(
-            children: [
-              renderIcon(context),
-              const Spacer(),
-              Tooltip(
-                  richMessage: sidebarTooltipTextSpan(),
+            child: Row(
+              children: [
+                renderIcon(context),
+                const Spacer(),
+                Tooltip(
+                  richMessage: sidebarTooltipTextSpan(
+                      LocaleKeys.sideBar_closeSidebar.tr()),
                   child: FlowyIconButton(
                     width: 28,
+                    hoverColor: Colors.transparent,
                     onPressed: () => context
                         .read<HomeBloc>()
                         .add(const HomeEvent.collapseMenu()),
                     iconPadding: const EdgeInsets.fromLTRB(4, 4, 4, 4),
-                    icon: svgWidget("home/hide_menu", color: theme.iconColor),
-                  ))
-            ],
-          )),
+                    icon: svgWidget(
+                      "home/hide_menu",
+                      color: Theme.of(context).colorScheme.onSurface,
+                    ),
+                  ),
+                )
+              ],
+            ),
+          ),
         );
       },
     );

+ 4 - 3
frontend/app_flowy/lib/workspace/presentation/home/menu/menu_user.dart

@@ -5,7 +5,6 @@ import 'package:app_flowy/workspace/presentation/settings/widgets/settings_user_
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart' show UserProfilePB;
@@ -74,7 +73,6 @@ class MenuUser extends StatelessWidget {
   }
 
   Widget _renderSettingsButton(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     final userProfile = context.read<MenuUserBloc>().state.userProfile;
     return Tooltip(
       message: LocaleKeys.settings_menu_open.tr(),
@@ -90,7 +88,10 @@ class MenuUser extends StatelessWidget {
         },
         icon: SizedBox.square(
           dimension: 20,
-          child: svgWidget("home/settings", color: theme.iconColor),
+          child: svgWidget(
+            "home/settings",
+            color: Theme.of(context).colorScheme.onSurface,
+          ),
         ),
       ),
     );

+ 12 - 10
frontend/app_flowy/lib/workspace/presentation/home/navigation.dart

@@ -7,7 +7,6 @@ import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/notifier.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flutter/material.dart';
@@ -61,8 +60,6 @@ class FlowyNavigation extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
     return ChangeNotifierProxyProvider<HomeStackNotifier, NavigationNotifier>(
       create: (_) {
         final notifier = Provider.of<HomeStackNotifier>(context, listen: false);
@@ -77,7 +74,7 @@ class FlowyNavigation extends StatelessWidget {
           Selector<NavigationNotifier, PublishNotifier<bool>>(
               selector: (context, notifier) => notifier.collapasedNotifier,
               builder: (ctx, collapsedNotifier, child) =>
-                  _renderCollapse(ctx, collapsedNotifier, theme)),
+                  _renderCollapse(ctx, collapsedNotifier)),
           Selector<NavigationNotifier, List<NavigationItem>>(
             selector: (context, notifier) => notifier.navigationItems,
             builder: (ctx, items, child) => Expanded(
@@ -92,8 +89,8 @@ class FlowyNavigation extends StatelessWidget {
     );
   }
 
-  Widget _renderCollapse(BuildContext context,
-      PublishNotifier<bool> collapsedNotifier, AppTheme theme) {
+  Widget _renderCollapse(
+      BuildContext context, PublishNotifier<bool> collapsedNotifier) {
     return ChangeNotifierProvider.value(
       value: collapsedNotifier,
       child: Consumer(
@@ -102,15 +99,20 @@ class FlowyNavigation extends StatelessWidget {
             return RotationTransition(
               turns: const AlwaysStoppedAnimation(180 / 360),
               child: Tooltip(
-                  richMessage: sidebarTooltipTextSpan(),
+                  richMessage: sidebarTooltipTextSpan(
+                      LocaleKeys.sideBar_openSidebar.tr()),
                   child: FlowyIconButton(
                     width: 24,
+                    hoverColor: Colors.transparent,
                     onPressed: () {
                       notifier.value = false;
                       ctx.read<HomeBloc>().add(const HomeEvent.collapseMenu());
                     },
                     iconPadding: const EdgeInsets.fromLTRB(2, 2, 2, 2),
-                    icon: svgWidget("home/hide_menu", color: theme.iconColor),
+                    icon: svgWidget(
+                      "home/hide_menu",
+                      color: Theme.of(context).colorScheme.onSurface,
+                    ),
                   )),
             );
           } else {
@@ -195,10 +197,10 @@ class EllipsisNaviItem extends NavigationItem {
   NavigationCallback get action => (id) {};
 }
 
-TextSpan sidebarTooltipTextSpan() => TextSpan(
+TextSpan sidebarTooltipTextSpan(String hintText) => TextSpan(
       children: [
         TextSpan(
-          text: "${LocaleKeys.sideBar_openSidebar.tr()}\n",
+          text: "$hintText\n",
           style: TextStyles.caption,
         ),
         TextSpan(

+ 37 - 45
frontend/app_flowy/lib/workspace/presentation/settings/settings_dialog.dart

@@ -1,6 +1,5 @@
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/generated/locale_keys.g.dart';
-import 'package:app_flowy/workspace/application/appearance.dart';
 import 'package:app_flowy/workspace/presentation/settings/widgets/settings_appearance_view.dart';
 import 'package:app_flowy/workspace/presentation/settings/widgets/settings_language_view.dart';
 import 'package:app_flowy/workspace/presentation/settings/widgets/settings_user_view.dart';
@@ -12,7 +11,6 @@ import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:provider/provider.dart';
 
 class SettingsDialog extends StatelessWidget {
   final UserProfilePB user;
@@ -30,48 +28,42 @@ class SettingsDialog extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     return BlocProvider<SettingsDialogBloc>(
-        create: (context) => getIt<SettingsDialogBloc>(param1: user)
-          ..add(const SettingsDialogEvent.initial()),
-        child: BlocBuilder<SettingsDialogBloc, SettingsDialogState>(
-            builder: (context, state) => ChangeNotifierProvider.value(
-                  value: Provider.of<AppearanceSetting>(context, listen: true),
-                  child: FlowyDialog(
-                    title: FlowyText(
-                      LocaleKeys.settings_title.tr(),
-                      fontSize: 20,
-                      fontWeight: FontWeight.w700,
-                    ),
-                    child: Row(
-                      crossAxisAlignment: CrossAxisAlignment.start,
-                      children: [
-                        SizedBox(
-                          width: 200,
-                          child: SettingsMenu(
-                            changeSelectedIndex: (index) {
-                              context
-                                  .read<SettingsDialogBloc>()
-                                  .add(SettingsDialogEvent.setViewIndex(index));
-                            },
-                            currentIndex: context
-                                .read<SettingsDialogBloc>()
-                                .state
-                                .viewIndex,
-                          ),
-                        ),
-                        const VerticalDivider(),
-                        const SizedBox(width: 10),
-                        Expanded(
-                          child: getSettingsView(
-                            context.read<SettingsDialogBloc>().state.viewIndex,
-                            context
-                                .read<SettingsDialogBloc>()
-                                .state
-                                .userProfile,
-                          ),
-                        )
-                      ],
-                    ),
-                  ),
-                )));
+      create: (context) => getIt<SettingsDialogBloc>(param1: user)
+        ..add(const SettingsDialogEvent.initial()),
+      child: BlocBuilder<SettingsDialogBloc, SettingsDialogState>(
+        builder: (context, state) => FlowyDialog(
+          title: FlowyText(
+            LocaleKeys.settings_title.tr(),
+            fontSize: 20,
+            fontWeight: FontWeight.w700,
+          ),
+          child: Row(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              SizedBox(
+                width: 200,
+                child: SettingsMenu(
+                  changeSelectedIndex: (index) {
+                    context
+                        .read<SettingsDialogBloc>()
+                        .add(SettingsDialogEvent.setViewIndex(index));
+                  },
+                  currentIndex:
+                      context.read<SettingsDialogBloc>().state.viewIndex,
+                ),
+              ),
+              const VerticalDivider(),
+              const SizedBox(width: 10),
+              Expanded(
+                child: getSettingsView(
+                  context.read<SettingsDialogBloc>().state.viewIndex,
+                  context.read<SettingsDialogBloc>().state.userProfile,
+                ),
+              )
+            ],
+          ),
+        ),
+      ),
+    );
   }
 }

+ 5 - 9
frontend/app_flowy/lib/workspace/presentation/settings/widgets/settings_appearance_view.dart

@@ -4,7 +4,6 @@ import 'package:app_flowy/workspace/presentation/widgets/toggle/toggle_style.dar
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:textstyle_extensions/textstyle_extensions.dart';
@@ -16,8 +15,6 @@ class SettingsAppearanceView extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
     return SingleChildScrollView(
       child: Column(
         crossAxisAlignment: CrossAxisAlignment.start,
@@ -29,9 +26,9 @@ class SettingsAppearanceView extends StatelessWidget {
                 style: TextStyles.body1.size(FontSizes.s14),
               ),
               Toggle(
-                value: theme.isDark,
+                value: Theme.of(context).brightness == Brightness.dark,
                 onChanged: (_) => setTheme(context),
-                style: ToggleStyle.big(theme),
+                style: ToggleStyle.big,
               ),
               Text(
                 LocaleKeys.settings_appearance_darkLabel.tr(),
@@ -45,11 +42,10 @@ class SettingsAppearanceView extends StatelessWidget {
   }
 
   void setTheme(BuildContext context) {
-    final theme = context.read<AppTheme>();
-    if (theme.isDark) {
-      context.read<AppearanceSetting>().setTheme(ThemeType.light);
+    if (Theme.of(context).brightness == Brightness.dark) {
+      context.read<AppearanceSettingsCubit>().setTheme(Brightness.light);
     } else {
-      context.read<AppearanceSetting>().setTheme(ThemeType.dark);
+      context.read<AppearanceSettingsCubit>().setTheme(Brightness.dark);
     }
   }
 }

+ 20 - 27
frontend/app_flowy/lib/workspace/presentation/settings/widgets/settings_language_view.dart

@@ -3,10 +3,9 @@ import 'package:app_flowy/workspace/application/appearance.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flutter/material.dart';
 import 'package:flowy_infra/language.dart';
-import 'package:provider/provider.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:textstyle_extensions/textstyle_extensions.dart';
 
 class SettingsLanguageView extends StatelessWidget {
@@ -14,24 +13,20 @@ class SettingsLanguageView extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    context.watch<AppTheme>();
-    return ChangeNotifierProvider.value(
-      value: Provider.of<AppearanceSetting>(context, listen: true),
-      child: SingleChildScrollView(
-        child: Column(
-          crossAxisAlignment: CrossAxisAlignment.start,
-          children: [
-            Row(
-              children: [
-                Text(
-                  LocaleKeys.settings_menu_language.tr(),
-                  style: TextStyles.body1.size(FontSizes.s14),
-                ),
-                const LanguageSelectorDropdown(),
-              ],
-            ),
-          ],
-        ),
+    return SingleChildScrollView(
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.start,
+        children: [
+          Row(
+            children: [
+              Text(
+                LocaleKeys.settings_menu_language.tr(),
+                style: TextStyles.body1.size(FontSizes.s14),
+              ),
+              const LanguageSelectorDropdown(),
+            ],
+          ),
+        ],
       ),
     );
   }
@@ -49,7 +44,6 @@ class LanguageSelectorDropdown extends StatefulWidget {
 
 class _LanguageSelectorDropdownState extends State<LanguageSelectorDropdown> {
   Color currHoverColor = Colors.white.withOpacity(0.0);
-  late Color themedHoverColor;
   void hoverExitLanguage() {
     setState(() {
       currHoverColor = Colors.white.withOpacity(0.0);
@@ -58,15 +52,12 @@ class _LanguageSelectorDropdownState extends State<LanguageSelectorDropdown> {
 
   void hoverEnterLanguage() {
     setState(() {
-      currHoverColor = themedHoverColor;
+      currHoverColor = Theme.of(context).colorScheme.primary;
     });
   }
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-    themedHoverColor = theme.main2;
-
     return MouseRegion(
       onEnter: (event) => {hoverEnterLanguage()},
       onExit: (event) => {hoverExitLanguage()},
@@ -78,10 +69,12 @@ class _LanguageSelectorDropdownState extends State<LanguageSelectorDropdown> {
         ),
         child: DropdownButtonHideUnderline(
           child: DropdownButton<Locale>(
-            value: context.read<AppearanceSetting>().locale,
+            value: context.locale,
             onChanged: (val) {
               setState(() {
-                context.read<AppearanceSetting>().setLocale(context, val!);
+                context
+                    .read<AppearanceSettingsCubit>()
+                    .setLocale(context, val!);
               });
             },
             icon: const Visibility(

+ 6 - 6
frontend/app_flowy/lib/workspace/presentation/settings/widgets/settings_menu_element.dart

@@ -1,8 +1,6 @@
 import 'package:flowy_infra/size.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
 
 class SettingsMenuElement extends StatelessWidget {
   const SettingsMenuElement({
@@ -22,19 +20,21 @@ class SettingsMenuElement extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return ListTile(
       leading: Icon(
         icon,
         size: 16,
-        color: index == currentIndex ? Colors.black : theme.textColor,
+        color: index == currentIndex
+            ? Theme.of(context).colorScheme.onSurface
+            : Theme.of(context).colorScheme.onSurface,
       ),
       onTap: () {
         changeSelectedIndex(index);
       },
       selected: index == currentIndex,
-      selectedColor: Colors.black,
-      selectedTileColor: theme.main2,
+      selectedColor: Theme.of(context).colorScheme.onSurface,
+      selectedTileColor: Theme.of(context).colorScheme.primaryContainer,
+      hoverColor: Theme.of(context).colorScheme.primary,
       shape: RoundedRectangleBorder(
         borderRadius: BorderRadius.circular(5),
       ),

+ 9 - 9
frontend/app_flowy/lib/workspace/presentation/widgets/dialogs.dart

@@ -1,12 +1,10 @@
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/buttons/primary_button.dart';
 import 'package:flowy_infra_ui/widget/buttons/secondary_button.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
 import 'package:app_flowy/startup/tasks/app_widget.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra_ui/style_widget/text_input.dart';
@@ -43,13 +41,13 @@ class _CreateTextFieldDialog extends State<NavigatorTextFieldDialog> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return StyledDialog(
       child: Column(
         crossAxisAlignment: CrossAxisAlignment.start,
         children: <Widget>[
           ...[
-            FlowyText.medium(widget.title, color: theme.shader4),
+            FlowyText.medium(widget.title,
+                color: Theme.of(context).disabledColor),
             VSpace(Insets.sm * 1.5),
           ],
           FlowyFormTextInput(
@@ -111,14 +109,16 @@ class _CreateFlowyAlertDialog extends State<NavigatorAlertDialog> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return StyledDialog(
       child: Column(
         crossAxisAlignment: CrossAxisAlignment.start,
         mainAxisAlignment: MainAxisAlignment.center,
         children: <Widget>[
           ...[
-            FlowyText.medium(widget.title, color: theme.shader4),
+            FlowyText.medium(
+              widget.title,
+              color: Theme.of(context).disabledColor,
+            ),
           ],
           if (widget.confirm != null) ...[
             const VSpace(20),
@@ -158,16 +158,16 @@ class NavigatorOkCancelDialog extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return StyledDialog(
       maxWidth: maxWidth ?? 500,
       child: Column(
         crossAxisAlignment: CrossAxisAlignment.start,
         children: <Widget>[
           if (title != null) ...[
-            FlowyText.medium(title!.toUpperCase(), color: theme.shader1),
+            FlowyText.medium(title!.toUpperCase()),
             VSpace(Insets.sm * 1.5),
-            Container(color: theme.bg1, height: 1),
+            Container(
+                color: Theme.of(context).colorScheme.surfaceVariant, height: 1),
             VSpace(Insets.m * 1.5),
           ],
           FlowyText.medium(message, fontSize: FontSizes.s12),

+ 7 - 10
frontend/app_flowy/lib/workspace/presentation/widgets/float_bubble/question_bubble.dart

@@ -4,13 +4,11 @@ import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/size.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
-import 'package:provider/provider.dart';
 import 'package:styled_widget/styled_widget.dart';
 import 'package:package_info_plus/package_info_plus.dart';
 import 'package:url_launcher/url_launcher.dart';
@@ -35,8 +33,6 @@ class BubbleActionList extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
     final List<PopoverAction> actions = [];
     actions.addAll(
       BubbleAction.values.map((action) => BubbleActionWrapper(action)),
@@ -52,7 +48,7 @@ class BubbleActionList extends StatelessWidget {
           tooltip: LocaleKeys.questionBubble_help.tr(),
           fontSize: 12,
           fontWeight: FontWeight.w600,
-          fillColor: theme.selector,
+          fillColor: Theme.of(context).colorScheme.secondaryContainer,
           mainAxisAlignment: MainAxisAlignment.center,
           radius: BorderRadius.circular(10),
           onPressed: () => controller.show(),
@@ -122,8 +118,6 @@ class _DebugToast {
 class FlowyVersionDescription extends CustomActionCell {
   @override
   Widget buildWithContext(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
     return FutureBuilder(
       future: PackageInfo.fromPlatform(),
       builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
@@ -132,7 +126,7 @@ class FlowyVersionDescription extends CustomActionCell {
             return FlowyText(
               "Error: ${snapshot.error}",
               fontSize: FontSizes.s12,
-              color: theme.shader4,
+              color: Theme.of(context).disabledColor,
             );
           }
 
@@ -147,12 +141,15 @@ class FlowyVersionDescription extends CustomActionCell {
               mainAxisAlignment: MainAxisAlignment.start,
               crossAxisAlignment: CrossAxisAlignment.start,
               children: [
-                Divider(height: 1, color: theme.shader6, thickness: 1.0),
+                Divider(
+                    height: 1,
+                    color: Theme.of(context).dividerColor,
+                    thickness: 1.0),
                 const VSpace(6),
                 FlowyText(
                   "$appName $version.$buildNumber",
                   fontSize: FontSizes.s12,
-                  color: theme.shader4,
+                  color: Theme.of(context).hintColor,
                 ),
               ],
             ).padding(

+ 1 - 5
frontend/app_flowy/lib/workspace/presentation/widgets/pop_up_action.dart

@@ -1,11 +1,9 @@
 import 'package:appflowy_popover/appflowy_popover.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
 import 'package:styled_widget/styled_widget.dart';
 
 class PopoverActionList<T extends PopoverAction> extends StatefulWidget {
@@ -115,11 +113,9 @@ class ActionCellWidget<T extends PopoverAction> extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     final actionCell = action as ActionCell;
-    final theme = context.watch<AppTheme>();
-    final icon = actionCell.icon(theme.iconColor);
+    final icon = actionCell.icon(Theme.of(context).colorScheme.onSurface);
 
     return FlowyHover(
-      style: HoverStyle(hoverColor: theme.hover),
       child: GestureDetector(
         behavior: HitTestBehavior.opaque,
         onTap: () => onSelected(action),

+ 13 - 3
frontend/app_flowy/lib/workspace/presentation/widgets/toggle/toggle.dart

@@ -1,9 +1,13 @@
 import 'package:app_flowy/workspace/presentation/widgets/toggle/toggle_style.dart';
-import 'package:flutter/widgets.dart';
+import 'package:flowy_infra/color_extension.dart';
+import 'package:flutter/material.dart';
 
 class Toggle extends StatelessWidget {
   final ToggleStyle style;
   final bool value;
+  final Color? thumbColor;
+  final Color? activeBackgroundColor;
+  final Color? inactiveBackgroundColor;
   final void Function(bool) onChanged;
   final EdgeInsets padding;
 
@@ -12,11 +16,17 @@ class Toggle extends StatelessWidget {
     required this.value,
     required this.onChanged,
     required this.style,
+    this.thumbColor,
+    this.activeBackgroundColor,
+    this.inactiveBackgroundColor,
     this.padding = const EdgeInsets.all(8.0),
   }) : super(key: key);
 
   @override
   Widget build(BuildContext context) {
+    final backgroundColor = value
+        ? activeBackgroundColor ?? Theme.of(context).colorScheme.primary
+        : activeBackgroundColor ?? CustomColors.of(context).toggleOffFill;
     return GestureDetector(
       onTap: (() => onChanged(value)),
       child: Padding(
@@ -27,7 +37,7 @@ class Toggle extends StatelessWidget {
               height: style.height,
               width: style.width,
               decoration: BoxDecoration(
-                color: value ? style.activeBackgroundColor : style.inactiveBackgroundColor,
+                color: backgroundColor,
                 borderRadius: BorderRadius.circular(style.height / 2),
               ),
             ),
@@ -39,7 +49,7 @@ class Toggle extends StatelessWidget {
                 height: style.thumbRadius,
                 width: style.thumbRadius,
                 decoration: BoxDecoration(
-                  color: style.thumbColor,
+                  color: thumbColor ?? Theme.of(context).colorScheme.onPrimary,
                   borderRadius: BorderRadius.circular(style.thumbRadius / 2),
                 ),
               ),

+ 4 - 24
frontend/app_flowy/lib/workspace/presentation/widgets/toggle/toggle_style.dart

@@ -1,38 +1,18 @@
-import 'package:flowy_infra/theme.dart';
-import 'package:flutter/painting.dart';
-import 'package:flutter/widgets.dart';
-
 class ToggleStyle {
   final double height;
   final double width;
 
   final double thumbRadius;
-  final Color thumbColor;
-  final Color activeBackgroundColor;
-  final Color inactiveBackgroundColor;
 
   ToggleStyle({
     required this.height,
     required this.width,
     required this.thumbRadius,
-    required this.thumbColor,
-    required this.activeBackgroundColor,
-    required this.inactiveBackgroundColor,
   });
 
-  ToggleStyle.big(AppTheme theme)
-      : height = 16,
-        width = 27,
-        thumbRadius = 14,
-        activeBackgroundColor = theme.main1,
-        inactiveBackgroundColor = theme.shader5,
-        thumbColor = theme.surface;
+  static ToggleStyle get big =>
+      ToggleStyle(height: 16, width: 27, thumbRadius: 14);
 
-  ToggleStyle.small(AppTheme theme)
-      : height = 10,
-        width = 16,
-        thumbRadius = 8,
-        activeBackgroundColor = theme.main1,
-        inactiveBackgroundColor = theme.shader5,
-        thumbColor = theme.surface;
+  static ToggleStyle get small =>
+      ToggleStyle(height: 10, width: 16, thumbRadius: 8);
 }

+ 70 - 0
frontend/app_flowy/packages/flowy_infra/lib/color_extension.dart

@@ -0,0 +1,70 @@
+import 'package:flutter/material.dart';
+
+@immutable
+class CustomColors extends ThemeExtension<CustomColors> {
+  final Color? warning;
+  final Color? success;
+
+  static Color tint1 = const Color(0xffe8e0ff);
+  static Color tint2 = const Color(0xffffe7fd);
+  static Color tint3 = const Color(0xffffe7ee);
+  static Color tint4 = const Color(0xffffefe3);
+  static Color tint5 = const Color(0xfffff2cd);
+  static Color tint6 = const Color(0xfff5ffdc);
+  static Color tint7 = const Color(0xffddffd6);
+  static Color tint8 = const Color(0xffdefff1);
+  static Color tint9 = const Color(0xffe1fbff);
+
+  final Color greyHover;
+  final Color greySelect;
+  final Color lightGreyHover;
+  final Color toggleOffFill;
+
+  const CustomColors({
+    required this.warning,
+    required this.success,
+    required this.greyHover,
+    required this.greySelect,
+    required this.lightGreyHover,
+    required this.toggleOffFill,
+  });
+
+  static CustomColors of(BuildContext context) {
+    return Theme.of(context).extension<CustomColors>()!;
+  }
+
+  @override
+  CustomColors copyWith({
+    Color? warning,
+    Color? success,
+    Color? greyHover,
+    Color? greySelect,
+    Color? lightGreyHover,
+    Color? toggleOffFill,
+  }) {
+    return CustomColors(
+      warning: warning ?? this.warning,
+      success: success ?? this.success,
+      greyHover: greyHover ?? this.greyHover,
+      greySelect: greySelect ?? this.greySelect,
+      lightGreyHover: lightGreyHover ?? this.lightGreyHover,
+      toggleOffFill: toggleOffFill ?? this.toggleOffFill,
+    );
+  }
+
+  @override
+  ThemeExtension<CustomColors> lerp(
+      ThemeExtension<CustomColors>? other, double t) {
+    if (other is! CustomColors) {
+      return this;
+    }
+    return CustomColors(
+      warning: Color.lerp(warning, other.warning, t),
+      success: Color.lerp(success, other.success, t),
+      greyHover: Color.lerp(greyHover, other.greyHover, t)!,
+      greySelect: Color.lerp(greySelect, other.greySelect, t)!,
+      lightGreyHover: Color.lerp(lightGreyHover, other.lightGreyHover, t)!,
+      toggleOffFill: Color.lerp(toggleOffFill, other.toggleOffFill, t)!,
+    );
+  }
+}

+ 66 - 47
frontend/app_flowy/packages/flowy_infra/lib/theme.dart

@@ -1,35 +1,32 @@
 import 'package:flutter/material.dart';
 
-enum ThemeType {
-  light,
-  dark,
-}
+import 'color_extension.dart';
 
-ThemeType themeTypeFromString(String name) {
-  ThemeType themeType = ThemeType.light;
+Brightness themeTypeFromString(String name) {
+  Brightness themeType = Brightness.light;
   if (name == "dark") {
-    themeType = ThemeType.dark;
+    themeType = Brightness.dark;
   }
   return themeType;
 }
 
-String themeTypeToString(ThemeType ty) {
-  switch (ty) {
-    case ThemeType.light:
+String themeTypeToString(Brightness brightness) {
+  switch (brightness) {
+    case Brightness.light:
       return "light";
-    case ThemeType.dark:
+    case Brightness.dark:
       return "dark";
   }
 }
 
-//Color Pallettes
+// Color Pallettes
 const _black = Color(0xff000000);
 const _white = Color(0xFFFFFFFF);
 
 class AppTheme {
-  ThemeType ty;
-  bool isDark;
-  late Color surface; //
+  Brightness brightness;
+
+  late Color surface;
   late Color hover;
   late Color selector;
   late Color red;
@@ -58,6 +55,7 @@ class AppTheme {
   late Color tint7;
   late Color tint8;
   late Color tint9;
+
   late Color textColor;
   late Color iconColor;
   late Color disableIconColor;
@@ -65,22 +63,22 @@ class AppTheme {
   late Color main1;
   late Color main2;
 
-  late Color shadowColor;
+  late Color shadow;
 
   /// Default constructor
-  AppTheme({required this.ty, this.isDark = false});
+  AppTheme({this.brightness = Brightness.light});
 
   factory AppTheme.fromName({required String name}) {
     return AppTheme.fromType(themeTypeFromString(name));
   }
 
   /// fromType factory constructor
-  factory AppTheme.fromType(ThemeType themeType) {
+  factory AppTheme.fromType(Brightness themeType) {
     switch (themeType) {
-      case ThemeType.light:
-        return AppTheme(ty: themeType, isDark: false)
+      case Brightness.light:
+        return AppTheme(brightness: Brightness.light)
           ..surface = Colors.white
-          ..hover = const Color(0xFFe0f8ff) //
+          ..hover = const Color(0xFFe0f8ff)
           ..selector = const Color(0xfff2fcff)
           ..red = const Color(0xfffb006d)
           ..yellow = const Color(0xffffd667)
@@ -109,11 +107,11 @@ class AppTheme {
           ..main2 = const Color(0xff00b7ea)
           ..textColor = _black
           ..iconColor = _black
-          ..shadowColor = _black
+          ..shadow = _black
           ..disableIconColor = const Color(0xffbdbdbd);
 
-      case ThemeType.dark:
-        return AppTheme(ty: themeType, isDark: true)
+      case Brightness.dark:
+        return AppTheme(brightness: Brightness.dark)
           ..surface = const Color(0xff292929)
           ..hover = const Color(0xff1f1f1f)
           ..selector = const Color(0xff333333)
@@ -144,44 +142,65 @@ class AppTheme {
           ..main2 = const Color(0xff009cc7)
           ..textColor = _white
           ..iconColor = _white
-          ..shadowColor = _white
+          ..shadow = _black
           ..disableIconColor = const Color(0xff333333);
     }
   }
 
   ThemeData get themeData {
-    var t = ThemeData(
-      textTheme: TextTheme(bodyText2: TextStyle(color: textColor)),
+    return ThemeData(
+      brightness: brightness,
+      textTheme: TextTheme(bodyText2: TextStyle(color: shader1)),
       textSelectionTheme: TextSelectionThemeData(
           cursorColor: main2, selectionHandleColor: main2),
       primaryIconTheme: IconThemeData(color: hover),
       iconTheme: IconThemeData(color: shader1),
+      scrollbarTheme: ScrollbarThemeData(
+        thumbColor: MaterialStateProperty.all(Colors.transparent),
+      ),
+      materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
       canvasColor: shader6,
-      //Don't use this property because of the redo/undo button in the toolbar use the hoverColor.
-      // hoverColor: main2,
+      dividerColor: shader6,
+      hintColor: shader3,
+      disabledColor: shader4,
+      highlightColor: main1,
+      indicatorColor: main1,
+      toggleableActiveColor: main1,
       colorScheme: ColorScheme(
-          brightness: isDark ? Brightness.dark : Brightness.light,
-          primary: main1,
-          secondary: main2,
-          background: surface,
-          surface: surface,
-          onBackground: surface,
-          onSurface: surface,
-          onError: red,
-          onPrimary: bg1,
-          onSecondary: bg1,
-          error: red),
+        brightness: brightness,
+        primary: main1,
+        onPrimary: shader7,
+        primaryContainer: main2,
+        onPrimaryContainer: shader7,
+        secondary: hover,
+        onSecondary: shader1,
+        secondaryContainer: selector,
+        onSecondaryContainer: shader1,
+        background: surface,
+        onBackground: shader1,
+        surface: surface,
+        onSurface: shader1,
+        onError: shader7,
+        error: red,
+        outline: shader4,
+        surfaceVariant: bg1,
+        shadow: shadow,
+      ),
+      extensions: [
+        CustomColors(
+          warning: yellow,
+          success: green,
+          greyHover: bg2,
+          greySelect: bg3,
+          lightGreyHover: shader6,
+          toggleOffFill: shader5,
+        )
+      ],
     );
-
-    return t.copyWith(
-        materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
-        highlightColor: main1,
-        indicatorColor: main1,
-        toggleableActiveColor: main1);
   }
 
   Color shift(Color c, double d) =>
-      ColorUtils.shiftHsl(c, d * (isDark ? -1 : 1));
+      ColorUtils.shiftHsl(c, d * (brightness == Brightness.dark ? -1 : 1));
 }
 
 class ColorUtils {

+ 2 - 5
frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/appflowy_popover.dart

@@ -1,9 +1,7 @@
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:flutter/material.dart';
 
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/decoration.dart';
-import 'package:provider/provider.dart';
 
 class AppFlowyPopover extends StatelessWidget {
   final Widget child;
@@ -69,10 +67,9 @@ class _PopoverContainer extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     final decoration = FlowyDecoration.decoration(
-      theme.surface,
-      theme.shadowColor.withOpacity(0.15),
+      Theme.of(context).colorScheme.surface,
+      Theme.of(context).colorScheme.shadow.withOpacity(0.15),
     );
 
     return Material(

+ 2 - 6
frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/list_overlay.dart

@@ -2,9 +2,7 @@ import 'dart:math';
 
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flutter/material.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/decoration.dart';
-import 'package:provider/provider.dart';
 
 class ListOverlayFooter {
   Widget widget;
@@ -124,15 +122,13 @@ class OverlayContainer extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme =
-        context.watch<AppTheme?>() ?? AppTheme.fromType(ThemeType.light);
     return Material(
       type: MaterialType.transparency,
       child: Container(
         padding: padding,
         decoration: FlowyDecoration.decoration(
-          theme.surface,
-          theme.shadowColor.withOpacity(0.15),
+          Theme.of(context).colorScheme.surface,
+          Theme.of(context).colorScheme.shadow.withOpacity(0.15),
         ),
         constraints: constraints,
         child: child,

+ 4 - 4
frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart

@@ -12,7 +12,7 @@ class FlowyButton extends StatelessWidget {
   final EdgeInsets margin;
   final Widget? leftIcon;
   final Widget? rightIcon;
-  final Color hoverColor;
+  final Color? hoverColor;
   final bool isSelected;
   final BorderRadius radius;
 
@@ -24,7 +24,7 @@ class FlowyButton extends StatelessWidget {
     this.margin = const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
     this.leftIcon,
     this.rightIcon,
-    this.hoverColor = Colors.transparent,
+    this.hoverColor,
     this.isSelected = false,
     this.radius = const BorderRadius.all(Radius.circular(6)),
   }) : super(key: key);
@@ -37,7 +37,7 @@ class FlowyButton extends StatelessWidget {
       child: FlowyHover(
         style: HoverStyle(
           borderRadius: radius,
-          hoverColor: hoverColor,
+          hoverColor: hoverColor ?? Theme.of(context).colorScheme.secondary,
         ),
         onHover: onHover,
         isSelected: () => isSelected,
@@ -138,7 +138,7 @@ class FlowyTextButton extends StatelessWidget {
       shape: RoundedRectangleBorder(
           borderRadius: radius ?? BorderRadius.circular(2)),
       fillColor: fillColor,
-      hoverColor: hoverColor ?? Colors.transparent,
+      hoverColor: hoverColor ?? Theme.of(context).colorScheme.secondary,
       focusColor: Colors.transparent,
       splashColor: Colors.transparent,
       highlightColor: Colors.transparent,

+ 16 - 13
frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/hover.dart

@@ -5,7 +5,7 @@ import 'package:flowy_infra/time/duration.dart';
 typedef HoverBuilder = Widget Function(BuildContext context, bool onHover);
 
 class FlowyHover extends StatefulWidget {
-  final HoverStyle style;
+  final HoverStyle? style;
   final HoverBuilder? builder;
   final Widget? child;
 
@@ -25,7 +25,7 @@ class FlowyHover extends StatefulWidget {
     Key? key,
     this.builder,
     this.child,
-    required this.style,
+    this.style,
     this.isSelected,
     this.onHover,
     this.cursor,
@@ -82,13 +82,15 @@ class _FlowyHoverState extends State<FlowyHover> {
     }
 
     final child = widget.child ?? widget.builder!(context, _onHover);
+    final style = widget.style ??
+        HoverStyle(hoverColor: Theme.of(context).colorScheme.secondary);
     if (showHover) {
       return FlowyHoverContainer(
-        style: widget.style,
+        style: style,
         child: child,
       );
     } else {
-      return Container(color: widget.style.backgroundColor, child: child);
+      return Container(color: style.backgroundColor, child: child);
     }
   }
 }
@@ -96,18 +98,19 @@ class _FlowyHoverState extends State<FlowyHover> {
 class HoverStyle {
   final Color borderColor;
   final double borderWidth;
-  final Color hoverColor;
+  final Color? hoverColor;
   final BorderRadius borderRadius;
   final EdgeInsets contentMargin;
   final Color backgroundColor;
 
-  const HoverStyle(
-      {this.borderColor = Colors.transparent,
-      this.borderWidth = 0,
-      this.borderRadius = const BorderRadius.all(Radius.circular(6)),
-      this.contentMargin = EdgeInsets.zero,
-      this.backgroundColor = Colors.transparent,
-      required this.hoverColor});
+  const HoverStyle({
+    this.borderColor = Colors.transparent,
+    this.borderWidth = 0,
+    this.borderRadius = const BorderRadius.all(Radius.circular(6)),
+    this.contentMargin = EdgeInsets.zero,
+    this.backgroundColor = Colors.transparent,
+    this.hoverColor,
+  });
 }
 
 class FlowyHoverContainer extends StatelessWidget {
@@ -131,7 +134,7 @@ class FlowyHoverContainer extends StatelessWidget {
       margin: style.contentMargin,
       decoration: BoxDecoration(
         border: hoverBorder,
-        color: style.hoverColor,
+        color: style.hoverColor ?? Theme.of(context).colorScheme.secondary,
         borderRadius: style.borderRadius,
       ),
       child: child,

+ 8 - 5
frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/icon_button.dart

@@ -20,7 +20,7 @@ class FlowyIconButton extends StatelessWidget {
     this.height,
     this.onPressed,
     this.fillColor = Colors.transparent,
-    this.hoverColor = Colors.transparent,
+    this.hoverColor,
     this.iconPadding = EdgeInsets.zero,
     this.radius,
     this.tooltipText,
@@ -35,11 +35,13 @@ class FlowyIconButton extends StatelessWidget {
     assert(size.width > iconPadding.horizontal);
     assert(size.height > iconPadding.vertical);
 
-    final childWidth = min(size.width - iconPadding.horizontal, size.height - iconPadding.vertical);
+    final childWidth = min(size.width - iconPadding.horizontal,
+        size.height - iconPadding.vertical);
     final childSize = Size(childWidth, childWidth);
 
     return ConstrainedBox(
-      constraints: BoxConstraints.tightFor(width: size.width, height: size.height),
+      constraints:
+          BoxConstraints.tightFor(width: size.width, height: size.height),
       child: Tooltip(
         message: tooltipText ?? '',
         showDuration: Duration.zero,
@@ -47,9 +49,10 @@ class FlowyIconButton extends StatelessWidget {
           visualDensity: VisualDensity.compact,
           hoverElevation: 0,
           highlightElevation: 0,
-          shape: RoundedRectangleBorder(borderRadius: radius ?? BorderRadius.circular(2)),
+          shape: RoundedRectangleBorder(
+              borderRadius: radius ?? BorderRadius.circular(2)),
           fillColor: fillColor,
-          hoverColor: hoverColor,
+          hoverColor: hoverColor ?? Theme.of(context).colorScheme.secondary,
           focusColor: Colors.transparent,
           splashColor: Colors.transparent,
           highlightColor: Colors.transparent,

+ 7 - 7
frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart

@@ -1,11 +1,10 @@
 import 'dart:math';
 import 'dart:async';
 import 'package:async/async.dart';
+import 'package:flowy_infra/color_extension.dart';
 import 'package:flowy_infra/size.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/widget/mouse_hover_builder.dart';
 import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
 import 'package:styled_widget/styled_widget.dart';
 
 class StyledScrollbar extends StatefulWidget {
@@ -83,7 +82,6 @@ class ScrollbarState extends State<StyledScrollbar> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return LayoutBuilder(
       builder: (_, BoxConstraints constraints) {
         double maxExtent;
@@ -139,12 +137,14 @@ class ScrollbarState extends State<StyledScrollbar> {
 
         // Handle color
         var handleColor = widget.handleColor ??
-            (theme.isDark ? theme.bg2.withOpacity(.2) : theme.bg2);
+            (Theme.of(context).brightness == Brightness.dark
+                ? CustomColors.of(context).greyHover.withOpacity(.2)
+                : CustomColors.of(context).greyHover);
         // Track color
         var trackColor = widget.trackColor ??
-            (theme.isDark
-                ? theme.bg2.withOpacity(.1)
-                : theme.bg2.withOpacity(.3));
+            (Theme.of(context).brightness == Brightness.dark
+                ? CustomColors.of(context).greyHover.withOpacity(.1)
+                : CustomColors.of(context).greyHover.withOpacity(.3));
 
         //Layout the stack, it just contains a child, and
         return Stack(children: <Widget>[

+ 1 - 4
frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/text.dart

@@ -1,7 +1,5 @@
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
 
 class FlowyText extends StatelessWidget {
   final String title;
@@ -58,7 +56,6 @@ class FlowyText extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return Text(
       title,
       maxLines: maxLines,
@@ -67,7 +64,7 @@ class FlowyText extends StatelessWidget {
       style: TextStyles.general(
         fontSize: fontSize,
         fontWeight: fontWeight,
-        color: color ?? theme.textColor,
+        color: color,
       ),
     );
   }

+ 3 - 5
frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/text_input.dart

@@ -2,10 +2,8 @@ import 'dart:async';
 import 'dart:math' as math;
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
-import 'package:provider/provider.dart';
 // ignore: import_of_legacy_library_into_null_safe
 import 'package:textstyle_extensions/textstyle_extensions.dart';
 
@@ -184,7 +182,6 @@ class StyledSearchTextInputState extends State<StyledSearchTextInput> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return Container(
       padding: EdgeInsets.symmetric(vertical: Insets.sm),
       child: TextFormField(
@@ -200,7 +197,7 @@ class StyledSearchTextInputState extends State<StyledSearchTextInput> {
         autocorrect: widget.autoCorrect ?? false,
         enableSuggestions: widget.enableSuggestions ?? false,
         style: widget.style ?? TextStyles.body1,
-        cursorColor: theme.main1,
+        cursorColor: Theme.of(context).colorScheme.primary,
         controller: _controller,
         showCursor: true,
         enabled: widget.enabled,
@@ -218,7 +215,8 @@ class StyledSearchTextInputState extends State<StyledSearchTextInput> {
                 errorText: widget.errorText,
                 errorMaxLines: 2,
                 hintText: widget.hintText,
-                hintStyle: TextStyles.body1.textColor(theme.shader4),
+                hintStyle:
+                    TextStyles.body1.textColor(Theme.of(context).hintColor),
                 labelText: widget.label),
       ),
     );

+ 17 - 15
frontend/app_flowy/packages/flowy_infra_ui/lib/widget/buttons/base_styled_button.dart

@@ -1,8 +1,6 @@
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/text_style.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
 
 class BaseStyledButton extends StatefulWidget {
   final Widget child;
@@ -72,23 +70,25 @@ class BaseStyledBtnState extends State<BaseStyledButton> {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return Container(
       decoration: BoxDecoration(
-        color: widget.bgColor ?? theme.surface,
+        color: widget.bgColor ?? Theme.of(context).colorScheme.surface,
         borderRadius: widget.borderRadius ?? Corners.s10Border,
         boxShadow: _isFocused
             ? [
                 BoxShadow(
-                    color: theme.shader6,
-                    offset: Offset.zero,
-                    blurRadius: 8.0,
-                    spreadRadius: 0.0),
+                  color: Theme.of(context).colorScheme.shadow,
+                  offset: Offset.zero,
+                  blurRadius: 8.0,
+                  spreadRadius: 0.0,
+                ),
                 BoxShadow(
-                    color: widget.bgColor ?? theme.surface,
-                    offset: Offset.zero,
-                    blurRadius: 8.0,
-                    spreadRadius: -4.0),
+                  color:
+                      widget.bgColor ?? Theme.of(context).colorScheme.surface,
+                  offset: Offset.zero,
+                  blurRadius: 8.0,
+                  spreadRadius: -4.0,
+                ),
               ]
             : [],
       ),
@@ -97,7 +97,7 @@ class BaseStyledBtnState extends State<BaseStyledButton> {
               shape: RoundedRectangleBorder(
                 side: BorderSide(
                   width: 1.8,
-                  color: theme.shader6,
+                  color: Theme.of(context).colorScheme.outline,
                 ),
                 borderRadius: widget.borderRadius ?? Corners.s10Border,
               ),
@@ -116,8 +116,10 @@ class BaseStyledBtnState extends State<BaseStyledButton> {
         highlightElevation: 0,
         focusElevation: 0,
         fillColor: Colors.transparent,
-        hoverColor: widget.hoverColor ?? theme.hover,
-        highlightColor: widget.downColor ?? theme.main1,
+        hoverColor:
+            widget.hoverColor ?? Theme.of(context).colorScheme.secondary,
+        highlightColor:
+            widget.downColor ?? Theme.of(context).colorScheme.primary,
         focusColor: widget.focusColor ?? Colors.grey.withOpacity(0.35),
         constraints: BoxConstraints(
             minHeight: widget.minHeight ?? 0, minWidth: widget.minWidth ?? 0),

+ 4 - 8
frontend/app_flowy/packages/flowy_infra_ui/lib/widget/buttons/primary_button.dart

@@ -1,8 +1,6 @@
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
 import 'package:flowy_infra/size.dart';
-import 'package:flowy_infra/theme.dart';
 import 'base_styled_button.dart';
 
 class PrimaryTextButton extends StatelessWidget {
@@ -16,13 +14,12 @@ class PrimaryTextButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return PrimaryButton(
       bigMode: bigMode,
       onPressed: onPressed,
       child: FlowyText.regular(
         label,
-        color: theme.surface,
+        color: Theme.of(context).colorScheme.onPrimary,
       ),
     );
   }
@@ -39,14 +36,13 @@ class PrimaryButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return BaseStyledButton(
       minWidth: bigMode ? 100 : 80,
       minHeight: bigMode ? 40 : 38,
       contentPadding: EdgeInsets.zero,
-      bgColor: theme.main1,
-      hoverColor: theme.main1,
-      downColor: theme.main1,
+      bgColor: Theme.of(context).colorScheme.primary,
+      hoverColor: Theme.of(context).colorScheme.primaryContainer,
+      downColor: Theme.of(context).colorScheme.primary,
       borderRadius: bigMode ? Corners.s12Border : Corners.s8Border,
       onPressed: onPressed,
       child: child,

+ 5 - 9
frontend/app_flowy/packages/flowy_infra_ui/lib/widget/buttons/secondary_button.dart

@@ -1,9 +1,7 @@
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
 // ignore: import_of_legacy_library_into_null_safe
 import 'package:flowy_infra/size.dart';
-import 'package:flowy_infra/theme.dart';
 import 'base_styled_button.dart';
 
 class SecondaryTextButton extends StatelessWidget {
@@ -17,13 +15,12 @@ class SecondaryTextButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return SecondaryButton(
       bigMode: bigMode,
       onPressed: onPressed,
       child: FlowyText.regular(
         label,
-        color: theme.main1,
+        color: Theme.of(context).colorScheme.primary,
       ),
     );
   }
@@ -40,15 +37,14 @@ class SecondaryButton extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
     return BaseStyledButton(
       minWidth: bigMode ? 100 : 80,
       minHeight: bigMode ? 40 : 38,
       contentPadding: EdgeInsets.zero,
-      bgColor: theme.shader7,
-      hoverColor: theme.hover,
-      downColor: theme.main1,
-      outlineColor: theme.main1,
+      bgColor: Theme.of(context).colorScheme.surface,
+      hoverColor: Theme.of(context).colorScheme.secondary,
+      downColor: Theme.of(context).colorScheme.primary,
+      outlineColor: Theme.of(context).colorScheme.primary,
       borderRadius: bigMode ? Corners.s12Border : Corners.s8Border,
       onPressed: onPressed,
       child: child,

+ 1 - 5
frontend/app_flowy/packages/flowy_infra_ui/lib/widget/dialog/styled_dialogs.dart

@@ -1,10 +1,8 @@
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra/size.dart';
-import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/widget/dialog/dialog_size.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
-import 'package:provider/provider.dart';
 import 'dart:ui';
 
 extension IntoDialog on Widget {
@@ -50,11 +48,9 @@ class StyledDialog extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    final theme = context.watch<AppTheme>();
-
     Widget innerContent = Container(
       padding: padding ?? EdgeInsets.all(Insets.lGutter),
-      color: bgColor ?? theme.shader7,
+      color: bgColor ?? Theme.of(context).colorScheme.surface,
       child: child,
     );
 

+ 3 - 3
frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_button.dart

@@ -9,7 +9,7 @@ class RoundedTextButton extends StatelessWidget {
   final double? height;
   final BorderRadius borderRadius;
   final Color borderColor;
-  final Color color;
+  final Color? color;
   final Color textColor;
   final double fontSize;
 
@@ -21,7 +21,7 @@ class RoundedTextButton extends StatelessWidget {
     this.height,
     this.borderRadius = Corners.s12Border,
     this.borderColor = Colors.transparent,
-    this.color = Colors.transparent,
+    this.color,
     this.textColor = Colors.white,
     this.fontSize = 16,
   }) : super(key: key);
@@ -39,7 +39,7 @@ class RoundedTextButton extends StatelessWidget {
         decoration: BoxDecoration(
           border: Border.all(color: borderColor),
           borderRadius: borderRadius,
-          color: color,
+          color: color ?? Theme.of(context).colorScheme.primary,
         ),
         child: SizedBox.expand(
           child: TextButton(

+ 14 - 11
frontend/app_flowy/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart

@@ -11,9 +11,9 @@ class RoundedInputField extends StatefulWidget {
   final bool obscureText;
   final Widget? obscureIcon;
   final Widget? obscureHideIcon;
-  final Color normalBorderColor;
-  final Color errorBorderColor;
-  final Color cursorColor;
+  final Color? normalBorderColor;
+  final Color? errorBorderColor;
+  final Color? cursorColor;
   final Color? focusBorderColor;
   final String errorText;
   final TextStyle style;
@@ -39,10 +39,10 @@ class RoundedInputField extends StatefulWidget {
     this.obscureHideIcon,
     this.onChanged,
     this.onEditingComplete,
-    this.normalBorderColor = Colors.transparent,
-    this.errorBorderColor = Colors.transparent,
+    this.normalBorderColor,
+    this.errorBorderColor,
     this.focusBorderColor,
-    this.cursorColor = Colors.black,
+    this.cursorColor,
     this.style = const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
     this.margin = EdgeInsets.zero,
     this.padding = EdgeInsets.zero,
@@ -76,11 +76,13 @@ class _RoundedInputFieldState extends State<RoundedInputField> {
 
   @override
   Widget build(BuildContext context) {
-    var borderColor = widget.normalBorderColor;
-    var focusBorderColor = widget.focusBorderColor ?? borderColor;
+    var borderColor =
+        widget.normalBorderColor ?? Theme.of(context).colorScheme.outline;
+    var focusBorderColor =
+        widget.focusBorderColor ?? Theme.of(context).colorScheme.primary;
 
     if (widget.errorText.isNotEmpty) {
-      borderColor = widget.errorBorderColor;
+      borderColor = Theme.of(context).colorScheme.error;
       focusBorderColor = borderColor;
     }
 
@@ -109,13 +111,14 @@ class _RoundedInputFieldState extends State<RoundedInputField> {
               widget.onEditingComplete!(inputText);
             }
           },
-          cursorColor: widget.cursorColor,
+          cursorColor:
+              widget.cursorColor ?? Theme.of(context).colorScheme.primary,
           obscureText: obscuteText,
           style: widget.style,
           decoration: InputDecoration(
             contentPadding: widget.contentPadding,
             hintText: widget.hintText,
-            hintStyle: TextStyles.body1.textColor(widget.normalBorderColor),
+            hintStyle: TextStyles.body1.textColor(borderColor),
             enabledBorder: OutlineInputBorder(
               borderSide: BorderSide(
                 color: borderColor,

+ 35 - 24
frontend/app_flowy/test/bloc_test/app_setting_test/appearance_test.dart

@@ -1,6 +1,8 @@
 import 'package:app_flowy/user/application/user_settings_service.dart';
 import 'package:app_flowy/workspace/application/appearance.dart';
-import 'package:flowy_infra/theme.dart';
+import 'package:bloc_test/bloc_test.dart';
+import 'package:flowy_sdk/protobuf/flowy-user/user_setting.pb.dart';
+import 'package:flutter/material.dart';
 import 'package:flutter_test/flutter_test.dart';
 
 import '../../util.dart';
@@ -12,32 +14,41 @@ void main() {
     context = await AppFlowyUnitTest.ensureInitialized();
   });
 
-  group('$AppearanceSetting', () {
-    late AppearanceSetting appearanceSetting;
+  group('$AppearanceSettingsCubit', () {
+    late AppearanceSettingsPB appearanceSetting;
     setUp(() async {
-      final setting = await SettingsFFIService().getAppearanceSetting();
-      appearanceSetting = AppearanceSetting(setting);
+      appearanceSetting = await SettingsFFIService().getAppearanceSetting();
       await blocResponseFuture();
     });
 
-    test('default theme', () {
-      expect(appearanceSetting.theme.ty, ThemeType.light);
-    });
-
-    test('save key/value', () async {
-      appearanceSetting.setKeyValue("123", "456");
-    });
-
-    test('read key/value', () {
-      expect(appearanceSetting.getValue("123"), "456");
-    });
-
-    test('remove key/value', () {
-      appearanceSetting.setKeyValue("123", null);
-    });
-
-    test('read key/value', () {
-      expect(appearanceSetting.getValue("123"), null);
-    });
+    blocTest<AppearanceSettingsCubit, AppearanceSettingsState>(
+      'default theme',
+      build: () => AppearanceSettingsCubit(appearanceSetting),
+      verify: (bloc) {
+        expect(bloc.state.theme.brightness, Brightness.light);
+      },
+    );
+
+    blocTest<AppearanceSettingsCubit, AppearanceSettingsState>(
+      'save key/value',
+      build: () => AppearanceSettingsCubit(appearanceSetting),
+      act: (bloc) {
+        bloc.setKeyValue("123", "456");
+      },
+      verify: (bloc) {
+        expect(bloc.getValue("123"), "456");
+      },
+    );
+
+    blocTest<AppearanceSettingsCubit, AppearanceSettingsState>(
+      'remove key/value',
+      build: () => AppearanceSettingsCubit(appearanceSetting),
+      act: (bloc) {
+        bloc.setKeyValue("123", null);
+      },
+      verify: (bloc) {
+        expect(bloc.getValue("123"), null);
+      },
+    );
   });
 }

+ 15 - 15
frontend/app_flowy/test/bloc_test/grid_test/grid_bloc_test.dart

@@ -12,7 +12,7 @@ void main() {
 
   group('Create a new row in Grid', () {
     blocTest<GridBloc, GridState>(
-      "Create a row",
+      "create a row",
       build: () =>
           GridBloc(view: gridTest.gridView)..add(const GridEvent.initial()),
       act: (bloc) => bloc.add(const GridEvent.createRow()),
@@ -21,20 +21,20 @@ void main() {
         assert(bloc.state.rowInfos.length == 4);
       },
     );
-  });
-
-  group('Delete a row in the grid', () {
-    late GridBloc gridBloc;
-    setUpAll(() async {
-      gridBloc = GridBloc(view: gridTest.gridView)
-        ..add(const GridEvent.initial());
-      await gridResponseFuture();
-    });
 
-    test('delete the last row', () async {
-      gridBloc.add(GridEvent.deleteRow(gridBloc.state.rowInfos.last));
-      await gridResponseFuture();
-      assert(gridBloc.state.rowInfos.length == 3);
-    });
+    blocTest<GridBloc, GridState>(
+      "delete the last row",
+      build: () =>
+          GridBloc(view: gridTest.gridView)..add(const GridEvent.initial()),
+      act: (bloc) async {
+        await gridResponseFuture();
+        bloc.add(GridEvent.deleteRow(bloc.state.rowInfos.last));
+      },
+      wait: const Duration(milliseconds: 300),
+      verify: (bloc) {
+        assert(bloc.state.rowInfos.length == 2,
+            "Expected 2, but receive ${bloc.state.rowInfos.length}");
+      },
+    );
   });
 }

+ 1 - 1
frontend/app_flowy/test/widget_test/select_option_text_field_test.dart

@@ -41,7 +41,7 @@ void main() {
         MaterialApp(
           home: Material(
             child: Provider<AppTheme>.value(
-              value: AppTheme.fromType(ThemeType.light),
+              value: AppTheme.fromType(Brightness.light),
               child: textField,
             ),
           ),