From d05b633b9b85181443c51311610fd065d56a82ab Mon Sep 17 00:00:00 2001 From: "Lucas.Xu" Date: Wed, 27 Dec 2023 20:29:14 +0800 Subject: [PATCH] feat: improve toolbar dark mode (#4218) --- .../mobile_toolbar_v3/_align_items.dart | 10 +- .../mobile_toolbar_v3/_bius_items.dart | 8 +- .../mobile_toolbar_v3/_block_items.dart | 21 +- .../mobile_toolbar_v3/_color_item.dart | 6 +- .../mobile_toolbar_v3/_color_list.dart | 7 +- .../mobile_toolbar_v3/_font_item.dart | 6 +- .../_heading_and_text_items.dart | 2 +- .../mobile_toolbar_v3/_indent_items.dart | 10 +- .../mobile_toolbar_v3/_menu_item.dart | 25 ++- .../mobile_toolbar_v3/_popup_menu.dart | 17 +- .../mobile_toolbar_v3/_toolbar_theme.dart | 182 ++++++++++++++++++ .../mobile_toolbar_v3/aa_toolbar_item.dart | 8 +- .../appflowy_mobile_toolbar.dart | 16 +- .../appflowy_mobile_toolbar_item.dart | 5 +- .../undo_redo_toolbar_item.dart | 12 +- .../mobile_toolbar_v3/util.dart | 19 +- .../appearance/mobile_appearance.dart | 2 + 17 files changed, 295 insertions(+), 61 deletions(-) create mode 100644 frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_align_items.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_align_items.dart index fc34bde4f5..3b878e784c 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_align_items.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_align_items.dart @@ -1,6 +1,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_menu_item.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_popup_menu.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/util.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:collection/collection.dart'; @@ -23,6 +24,7 @@ class AlignItems extends StatelessWidget { Widget build(BuildContext context) { final currentAlignItem = _getCurrentAlignItem(); final alignMenuItems = _getAlignMenuItems(); + final theme = ToolbarColorExtension.of(context); return PopupMenu( itemLength: alignMenuItems.length, onSelected: (index) { @@ -38,7 +40,7 @@ class AlignItems extends StatelessWidget { final children = alignMenuItems .mapIndexed( (index, e) => [ - MenuItem( + PopupMenuItemWrapper( key: keys[index], isSelected: currentIndex == index, icon: e.$2, @@ -49,14 +51,14 @@ class AlignItems extends StatelessWidget { ) .flattened .toList(); - return MenuWrapper( + return PopupMenuWrapper( child: Row( mainAxisSize: MainAxisSize.min, children: children, ), ); }, - builder: (context, key) => MobileToolbarItemWrapper( + builder: (context, key) => MobileToolbarMenuItemWrapper( key: key, size: const Size(82, 52), onTap: () async { @@ -74,7 +76,7 @@ class AlignItems extends StatelessWidget { vertical: 14.0, ), showDownArrow: true, - backgroundColor: const Color(0xFFF2F2F7), + backgroundColor: theme.toolbarMenuItemBackgroundColor, ), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_bius_items.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_bius_items.dart index 94a3a37b75..4a2c7220ce 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_bius_items.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_bius_items.dart @@ -1,4 +1,5 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/util.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:collection/collection.dart'; @@ -28,6 +29,7 @@ class BIUSItems extends StatelessWidget { .mapIndexed( (index, e) => [ _buildBIUSItem( + context, index, e.$1, e.$2, @@ -43,18 +45,20 @@ class BIUSItems extends StatelessWidget { } Widget _buildBIUSItem( + BuildContext context, int index, FlowySvgData icon, String richTextKey, ) { + final theme = ToolbarColorExtension.of(context); return StatefulBuilder( - builder: (_, setState) => MobileToolbarItemWrapper( + builder: (_, setState) => MobileToolbarMenuItemWrapper( size: const Size(62, 52), enableTopLeftRadius: index == 0, enableBottomLeftRadius: index == 0, enableTopRightRadius: index == _bius.length - 1, enableBottomRightRadius: index == _bius.length - 1, - backgroundColor: const Color(0xFFF2F2F7), + backgroundColor: theme.toolbarMenuItemBackgroundColor, onTap: () async { await editorState.toggleAttribute( richTextKey, diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_block_items.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_block_items.dart index b836da1097..9c54c9b6fa 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_block_items.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_block_items.dart @@ -2,6 +2,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_item/utils.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_menu_item.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_popup_menu.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:collection/collection.dart'; @@ -35,6 +36,7 @@ class BlockItems extends StatelessWidget { .mapIndexed( (index, e) => [ _buildBlockItem( + context, index, e.$1, e.$2, @@ -44,18 +46,20 @@ class BlockItems extends StatelessWidget { ) .flattened, // this item is a special case, use link item here instead of block item - _buildLinkItem(), + _buildLinkItem(context), ], ), ); } Widget _buildBlockItem( + BuildContext context, int index, FlowySvgData icon, String blockType, ) { - return MobileToolbarItemWrapper( + final theme = ToolbarColorExtension.of(context); + return MobileToolbarMenuItemWrapper( size: const Size(62, 54), enableTopLeftRadius: index == 0, enableBottomLeftRadius: index == 0, @@ -64,7 +68,7 @@ class BlockItems extends StatelessWidget { onTap: () async { await editorState.convertBlockType(blockType); }, - backgroundColor: const Color(0xFFF2F2F7), + backgroundColor: theme.toolbarMenuItemBackgroundColor, icon: icon, isSelected: editorState.isBlockTypeSelected(blockType), iconPadding: const EdgeInsets.symmetric( @@ -73,7 +77,8 @@ class BlockItems extends StatelessWidget { ); } - Widget _buildLinkItem() { + Widget _buildLinkItem(BuildContext context) { + final theme = ToolbarColorExtension.of(context); final items = [ (AppFlowyRichTextKeys.code, FlowySvgs.m_aa_code_s), // (InlineMathEquationKeys.formula, FlowySvgs.m_aa_math_s), @@ -87,7 +92,7 @@ class BlockItems extends StatelessWidget { final children = items .mapIndexed( (index, e) => [ - MenuItem( + PopupMenuItemWrapper( key: keys[index], isSelected: currentIndex == index, icon: e.$2, @@ -97,14 +102,14 @@ class BlockItems extends StatelessWidget { ) .flattened .toList(); - return MenuWrapper( + return PopupMenuWrapper( child: Row( mainAxisSize: MainAxisSize.min, children: children, ), ); }, - builder: (context, key) => MobileToolbarItemWrapper( + builder: (context, key) => MobileToolbarMenuItemWrapper( key: key, size: const Size(62, 54), enableTopLeftRadius: false, @@ -113,7 +118,7 @@ class BlockItems extends StatelessWidget { enableBottomRightRadius: true, showDownArrow: true, onTap: _onLinkItemTap, - backgroundColor: const Color(0xFFF2F2F7), + backgroundColor: theme.toolbarMenuItemBackgroundColor, icon: FlowySvgs.m_aa_link_s, isSelected: false, iconPadding: const EdgeInsets.symmetric( diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_color_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_color_item.dart index eb7614aac7..36c60967ab 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_color_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_color_item.dart @@ -1,5 +1,6 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_color_list.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:flutter/material.dart'; @@ -16,7 +17,8 @@ class ColorItem extends StatelessWidget { @override Widget build(BuildContext context) { - return MobileToolbarItemWrapper( + final theme = ToolbarColorExtension.of(context); + return MobileToolbarMenuItemWrapper( size: const Size(82, 52), onTap: () async { service.closeKeyboard(); @@ -36,7 +38,7 @@ class ColorItem extends StatelessWidget { ); }, icon: FlowySvgs.m_aa_color_s, - backgroundColor: const Color(0xFFF2F2F7), + backgroundColor: theme.toolbarMenuItemBackgroundColor, isSelected: false, showRightArrow: true, enable: editorState.selection?.isCollapsed == false, diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_color_list.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_color_list.dart index e25b2ff63f..c70ece6f03 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_color_list.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_color_list.dart @@ -1,6 +1,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:collection/collection.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -13,6 +14,7 @@ Future showTextColorAndBackgroundColorPicker( required EditorState editorState, required Selection selection, }) async { + final theme = ToolbarColorExtension.of(context); await showMobileBottomSheet( context, showHeader: true, @@ -20,7 +22,7 @@ Future showTextColorAndBackgroundColorPicker( showDivider: false, showDragHandle: true, barrierColor: Colors.transparent, - backgroundColor: Colors.white, + backgroundColor: theme.toolbarMenuBackgroundColor, elevation: 20, title: LocaleKeys.grid_selectOption_colorPanelTitle.tr(), padding: const EdgeInsets.fromLTRB(18, 4, 18, 0), @@ -198,6 +200,7 @@ class _BackgroundColorItem extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = ToolbarColorExtension.of(context); return GestureDetector( onTap: onTap, child: Container( @@ -209,7 +212,7 @@ class _BackgroundColorItem extends StatelessWidget { borderRadius: Corners.s12Border, border: Border.all( color: isSelected - ? const Color(0xff00C6F1) + ? theme.toolbarMenuItemSelectedBackgroundColor : Theme.of(context).dividerColor, ), ), diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_font_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_font_item.dart index e1b308d9ff..606b340862 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_font_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_font_item.dart @@ -1,4 +1,5 @@ import 'package:appflowy/mobile/presentation/setting/font/font_picker_screen.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart'; import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; @@ -17,12 +18,13 @@ class FontFamilyItem extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = ToolbarColorExtension.of(context); final fontFamily = editorState.getDeltaAttributeValueInSelection( AppFlowyRichTextKeys.fontFamily, ); final systemFonFamily = context.read().state.fontFamily; - return MobileToolbarItemWrapper( + return MobileToolbarMenuItemWrapper( size: const Size(144, 52), onTap: () async { final selection = editorState.selection; @@ -44,7 +46,7 @@ class FontFamilyItem extends StatelessWidget { }, text: fontFamily ?? systemFonFamily, fontFamily: fontFamily ?? systemFonFamily, - backgroundColor: const Color(0xFFF2F2F7), + backgroundColor: theme.toolbarMenuItemBackgroundColor, isSelected: false, enable: editorState.selection?.isCollapsed == false, showRightArrow: true, diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_heading_and_text_items.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_heading_and_text_items.dart index e8f12d8fad..ff7d495c31 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_heading_and_text_items.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_heading_and_text_items.dart @@ -70,7 +70,7 @@ class _HeadingOrTextItem extends StatelessWidget { : const EdgeInsets.symmetric( vertical: 16.0, ); - return MobileToolbarItemWrapper( + return MobileToolbarMenuItemWrapper( size: const Size(76, 52), onTap: () async => await _convert(isSelected), icon: icon, diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_indent_items.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_indent_items.dart index a840fcfb52..09ab3343ee 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_indent_items.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_indent_items.dart @@ -1,4 +1,5 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/util.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:flutter/material.dart'; @@ -13,10 +14,11 @@ class IndentAndOutdentItems extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = ToolbarColorExtension.of(context); return IntrinsicHeight( child: Row( children: [ - MobileToolbarItemWrapper( + MobileToolbarMenuItemWrapper( size: const Size(95, 52), icon: FlowySvgs.m_aa_outdent_s, enable: isOutdentable(editorState), @@ -24,13 +26,13 @@ class IndentAndOutdentItems extends StatelessWidget { enableTopRightRadius: false, enableBottomRightRadius: false, iconPadding: const EdgeInsets.symmetric(vertical: 14.0), - backgroundColor: const Color(0xFFF2F2F7), + backgroundColor: theme.toolbarMenuItemBackgroundColor, onTap: () { outdentCommand.execute(editorState); }, ), const ScaledVerticalDivider(), - MobileToolbarItemWrapper( + MobileToolbarMenuItemWrapper( size: const Size(95, 52), icon: FlowySvgs.m_aa_indent_s, enable: isIndentable(editorState), @@ -38,7 +40,7 @@ class IndentAndOutdentItems extends StatelessWidget { enableTopLeftRadius: false, enableBottomLeftRadius: false, iconPadding: const EdgeInsets.symmetric(vertical: 14.0), - backgroundColor: const Color(0xFFF2F2F7), + backgroundColor: theme.toolbarMenuItemBackgroundColor, onTap: () { indentCommand.execute(editorState); }, diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_menu_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_menu_item.dart index 90b98dda7b..0056756d1a 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_menu_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_menu_item.dart @@ -1,8 +1,9 @@ +import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart'; import 'package:flowy_svg/flowy_svg.dart'; import 'package:flutter/material.dart'; -class MenuItem extends StatelessWidget { - const MenuItem({ +class PopupMenuItemWrapper extends StatelessWidget { + const PopupMenuItemWrapper({ super.key, required this.isSelected, required this.icon, @@ -13,11 +14,12 @@ class MenuItem extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = ToolbarColorExtension.of(context); return Container( width: 62, height: 44, decoration: ShapeDecoration( - color: isSelected ? const Color(0xFF00BCF0) : null, + color: isSelected ? theme.toolbarMenuItemSelectedBackgroundColor : null, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), @@ -25,14 +27,16 @@ class MenuItem extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 9), child: FlowySvg( icon, - color: isSelected ? Colors.white : null, + color: isSelected + ? theme.toolbarMenuIconSelectedColor + : theme.toolbarMenuIconColor, ), ); } } -class MenuWrapper extends StatelessWidget { - const MenuWrapper({ +class PopupMenuWrapper extends StatelessWidget { + const PopupMenuWrapper({ super.key, required this.child, }); @@ -41,6 +45,7 @@ class MenuWrapper extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = ToolbarColorExtension.of(context); return Container( height: 64, padding: const EdgeInsets.symmetric( @@ -48,15 +53,15 @@ class MenuWrapper extends StatelessWidget { vertical: 10, ), decoration: ShapeDecoration( - color: Colors.white, + color: theme.toolbarMenuBackgroundColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), - shadows: const [ + shadows: [ BoxShadow( - color: Color(0x2D000000), + color: theme.toolbarShadowColor, blurRadius: 20, - offset: Offset(0, 10), + offset: const Offset(0, 10), spreadRadius: 0, ), ], diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_popup_menu.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_popup_menu.dart index a5bba2393c..6eb948fa1b 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_popup_menu.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_popup_menu.dart @@ -1,3 +1,4 @@ +import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -83,6 +84,7 @@ class _PopupMenuState extends State { } void _showMenu(BuildContext context) { + final theme = ToolbarColorExtension.of(context); _hideMenu(); indexNotifier.value = widget.itemLength - 1; @@ -94,12 +96,15 @@ class _PopupMenuState extends State { return Positioned( right: right, bottom: bottom, - child: ValueListenableBuilder( - valueListenable: indexNotifier, - builder: (context, value, _) => widget.menuBuilder( - context, - itemKeys, - value, + child: ColoredBox( + color: theme.toolbarMenuBackgroundColor, + child: ValueListenableBuilder( + valueListenable: indexNotifier, + builder: (context, value, _) => widget.menuBuilder( + context, + itemKeys, + value, + ), ), ), ); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart new file mode 100644 index 0000000000..6042bd6695 --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart @@ -0,0 +1,182 @@ +// workaround for toolbar theme color. + +import 'package:flutter/material.dart'; + +class ToolbarColorExtension extends ThemeExtension { + const ToolbarColorExtension({ + required this.toolbarBackgroundColor, + required this.toolbarItemIconColor, + required this.toolbarItemIconDisabledColor, + required this.toolbarItemIconSelectedColor, + required this.toolbarMenuBackgroundColor, + required this.toolbarMenuItemBackgroundColor, + required this.toolbarMenuItemSelectedBackgroundColor, + required this.toolbarItemSelectedBackgroundColor, + required this.toolbarMenuIconColor, + required this.toolbarMenuIconDisabledColor, + required this.toolbarMenuIconSelectedColor, + required this.toolbarShadowColor, + }); + + final Color toolbarBackgroundColor; + + final Color toolbarItemIconColor; + final Color toolbarItemIconDisabledColor; + final Color toolbarItemIconSelectedColor; + final Color toolbarItemSelectedBackgroundColor; + + final Color toolbarMenuBackgroundColor; + final Color toolbarMenuItemBackgroundColor; + final Color toolbarMenuItemSelectedBackgroundColor; + final Color toolbarMenuIconColor; + final Color toolbarMenuIconDisabledColor; + final Color toolbarMenuIconSelectedColor; + + final Color toolbarShadowColor; + + factory ToolbarColorExtension.fromBrightness(Brightness brightness) { + return brightness == Brightness.light + ? ToolbarColorExtension.light() + : ToolbarColorExtension.dark(); + } + + factory ToolbarColorExtension.light() { + return const ToolbarColorExtension( + toolbarBackgroundColor: Color(0xFFF3F3F8), + toolbarItemIconColor: Color(0xFF1F2329), + toolbarItemIconDisabledColor: Color(0xFF999BA0), + toolbarItemIconSelectedColor: Color(0x1F232914), + toolbarItemSelectedBackgroundColor: Color(0x1F232914), + toolbarMenuBackgroundColor: Color(0xFFFFFFFF), + toolbarMenuItemBackgroundColor: Color(0xFFF2F2F7), + toolbarMenuItemSelectedBackgroundColor: Color(0xFF00BCF0), + toolbarMenuIconColor: Color(0xFF1F2329), + toolbarMenuIconDisabledColor: Color(0xFF999BA0), + toolbarMenuIconSelectedColor: Color(0xFFFFFFFF), + toolbarShadowColor: Color(0x2D000000), + ); + } + factory ToolbarColorExtension.dark() { + return const ToolbarColorExtension( + toolbarBackgroundColor: Color(0xFF1F2329), + toolbarItemIconColor: Color(0xFFF3F3F8), + toolbarItemIconDisabledColor: Color(0xFF55565B), + toolbarItemIconSelectedColor: Color(0xFF00BCF0), + toolbarItemSelectedBackgroundColor: Color(0xFF3A3D43), + toolbarMenuBackgroundColor: Color(0xFF23262B), + toolbarMenuItemBackgroundColor: Color(0xFF2D3036), + toolbarMenuItemSelectedBackgroundColor: Color(0xFF00BCF0), + toolbarMenuIconColor: Color(0xFFF3F3F8), + toolbarMenuIconDisabledColor: Color(0xFF55565B), + toolbarMenuIconSelectedColor: Color(0xFF1F2329), + toolbarShadowColor: Color.fromARGB( + 80, + 112, + 112, + 112, + ), + ); + } + + static ToolbarColorExtension of(BuildContext context) { + return Theme.of(context).extension()!; + } + + @override + ToolbarColorExtension copyWith({ + Color? toolbarBackgroundColor, + Color? toolbarItemIconColor, + Color? toolbarItemIconDisabledColor, + Color? toolbarItemIconSelectedColor, + Color? toolbarMenuBackgroundColor, + Color? toolbarItemSelectedBackgroundColor, + Color? toolbarMenuItemBackgroundColor, + Color? toolbarMenuItemSelectedBackgroundColor, + Color? toolbarMenuIconColor, + Color? toolbarMenuIconDisabledColor, + Color? toolbarMenuIconSelectedColor, + Color? toolbarShadowColor, + }) { + return ToolbarColorExtension( + toolbarBackgroundColor: + toolbarBackgroundColor ?? this.toolbarBackgroundColor, + toolbarItemIconColor: toolbarItemIconColor ?? this.toolbarItemIconColor, + toolbarItemIconDisabledColor: + toolbarItemIconDisabledColor ?? this.toolbarItemIconDisabledColor, + toolbarItemIconSelectedColor: + toolbarItemIconSelectedColor ?? this.toolbarItemIconSelectedColor, + toolbarItemSelectedBackgroundColor: toolbarItemSelectedBackgroundColor ?? + this.toolbarItemSelectedBackgroundColor, + toolbarMenuBackgroundColor: + toolbarMenuBackgroundColor ?? this.toolbarMenuBackgroundColor, + toolbarMenuItemBackgroundColor: + toolbarMenuItemBackgroundColor ?? this.toolbarMenuItemBackgroundColor, + toolbarMenuItemSelectedBackgroundColor: + toolbarMenuItemSelectedBackgroundColor ?? + this.toolbarMenuItemSelectedBackgroundColor, + toolbarMenuIconColor: toolbarMenuIconColor ?? this.toolbarMenuIconColor, + toolbarMenuIconDisabledColor: + toolbarMenuIconDisabledColor ?? this.toolbarMenuIconDisabledColor, + toolbarMenuIconSelectedColor: + toolbarMenuIconSelectedColor ?? this.toolbarMenuIconSelectedColor, + toolbarShadowColor: toolbarShadowColor ?? this.toolbarShadowColor, + ); + } + + @override + ToolbarColorExtension lerp(ToolbarColorExtension? other, double t) { + if (other is! ToolbarColorExtension) { + return this; + } + return ToolbarColorExtension( + toolbarBackgroundColor: + Color.lerp(toolbarBackgroundColor, other.toolbarBackgroundColor, t)!, + toolbarItemIconColor: + Color.lerp(toolbarItemIconColor, other.toolbarItemIconColor, t)!, + toolbarItemIconDisabledColor: Color.lerp( + toolbarItemIconDisabledColor, + other.toolbarItemIconDisabledColor, + t, + )!, + toolbarItemIconSelectedColor: Color.lerp( + toolbarItemIconSelectedColor, + other.toolbarItemIconSelectedColor, + t, + )!, + toolbarItemSelectedBackgroundColor: Color.lerp( + toolbarItemSelectedBackgroundColor, + other.toolbarItemSelectedBackgroundColor, + t, + )!, + toolbarMenuBackgroundColor: Color.lerp( + toolbarMenuBackgroundColor, + other.toolbarMenuBackgroundColor, + t, + )!, + toolbarMenuItemBackgroundColor: Color.lerp( + toolbarMenuItemBackgroundColor, + other.toolbarMenuItemBackgroundColor, + t, + )!, + toolbarMenuItemSelectedBackgroundColor: Color.lerp( + toolbarMenuItemSelectedBackgroundColor, + other.toolbarMenuItemSelectedBackgroundColor, + t, + )!, + toolbarMenuIconColor: + Color.lerp(toolbarMenuIconColor, other.toolbarMenuIconColor, t)!, + toolbarMenuIconDisabledColor: Color.lerp( + toolbarMenuIconDisabledColor, + other.toolbarMenuIconDisabledColor, + t, + )!, + toolbarMenuIconSelectedColor: Color.lerp( + toolbarMenuIconSelectedColor, + other.toolbarMenuIconSelectedColor, + t, + )!, + toolbarShadowColor: + Color.lerp(toolbarShadowColor, other.toolbarShadowColor, t)!, + ); + } +} diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/aa_toolbar_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/aa_toolbar_item.dart index c8c36cb61f..23f5d7b273 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/aa_toolbar_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/aa_toolbar_item.dart @@ -6,6 +6,7 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_too import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_font_item.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_heading_and_text_items.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_indent_items.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:flutter/material.dart'; @@ -53,9 +54,10 @@ class _TextDecorationMenuState extends State<_TextDecorationMenu> { @override Widget build(BuildContext context) { - return SingleChildScrollView( - child: ColoredBox( - color: Colors.white, + final theme = ToolbarColorExtension.of(context); + return ColoredBox( + color: theme.toolbarMenuBackgroundColor, + child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.only( top: 16, diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/appflowy_mobile_toolbar.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/appflowy_mobile_toolbar.dart index e39da4cd95..b016b82085 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/appflowy_mobile_toolbar.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/appflowy_mobile_toolbar.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_close_keyboard_or_menu_button.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/appflowy_mobile_toolbar_item.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/keyboard_height_observer.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; @@ -275,12 +276,13 @@ class _MobileToolbarState extends State<_MobileToolbar> // toolbar list view and close keyboard/menu button Widget _buildToolbar(BuildContext context) { + final theme = ToolbarColorExtension.of(context); return Container( height: widget.toolbarHeight, width: MediaQuery.of(context).size.width, - decoration: const BoxDecoration( - color: Color(0xFFF3F3F8), - boxShadow: [ + decoration: BoxDecoration( + color: theme.toolbarBackgroundColor, + boxShadow: const [ BoxShadow( color: Color(0x0F181818), blurRadius: 40, @@ -345,13 +347,13 @@ class _MobileToolbarState extends State<_MobileToolbar> final showShadow = offset > 0; return DecoratedBox( decoration: BoxDecoration( - color: const Color(0xFFF3F3F8), + color: theme.toolbarBackgroundColor, boxShadow: showShadow ? [ - const BoxShadow( - color: Color(0x51000000), + BoxShadow( + color: theme.toolbarShadowColor, blurRadius: 20, - offset: Offset(-2, 0), + offset: const Offset(-2, 0), spreadRadius: -10, ), ] diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/appflowy_mobile_toolbar_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/appflowy_mobile_toolbar_item.dart index dd9bb20c9d..423173fa6f 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/appflowy_mobile_toolbar_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/appflowy_mobile_toolbar_item.dart @@ -1,4 +1,5 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/appflowy_mobile_toolbar.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:flutter/material.dart'; @@ -77,6 +78,7 @@ class _AppFlowyMobileToolbarIconItemState @override Widget build(BuildContext context) { + final theme = ToolbarColorExtension.of(context); return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: GestureDetector( @@ -98,11 +100,12 @@ class _AppFlowyMobileToolbarIconItemState padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 8), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), - color: isSelected ? const Color(0x1f232914) : null, + color: isSelected ? theme.toolbarItemSelectedBackgroundColor : null, ), child: widget.iconBuilder?.call(context) ?? FlowySvg( widget.icon!, + color: theme.toolbarItemIconColor, ), ), ), diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/undo_redo_toolbar_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/undo_redo_toolbar_item.dart index c3808ce83e..5001b37c81 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/undo_redo_toolbar_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/undo_redo_toolbar_item.dart @@ -1,17 +1,20 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; -import 'package:flutter/material.dart'; final undoToolbarItem = AppFlowyMobileToolbarItem( pilotAtCollapsedSelection: true, itemBuilder: (context, editorState, _, __, onAction) { + final theme = ToolbarColorExtension.of(context); return AppFlowyMobileToolbarIconItem( iconBuilder: (context) { final canUndo = editorState.undoManager.undoStack.isNonEmpty; return FlowySvg( FlowySvgs.m_toolbar_undo_s, - color: canUndo ? null : const Color(0xFFC7C7CC), + color: canUndo + ? theme.toolbarItemIconColor + : theme.toolbarItemIconDisabledColor, ); }, onTap: () => undoCommand.execute(editorState), @@ -21,12 +24,15 @@ final undoToolbarItem = AppFlowyMobileToolbarItem( final redoToolbarItem = AppFlowyMobileToolbarItem( itemBuilder: (context, editorState, _, __, onAction) { + final theme = ToolbarColorExtension.of(context); return AppFlowyMobileToolbarIconItem( iconBuilder: (context) { final canRedo = editorState.undoManager.redoStack.isNonEmpty; return FlowySvg( FlowySvgs.m_toolbar_redo_s, - color: canRedo ? null : const Color(0xFFC7C7CC), + color: canRedo + ? theme.toolbarItemIconColor + : theme.toolbarItemIconDisabledColor, ); }, onTap: () => redoCommand.execute(editorState), diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/util.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/util.dart index 5738b7b7ff..0cd6bc37c0 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/util.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/util.dart @@ -1,10 +1,11 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; -class MobileToolbarItemWrapper extends StatelessWidget { - const MobileToolbarItemWrapper({ +class MobileToolbarMenuItemWrapper extends StatelessWidget { + const MobileToolbarMenuItemWrapper({ super.key, required this.size, this.icon, @@ -43,13 +44,17 @@ class MobileToolbarItemWrapper extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = ToolbarColorExtension.of(context); Color? iconColor; if (enable != null) { - iconColor = enable! ? null : const Color(0xFFC7C7CC); + iconColor = enable! ? null : theme.toolbarMenuIconDisabledColor; } else { - iconColor = isSelected ? Colors.white : Colors.black; + iconColor = isSelected + ? theme.toolbarMenuIconSelectedColor + : theme.toolbarMenuIconColor; } - final textColor = enable == false ? const Color(0xFFC7C7CC) : null; + final textColor = + enable == false ? theme.toolbarMenuIconDisabledColor : null; // the ui design is based on 375.0 width final scale = context.scale; final radius = Radius.circular(12 * scale); @@ -84,7 +89,9 @@ class MobileToolbarItemWrapper extends StatelessWidget { width: size.width * scale, alignment: text != null ? Alignment.centerLeft : Alignment.center, decoration: BoxDecoration( - color: isSelected ? const Color(0xFF00BCF0) : backgroundColor, + color: isSelected + ? theme.toolbarMenuItemSelectedBackgroundColor + : backgroundColor, borderRadius: BorderRadius.only( topLeft: enableTopLeftRadius ? radius : Radius.zero, topRight: enableTopRightRadius ? radius : Radius.zero, diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/appearance/mobile_appearance.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/appearance/mobile_appearance.dart index eea54cf0ce..a0e08ee519 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/appearance/mobile_appearance.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/appearance/mobile_appearance.dart @@ -1,4 +1,5 @@ // ThemeData in mobile +import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart'; import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme.dart'; @@ -284,6 +285,7 @@ class MobileAppearance extends BaseAppearance { color: theme.hint, ), ), + ToolbarColorExtension.fromBrightness(brightness), ], ); }