From 980bebf86a8299edd8530d85469e171a87ab427d Mon Sep 17 00:00:00 2001 From: "Lucas.Xu" Date: Wed, 28 Feb 2024 12:32:24 +0700 Subject: [PATCH] fix: mobile UI regression (#4754) * fix: aa menu item selected status * feat: support selecting word on iOS throught long pressing * chore: update editor version * feat: update add block menu colors * feat: add scrollbar in bottom sheet * fix: aa menu should not dimiss after changing block type * fix: add link menu ui issues * feat: sync bius status * Update frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/appflowy_mobile_toolbar_item.dart Co-authored-by: Mathias Mogensen <42929161+Xazin@users.noreply.github.com> * chore: update editor version * fix: flutter analyze --------- Co-authored-by: Mathias Mogensen <42929161+Xazin@users.noreply.github.com> --- .../show_mobile_bottom_sheet.dart | 8 +- .../editor_plugins/mention/mention_block.dart | 3 +- .../migration/editor_migration.dart | 2 +- .../mobile_toolbar_item/utils.dart | 3 + .../mobile_toolbar_v3/_bius_items.dart | 3 +- .../mobile_toolbar_v3/_block_items.dart | 21 +- .../mobile_toolbar_v3/_color_list.dart | 4 +- .../mobile_toolbar_v3/aa_toolbar_item.dart | 1 + .../add_block_toolbar_item.dart | 328 ++++++++++-------- .../appflowy_mobile_toolbar.dart | 5 + .../appflowy_mobile_toolbar_item.dart | 40 ++- .../mobile_toolbar_v3/biuc_toolbar_item.dart | 17 +- .../checkbox_toolbar_item.dart | 2 + .../mobile_toolbar_v3/more_toolbar_item.dart | 1 + .../undo_redo_toolbar_item.dart | 2 + frontend/appflowy_flutter/pubspec.lock | 4 +- frontend/appflowy_flutter/pubspec.yaml | 2 +- 17 files changed, 277 insertions(+), 169 deletions(-) diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart b/frontend/appflowy_flutter/lib/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart index 6ad821bb64..bf94d766f2 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart @@ -127,9 +127,11 @@ Future showMobileBottomSheet( children: [ ...children, Expanded( - child: SingleChildScrollView( - controller: scrollController, - child: child, + child: Scrollbar( + child: SingleChildScrollView( + controller: scrollController, + child: child, + ), ), ), ], diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_block.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_block.dart index 18afae962e..00793adb4b 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_block.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_block.dart @@ -1,10 +1,9 @@ -import 'package:flutter/material.dart'; - import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_date_block.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_page_block.dart'; import 'package:appflowy/workspace/presentation/widgets/date_picker/widgets/reminder_selector.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:collection/collection.dart'; +import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; enum MentionType { diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/migration/editor_migration.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/migration/editor_migration.dart index 0cdf04a7d0..f2e3d4d427 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/migration/editor_migration.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/migration/editor_migration.dart @@ -141,7 +141,7 @@ class EditorMigration { } const backgroundColor = 'backgroundColor'; if (attributes.containsKey(backgroundColor)) { - attributes[AppFlowyRichTextKeys.highlightColor] = + attributes[AppFlowyRichTextKeys.backgroundColor] = attributes[backgroundColor]; attributes.remove(backgroundColor); } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_item/utils.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_item/utils.dart index 699bce2f73..21f3b7ea68 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_item/utils.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_item/utils.dart @@ -11,6 +11,9 @@ Future showEditLinkBottomSheet( return showMobileBottomSheet( context, showHeader: false, + showCloseButton: false, + showDragHandle: true, + padding: const EdgeInsets.symmetric(horizontal: 16), builder: (context) { return MobileBottomSheetEditLinkWidget( text: text, 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 4a2c7220ce..36a023251e 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 @@ -71,7 +71,8 @@ class BIUSItems extends StatelessWidget { setState(() {}); }, icon: icon, - isSelected: editorState.isTextDecorationSelected(richTextKey), + isSelected: editorState.isTextDecorationSelected(richTextKey) && + editorState.toggledStyle[richTextKey] != true, iconPadding: const EdgeInsets.symmetric( vertical: 14.0, ), 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 3b11c078d1..00d86be244 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 @@ -68,7 +68,7 @@ class BlockItems extends StatelessWidget { enableTopRightRadius: false, enableBottomRightRadius: false, onTap: () async { - await editorState.convertBlockType(blockType); + await _convert(blockType); }, backgroundColor: theme.toolbarMenuItemBackgroundColor, icon: icon, @@ -196,4 +196,23 @@ class BlockItems extends StatelessWidget { ); editorState.service.keyboardService?.closeKeyboard(); } + + Future _convert(String blockType) async { + await editorState.convertBlockType( + blockType, + selectionExtraInfo: { + selectionExtraInfoDoNotAttachTextService: true, + selectionExtraInfoDisableFloatingToolbar: true, + }, + ); + unawaited( + editorState.updateSelectionWithReason( + editorState.selection, + extraInfo: { + selectionExtraInfoDisableFloatingToolbar: true, + selectionExtraInfoDoNotAttachTextService: true, + }, + ), + ); + } } 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 eb8b7ec061..202ab3a786 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 @@ -70,7 +70,7 @@ class _TextColorAndBackgroundColorState ); final String? selectedBackgroundColor = widget.editorState.getDeltaAttributeValueInSelection( - AppFlowyRichTextKeys.highlightColor, + AppFlowyRichTextKeys.backgroundColor, widget.selection, ); return Column( @@ -122,7 +122,7 @@ class _TextColorAndBackgroundColorState await widget.editorState.formatDelta( widget.selection, { - AppFlowyRichTextKeys.highlightColor: hex, + AppFlowyRichTextKeys.backgroundColor: hex, }, selectionExtraInfo: { selectionExtraInfoDisableFloatingToolbar: true, 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 999e6607b9..c26a33adb2 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 @@ -15,6 +15,7 @@ final aaToolbarItem = AppFlowyMobileToolbarItem( pilotAtExpandedSelection: true, itemBuilder: (context, editorState, service, onMenu, _) { return AppFlowyMobileToolbarIconItem( + editorState: editorState, isSelected: () => service.showMenuNotifier.value, keepSelectedStatus: true, icon: FlowySvgs.m_toolbar_aa_s, diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/add_block_toolbar_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/add_block_toolbar_item.dart index 724211b6e7..aac7306be5 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/add_block_toolbar_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/add_block_toolbar_item.dart @@ -18,6 +18,7 @@ import 'package:go_router/go_router.dart'; final addBlockToolbarItem = AppFlowyMobileToolbarItem( itemBuilder: (context, editorState, service, __, onAction) { return AppFlowyMobileToolbarIconItem( + editorState: editorState, icon: FlowySvgs.m_toolbar_add_s, onTap: () { final selection = editorState.selection; @@ -83,7 +84,7 @@ Future showAddBlockMenu( } class _AddBlockMenu extends StatelessWidget { - _AddBlockMenu({ + const _AddBlockMenu({ required this.selection, required this.editorState, }); @@ -91,151 +92,10 @@ class _AddBlockMenu extends StatelessWidget { final Selection selection; final EditorState editorState; - late final List> typeOptionMenuItemValue = [ - // heading 1 - 3 - TypeOptionMenuItemValue( - value: HeadingBlockKeys.type, - backgroundColor: const Color(0xFFBAC9FF), - text: LocaleKeys.editor_heading1.tr(), - icon: FlowySvgs.m_add_block_h1_s, - onTap: (_, __) => _insertBlock(headingNode(level: 1)), - ), - TypeOptionMenuItemValue( - value: HeadingBlockKeys.type, - backgroundColor: const Color(0xFFBAC9FF), - text: LocaleKeys.editor_heading2.tr(), - icon: FlowySvgs.m_add_block_h2_s, - onTap: (_, __) => _insertBlock(headingNode(level: 2)), - ), - TypeOptionMenuItemValue( - value: HeadingBlockKeys.type, - backgroundColor: const Color(0xFFBAC9FF), - text: LocaleKeys.editor_heading3.tr(), - icon: FlowySvgs.m_add_block_h3_s, - onTap: (_, __) => _insertBlock(headingNode(level: 3)), - ), - - // paragraph - TypeOptionMenuItemValue( - value: ParagraphBlockKeys.type, - backgroundColor: const Color(0xFFBAC9FF), - text: LocaleKeys.editor_text.tr(), - icon: FlowySvgs.m_add_block_paragraph_s, - onTap: (_, __) => _insertBlock(paragraphNode()), - ), - - // checkbox - TypeOptionMenuItemValue( - value: TodoListBlockKeys.type, - backgroundColor: const Color(0xFF98F4CD), - text: LocaleKeys.editor_checkbox.tr(), - icon: FlowySvgs.m_add_block_checkbox_s, - onTap: (_, __) => _insertBlock(todoListNode(checked: false)), - ), - - // quote - TypeOptionMenuItemValue( - value: QuoteBlockKeys.type, - backgroundColor: const Color(0xFFFDEDA7), - text: LocaleKeys.editor_quote.tr(), - icon: FlowySvgs.m_add_block_quote_s, - onTap: (_, __) => _insertBlock(quoteNode()), - ), - - // bulleted list, numbered list, toggle list - TypeOptionMenuItemValue( - value: BulletedListBlockKeys.type, - backgroundColor: const Color(0xFFFFB9EF), - text: LocaleKeys.editor_bulletedListShortForm.tr(), - icon: FlowySvgs.m_add_block_bulleted_list_s, - onTap: (_, __) => _insertBlock(bulletedListNode()), - ), - TypeOptionMenuItemValue( - value: NumberedListBlockKeys.type, - backgroundColor: const Color(0xFFFFB9EF), - text: LocaleKeys.editor_numberedListShortForm.tr(), - icon: FlowySvgs.m_add_block_numbered_list_s, - onTap: (_, __) => _insertBlock(numberedListNode()), - ), - TypeOptionMenuItemValue( - value: ToggleListBlockKeys.type, - backgroundColor: const Color(0xFFFFB9EF), - text: LocaleKeys.editor_toggleListShortForm.tr(), - icon: FlowySvgs.m_add_block_toggle_s, - onTap: (_, __) => _insertBlock(toggleListBlockNode()), - ), - - // image - TypeOptionMenuItemValue( - value: DividerBlockKeys.type, - backgroundColor: const Color(0xFF98F4CD), - text: LocaleKeys.editor_image.tr(), - icon: FlowySvgs.m_add_block_image_s, - onTap: (_, __) async { - AppGlobals.rootNavKey.currentContext?.pop(true); - Future.delayed(const Duration(milliseconds: 400), () async { - final imagePlaceholderKey = GlobalKey(); - await editorState.insertEmptyImageBlock(imagePlaceholderKey); - }); - }, - ), - - // date - TypeOptionMenuItemValue( - value: ParagraphBlockKeys.type, - backgroundColor: const Color(0xFF91EAF5), - text: LocaleKeys.editor_date.tr(), - icon: FlowySvgs.m_add_block_date_s, - onTap: (_, __) => _insertBlock(dateMentionNode()), - ), - - // divider - TypeOptionMenuItemValue( - value: DividerBlockKeys.type, - backgroundColor: const Color(0xFF98F4CD), - text: LocaleKeys.editor_divider.tr(), - icon: FlowySvgs.m_add_block_divider_s, - onTap: (_, __) { - AppGlobals.rootNavKey.currentContext?.pop(true); - Future.delayed(const Duration(milliseconds: 100), () { - editorState.insertDivider(selection); - }); - }, - ), - - // callout, code, math equation - TypeOptionMenuItemValue( - value: CalloutBlockKeys.type, - backgroundColor: const Color(0xFFCABDFF), - text: LocaleKeys.document_plugins_callout.tr(), - icon: FlowySvgs.m_add_block_callout_s, - onTap: (_, __) => _insertBlock(calloutNode()), - ), - TypeOptionMenuItemValue( - value: CodeBlockKeys.type, - backgroundColor: const Color(0xFFCABDFF), - text: LocaleKeys.editor_codeBlockShortForm.tr(), - icon: FlowySvgs.m_add_block_code_s, - onTap: (_, __) => _insertBlock(codeBlockNode()), - ), - TypeOptionMenuItemValue( - value: MathEquationBlockKeys.type, - backgroundColor: const Color(0xFFCABDFF), - text: LocaleKeys.editor_mathEquationShortForm.tr(), - icon: FlowySvgs.m_add_block_formula_s, - onTap: (_, __) { - AppGlobals.rootNavKey.currentContext?.pop(true); - Future.delayed(const Duration(milliseconds: 100), () { - editorState.insertMathEquation(selection); - }); - }, - ), - ]; - @override Widget build(BuildContext context) { return TypeOptionMenu( - values: typeOptionMenuItemValue, + values: buildTypeOptionMenuItemValues(context), scaleFactor: context.scale, ); } @@ -249,6 +109,188 @@ class _AddBlockMenu extends StatelessWidget { ); }); } + + List> buildTypeOptionMenuItemValues( + BuildContext context, + ) { + final colorMap = _colorMap(context); + return [ + // heading 1 - 3 + TypeOptionMenuItemValue( + value: HeadingBlockKeys.type, + backgroundColor: colorMap[HeadingBlockKeys.type]!, + text: LocaleKeys.editor_heading1.tr(), + icon: FlowySvgs.m_add_block_h1_s, + onTap: (_, __) => _insertBlock(headingNode(level: 1)), + ), + TypeOptionMenuItemValue( + value: HeadingBlockKeys.type, + backgroundColor: colorMap[HeadingBlockKeys.type]!, + text: LocaleKeys.editor_heading2.tr(), + icon: FlowySvgs.m_add_block_h2_s, + onTap: (_, __) => _insertBlock(headingNode(level: 2)), + ), + TypeOptionMenuItemValue( + value: HeadingBlockKeys.type, + backgroundColor: colorMap[HeadingBlockKeys.type]!, + text: LocaleKeys.editor_heading3.tr(), + icon: FlowySvgs.m_add_block_h3_s, + onTap: (_, __) => _insertBlock(headingNode(level: 3)), + ), + + // paragraph + TypeOptionMenuItemValue( + value: ParagraphBlockKeys.type, + backgroundColor: colorMap[ParagraphBlockKeys.type]!, + text: LocaleKeys.editor_text.tr(), + icon: FlowySvgs.m_add_block_paragraph_s, + onTap: (_, __) => _insertBlock(paragraphNode()), + ), + + // checkbox + TypeOptionMenuItemValue( + value: TodoListBlockKeys.type, + backgroundColor: colorMap[TodoListBlockKeys.type]!, + text: LocaleKeys.editor_checkbox.tr(), + icon: FlowySvgs.m_add_block_checkbox_s, + onTap: (_, __) => _insertBlock(todoListNode(checked: false)), + ), + + // quote + TypeOptionMenuItemValue( + value: QuoteBlockKeys.type, + backgroundColor: colorMap[QuoteBlockKeys.type]!, + text: LocaleKeys.editor_quote.tr(), + icon: FlowySvgs.m_add_block_quote_s, + onTap: (_, __) => _insertBlock(quoteNode()), + ), + + // bulleted list, numbered list, toggle list + TypeOptionMenuItemValue( + value: BulletedListBlockKeys.type, + backgroundColor: colorMap[BulletedListBlockKeys.type]!, + text: LocaleKeys.editor_bulletedListShortForm.tr(), + icon: FlowySvgs.m_add_block_bulleted_list_s, + onTap: (_, __) => _insertBlock(bulletedListNode()), + ), + TypeOptionMenuItemValue( + value: NumberedListBlockKeys.type, + backgroundColor: colorMap[NumberedListBlockKeys.type]!, + text: LocaleKeys.editor_numberedListShortForm.tr(), + icon: FlowySvgs.m_add_block_numbered_list_s, + onTap: (_, __) => _insertBlock(numberedListNode()), + ), + TypeOptionMenuItemValue( + value: ToggleListBlockKeys.type, + backgroundColor: colorMap[ToggleListBlockKeys.type]!, + text: LocaleKeys.editor_toggleListShortForm.tr(), + icon: FlowySvgs.m_add_block_toggle_s, + onTap: (_, __) => _insertBlock(toggleListBlockNode()), + ), + + // image + TypeOptionMenuItemValue( + value: ImageBlockKeys.type, + backgroundColor: colorMap[ImageBlockKeys.type]!, + text: LocaleKeys.editor_image.tr(), + icon: FlowySvgs.m_add_block_image_s, + onTap: (_, __) async { + AppGlobals.rootNavKey.currentContext?.pop(true); + Future.delayed(const Duration(milliseconds: 400), () async { + final imagePlaceholderKey = GlobalKey(); + await editorState.insertEmptyImageBlock(imagePlaceholderKey); + }); + }, + ), + + // date + TypeOptionMenuItemValue( + value: ParagraphBlockKeys.type, + backgroundColor: colorMap['date']!, + text: LocaleKeys.editor_date.tr(), + icon: FlowySvgs.m_add_block_date_s, + onTap: (_, __) => _insertBlock(dateMentionNode()), + ), + + // divider + TypeOptionMenuItemValue( + value: DividerBlockKeys.type, + backgroundColor: colorMap[DividerBlockKeys.type]!, + text: LocaleKeys.editor_divider.tr(), + icon: FlowySvgs.m_add_block_divider_s, + onTap: (_, __) { + AppGlobals.rootNavKey.currentContext?.pop(true); + Future.delayed(const Duration(milliseconds: 100), () { + editorState.insertDivider(selection); + }); + }, + ), + + // callout, code, math equation + TypeOptionMenuItemValue( + value: CalloutBlockKeys.type, + backgroundColor: colorMap[CalloutBlockKeys.type]!, + text: LocaleKeys.document_plugins_callout.tr(), + icon: FlowySvgs.m_add_block_callout_s, + onTap: (_, __) => _insertBlock(calloutNode()), + ), + TypeOptionMenuItemValue( + value: CodeBlockKeys.type, + backgroundColor: colorMap[CodeBlockKeys.type]!, + text: LocaleKeys.editor_codeBlockShortForm.tr(), + icon: FlowySvgs.m_add_block_code_s, + onTap: (_, __) => _insertBlock(codeBlockNode()), + ), + TypeOptionMenuItemValue( + value: MathEquationBlockKeys.type, + backgroundColor: colorMap[MathEquationBlockKeys.type]!, + text: LocaleKeys.editor_mathEquationShortForm.tr(), + icon: FlowySvgs.m_add_block_formula_s, + onTap: (_, __) { + AppGlobals.rootNavKey.currentContext?.pop(true); + Future.delayed(const Duration(milliseconds: 100), () { + editorState.insertMathEquation(selection); + }); + }, + ), + ]; + } + + Map _colorMap(BuildContext context) { + final isDarkMode = Theme.of(context).brightness == Brightness.dark; + if (isDarkMode) { + return { + HeadingBlockKeys.type: const Color(0xFF5465A1), + ParagraphBlockKeys.type: const Color(0xFF5465A1), + TodoListBlockKeys.type: const Color(0xFF4BB299), + QuoteBlockKeys.type: const Color(0xFFBAAC74), + BulletedListBlockKeys.type: const Color(0xFFA35F94), + NumberedListBlockKeys.type: const Color(0xFFA35F94), + ToggleListBlockKeys.type: const Color(0xFFA35F94), + ImageBlockKeys.type: const Color(0xFFBAAC74), + 'date': const Color(0xFF40AAB8), + DividerBlockKeys.type: const Color(0xFF4BB299), + CalloutBlockKeys.type: const Color(0xFF66599B), + CodeBlockKeys.type: const Color(0xFF66599B), + MathEquationBlockKeys.type: const Color(0xFF66599B), + }; + } + return { + HeadingBlockKeys.type: const Color(0xFFBECCFF), + ParagraphBlockKeys.type: const Color(0xFFBECCFF), + TodoListBlockKeys.type: const Color(0xFF98F4CD), + QuoteBlockKeys.type: const Color(0xFFFDEDA7), + BulletedListBlockKeys.type: const Color(0xFFFFB9EF), + NumberedListBlockKeys.type: const Color(0xFFFFB9EF), + ToggleListBlockKeys.type: const Color(0xFFFFB9EF), + ImageBlockKeys.type: const Color(0xFFFDEDA7), + 'date': const Color(0xFF91EAF5), + DividerBlockKeys.type: const Color(0xFF98F4CD), + CalloutBlockKeys.type: const Color(0xFFCABDFF), + CodeBlockKeys.type: const Color(0xFFCABDFF), + MathEquationBlockKeys.type: const Color(0xFFCABDFF), + }; + } } extension on EditorState { 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 ba286b7b9f..e76e7d51ab 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 @@ -270,6 +270,11 @@ class _MobileToolbarState extends State<_MobileToolbar> widget.editorState.selection = null; } + // if the menu is shown and the height is not 0, we need to close the menu + if (showMenuNotifier.value && height != 0) { + closeItemMenu(); + } + if (canUpdateCachedKeyboardHeight) { cachedKeyboardHeight.value = height; } 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 423173fa6f..61654ff5cd 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,3 +1,5 @@ +import 'dart:async'; + 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'; @@ -42,7 +44,9 @@ class AppFlowyMobileToolbarIconItem extends StatefulWidget { this.keepSelectedStatus = false, this.iconBuilder, this.isSelected, + this.shouldListenToToggledStyle = false, required this.onTap, + required this.editorState, }); final FlowySvgData? icon; @@ -50,6 +54,8 @@ class AppFlowyMobileToolbarIconItem extends StatefulWidget { final VoidCallback onTap; final WidgetBuilder? iconBuilder; final bool Function()? isSelected; + final bool shouldListenToToggledStyle; + final EditorState editorState; @override State createState() => @@ -59,12 +65,28 @@ class AppFlowyMobileToolbarIconItem extends StatefulWidget { class _AppFlowyMobileToolbarIconItemState extends State { bool isSelected = false; + StreamSubscription? _subscription; @override void initState() { super.initState(); isSelected = widget.isSelected?.call() ?? false; + if (widget.shouldListenToToggledStyle) { + widget.editorState.toggledStyleNotifier.addListener(_rebuild); + _subscription = widget.editorState.transactionStream.listen((_) { + _rebuild(); + }); + } + } + + @override + void dispose() { + if (widget.shouldListenToToggledStyle) { + widget.editorState.toggledStyleNotifier.removeListener(_rebuild); + _subscription?.cancel(); + } + super.dispose(); } @override @@ -85,15 +107,7 @@ class _AppFlowyMobileToolbarIconItemState behavior: HitTestBehavior.opaque, onTap: () { widget.onTap(); - if (widget.keepSelectedStatus && widget.isSelected == null) { - setState(() { - isSelected = !isSelected; - }); - } else { - setState(() { - isSelected = widget.isSelected?.call() ?? false; - }); - } + _rebuild(); }, child: Container( width: 48, @@ -111,4 +125,12 @@ class _AppFlowyMobileToolbarIconItemState ), ); } + + void _rebuild() { + setState(() { + isSelected = (widget.keepSelectedStatus && widget.isSelected == null) + ? !isSelected + : widget.isSelected?.call() ?? false; + }); + } } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/biuc_toolbar_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/biuc_toolbar_item.dart index 6072feed88..16eced6d28 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/biuc_toolbar_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/biuc_toolbar_item.dart @@ -6,9 +6,13 @@ import 'package:appflowy_editor/appflowy_editor.dart'; final boldToolbarItem = AppFlowyMobileToolbarItem( itemBuilder: (context, editorState, _, __, onAction) { return AppFlowyMobileToolbarIconItem( - isSelected: () => editorState.isTextDecorationSelected( - AppFlowyRichTextKeys.bold, - ), + editorState: editorState, + shouldListenToToggledStyle: true, + isSelected: () => + editorState.isTextDecorationSelected( + AppFlowyRichTextKeys.bold, + ) && + editorState.toggledStyle[AppFlowyRichTextKeys.bold] != false, icon: FlowySvgs.m_toolbar_bold_s, onTap: () async => editorState.toggleAttribute( AppFlowyRichTextKeys.bold, @@ -23,7 +27,8 @@ final boldToolbarItem = AppFlowyMobileToolbarItem( final italicToolbarItem = AppFlowyMobileToolbarItem( itemBuilder: (context, editorState, _, __, onAction) { return AppFlowyMobileToolbarIconItem( - // keepSelectedStatus: true, + editorState: editorState, + shouldListenToToggledStyle: true, isSelected: () => editorState.isTextDecorationSelected( AppFlowyRichTextKeys.italic, ), @@ -41,6 +46,8 @@ final italicToolbarItem = AppFlowyMobileToolbarItem( final underlineToolbarItem = AppFlowyMobileToolbarItem( itemBuilder: (context, editorState, _, __, onAction) { return AppFlowyMobileToolbarIconItem( + editorState: editorState, + shouldListenToToggledStyle: true, isSelected: () => editorState.isTextDecorationSelected( AppFlowyRichTextKeys.underline, ), @@ -58,6 +65,8 @@ final underlineToolbarItem = AppFlowyMobileToolbarItem( final colorToolbarItem = AppFlowyMobileToolbarItem( itemBuilder: (context, editorState, service, __, onAction) { return AppFlowyMobileToolbarIconItem( + editorState: editorState, + shouldListenToToggledStyle: true, icon: FlowySvgs.m_toolbar_color_s, onTap: () { service.closeKeyboard(); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/checkbox_toolbar_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/checkbox_toolbar_item.dart index ab8343082e..2b02bb2e5a 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/checkbox_toolbar_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/checkbox_toolbar_item.dart @@ -6,6 +6,8 @@ final todoListToolbarItem = AppFlowyMobileToolbarItem( itemBuilder: (context, editorState, _, __, onAction) { final isSelected = editorState.isBlockTypeSelected(TodoListBlockKeys.type); return AppFlowyMobileToolbarIconItem( + editorState: editorState, + shouldListenToToggledStyle: true, keepSelectedStatus: true, isSelected: () => isSelected, icon: FlowySvgs.m_toolbar_checkbox_s, diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/more_toolbar_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/more_toolbar_item.dart index fb07c0663b..1488847ea5 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/more_toolbar_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/more_toolbar_item.dart @@ -4,6 +4,7 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.da final moreToolbarItem = AppFlowyMobileToolbarItem( itemBuilder: (context, editorState, _, __, onAction) { return AppFlowyMobileToolbarIconItem( + editorState: editorState, icon: FlowySvgs.m_toolbar_more_s, onTap: () {}, ); 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 5001b37c81..65c4a9b783 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 @@ -8,6 +8,7 @@ final undoToolbarItem = AppFlowyMobileToolbarItem( itemBuilder: (context, editorState, _, __, onAction) { final theme = ToolbarColorExtension.of(context); return AppFlowyMobileToolbarIconItem( + editorState: editorState, iconBuilder: (context) { final canUndo = editorState.undoManager.undoStack.isNonEmpty; return FlowySvg( @@ -26,6 +27,7 @@ final redoToolbarItem = AppFlowyMobileToolbarItem( itemBuilder: (context, editorState, _, __, onAction) { final theme = ToolbarColorExtension.of(context); return AppFlowyMobileToolbarIconItem( + editorState: editorState, iconBuilder: (context) { final canRedo = editorState.undoManager.redoStack.isNonEmpty; return FlowySvg( diff --git a/frontend/appflowy_flutter/pubspec.lock b/frontend/appflowy_flutter/pubspec.lock index f9f7c7dbf4..56b6597c34 100644 --- a/frontend/appflowy_flutter/pubspec.lock +++ b/frontend/appflowy_flutter/pubspec.lock @@ -53,8 +53,8 @@ packages: dependency: "direct main" description: path: "." - ref: "9d90053" - resolved-ref: "9d9005366ba8383e93029c4f2f006f9ff8d1cb08" + ref: d4d35c0 + resolved-ref: d4d35c0d103a5d1bddf68181fcfaf9f75b0fccb5 url: "https://github.com/AppFlowy-IO/appflowy-editor.git" source: git version: "2.3.2" diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml index 6a388c9709..ac0141bc73 100644 --- a/frontend/appflowy_flutter/pubspec.yaml +++ b/frontend/appflowy_flutter/pubspec.yaml @@ -167,7 +167,7 @@ dependency_overrides: appflowy_editor: git: url: https://github.com/AppFlowy-IO/appflowy-editor.git - ref: "9d90053" + ref: "d4d35c0" sheet: git: