feat: observe mention block change and support block navigation (#6568)

* feat: observe mentioned block changes and navigate to block

* test: add delete mentioned block test

* chore: update editor version

* feat: navigate block in same page

* fix: sometimes turn into menu doesn't work

* test: add test

* fix: integration test
This commit is contained in:
Lucas 2024-10-17 13:29:34 +08:00 committed by GitHub
parent 7cad04bbf4
commit 0413100e2b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 296 additions and 34 deletions

View File

@ -1,9 +1,12 @@
import 'package:appflowy/env/cloud_env.dart'; import 'package:appflowy/env/cloud_env.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/document/document_page.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_block.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_block.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_page_block.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_page_block.dart';
import 'package:appflowy/shared/patterns/common_patterns.dart'; import 'package:appflowy/shared/patterns/common_patterns.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
@ -99,6 +102,27 @@ void main() {
// tap the mention block to jump to the page // tap the mention block to jump to the page
await tester.tapButton(find.byType(MentionPageBlock)); await tester.tapButton(find.byType(MentionPageBlock));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
// expect to go to the getting started page
final documentPage = find.byType(DocumentPage);
expect(documentPage, findsOneWidget);
expect(
tester.widget<DocumentPage>(documentPage).view.name,
Constants.gettingStartedPageName,
);
// and the block is selected
expect(
tester.widget<DocumentPage>(documentPage).initialBlockId,
mention[MentionBlockKeys.blockId],
);
expect(
tester.editor.getCurrentEditorState().selection,
Selection.collapsed(
Position(
path: [0],
),
),
);
}); });
testWidgets('copy link to block(same page) and paste it in doc', testWidgets('copy link to block(same page) and paste it in doc',
@ -168,6 +192,84 @@ void main() {
), ),
findsNWidgets(2), findsNWidgets(2),
); );
// tap the mention block
await tester.tapButton(find.byType(MentionPageBlock));
expect(
tester.editor.getCurrentEditorState().selection,
Selection.collapsed(
Position(
path: [0],
),
),
);
});
testWidgets('''1. copy link to block from another page
2. paste the link to the new page
3. delete the original page
4. check the content of the block, it should be no access to the page
''', (tester) async {
await tester.initializeAppFlowy(
cloudType: AuthenticatorType.appflowyCloudSelfHost,
);
await tester.tapGoogleLoginInButton();
await tester.expectToSeeHomePageWithGetStartedPage();
// open getting started page
await tester.openPage(Constants.gettingStartedPageName);
await tester.editor.copyLinkToBlock([0]);
// create a new page and paste it
const pageName = 'copy link to block';
await tester.createNewPageInSpace(
spaceName: Constants.generalSpaceName,
layout: ViewLayoutPB.Document,
pageName: pageName,
);
// paste the link to the new page
await tester.editor.tapLineOfEditorAt(0);
await tester.editor.paste();
await tester.pumpAndSettle();
// tap the mention block to jump to the page
await tester.tapButton(find.byType(MentionPageBlock));
await tester.pumpAndSettle();
// expect to go to the getting started page
final documentPage = find.byType(DocumentPage);
expect(documentPage, findsOneWidget);
expect(
tester.widget<DocumentPage>(documentPage).view.name,
Constants.gettingStartedPageName,
);
// delete the getting started page
await tester.hoverOnPageName(
Constants.gettingStartedPageName,
onHover: () async => tester.tapDeletePageButton(),
);
tester.expectToSeeDocumentBanner();
tester.expectNotToSeePageName(gettingStarted);
// delete the page permanently
await tester.tapDeletePermanentlyButton();
// go back the page
await tester.openPage(pageName);
await tester.pumpAndSettle();
// check the content of the block
// it should be no access to the page
expect(
find.descendant(
of: find.byType(AppFlowyEditor),
matching: find.findTextInFlowyText(
LocaleKeys.document_mention_noAccess.tr(),
),
),
findsOneWidget,
);
}); });
}); });
} }

View File

@ -51,6 +51,7 @@ class DocumentPlugin extends Plugin {
required ViewPB view, required ViewPB view,
required PluginType pluginType, required PluginType pluginType,
this.initialSelection, this.initialSelection,
this.initialBlockId,
}) : notifier = ViewPluginNotifier(view: view) { }) : notifier = ViewPluginNotifier(view: view) {
_pluginType = pluginType; _pluginType = pluginType;
} }
@ -61,13 +62,18 @@ class DocumentPlugin extends Plugin {
@override @override
final ViewPluginNotifier notifier; final ViewPluginNotifier notifier;
// the initial selection of the document
final Selection? initialSelection; final Selection? initialSelection;
// the initial block id of the document
final String? initialBlockId;
@override @override
PluginWidgetBuilder get widgetBuilder => DocumentPluginWidgetBuilder( PluginWidgetBuilder get widgetBuilder => DocumentPluginWidgetBuilder(
bloc: _viewInfoBloc, bloc: _viewInfoBloc,
notifier: notifier, notifier: notifier,
initialSelection: initialSelection, initialSelection: initialSelection,
initialBlockId: initialBlockId,
); );
@override @override
@ -95,6 +101,7 @@ class DocumentPluginWidgetBuilder extends PluginWidgetBuilder
required this.bloc, required this.bloc,
required this.notifier, required this.notifier,
this.initialSelection, this.initialSelection,
this.initialBlockId,
}); });
final ViewInfoBloc bloc; final ViewInfoBloc bloc;
@ -102,6 +109,7 @@ class DocumentPluginWidgetBuilder extends PluginWidgetBuilder
ViewPB get view => notifier.view; ViewPB get view => notifier.view;
int? deletedViewIndex; int? deletedViewIndex;
final Selection? initialSelection; final Selection? initialSelection;
final String? initialBlockId;
@override @override
EdgeInsets get contentPadding => EdgeInsets.zero; EdgeInsets get contentPadding => EdgeInsets.zero;
@ -129,6 +137,7 @@ class DocumentPluginWidgetBuilder extends PluginWidgetBuilder
view: view, view: view,
onDeleted: () => context.onDeleted?.call(view, deletedViewIndex), onDeleted: () => context.onDeleted?.call(view, deletedViewIndex),
initialSelection: initialSelection, initialSelection: initialSelection,
initialBlockId: initialBlockId,
fixedTitle: fixedTitle, fixedTitle: fixedTitle,
), ),
), ),

View File

@ -1,7 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart';
import 'package:appflowy/mobile/application/page_style/document_page_style_bloc.dart'; import 'package:appflowy/mobile/application/page_style/document_page_style_bloc.dart';
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart'; import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
import 'package:appflowy/plugins/document/application/document_bloc.dart'; import 'package:appflowy/plugins/document/application/document_bloc.dart';
@ -21,6 +19,7 @@ import 'package:appflowy/workspace/application/view/prelude.dart';
import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:universal_platform/universal_platform.dart'; import 'package:universal_platform/universal_platform.dart';
@ -31,12 +30,14 @@ class DocumentPage extends StatefulWidget {
required this.view, required this.view,
required this.onDeleted, required this.onDeleted,
this.initialSelection, this.initialSelection,
this.initialBlockId,
this.fixedTitle, this.fixedTitle,
}); });
final ViewPB view; final ViewPB view;
final VoidCallback onDeleted; final VoidCallback onDeleted;
final Selection? initialSelection; final Selection? initialSelection;
final String? initialBlockId;
final String? fixedTitle; final String? fixedTitle;
@override @override
@ -124,13 +125,18 @@ class _DocumentPageState extends State<DocumentPage>
BuildContext context, BuildContext context,
DocumentState state, DocumentState state,
) { ) {
final editorState = state.editorState;
if (editorState == null) {
return const SizedBox.shrink();
}
final width = context.read<DocumentAppearanceCubit>().state.width; final width = context.read<DocumentAppearanceCubit>().state.width;
final Widget child; final Widget child;
if (UniversalPlatform.isMobile) { if (UniversalPlatform.isMobile) {
child = BlocBuilder<DocumentPageStyleBloc, DocumentPageStyleState>( child = BlocBuilder<DocumentPageStyleBloc, DocumentPageStyleState>(
builder: (context, styleState) => AppFlowyEditorPage( builder: (context, styleState) => AppFlowyEditorPage(
editorState: state.editorState!, editorState: editorState,
// if the view's name is empty, focus on the title // if the view's name is empty, focus on the title
autoFocus: widget.view.name.isEmpty ? false : null, autoFocus: widget.view.name.isEmpty ? false : null,
styleCustomizer: EditorStyleCustomizer( styleCustomizer: EditorStyleCustomizer(
@ -145,10 +151,10 @@ class _DocumentPageState extends State<DocumentPage>
} else { } else {
child = EditorDropHandler( child = EditorDropHandler(
viewId: widget.view.id, viewId: widget.view.id,
editorState: state.editorState!, editorState: editorState,
isLocalMode: context.read<DocumentBloc>().isLocalMode, isLocalMode: context.read<DocumentBloc>().isLocalMode,
child: AppFlowyEditorPage( child: AppFlowyEditorPage(
editorState: state.editorState!, editorState: editorState,
// if the view's name is empty, focus on the title // if the view's name is empty, focus on the title
autoFocus: widget.view.name.isEmpty ? false : null, autoFocus: widget.view.name.isEmpty ? false : null,
styleCustomizer: EditorStyleCustomizer( styleCustomizer: EditorStyleCustomizer(
@ -157,7 +163,7 @@ class _DocumentPageState extends State<DocumentPage>
padding: EditorStyleCustomizer.documentPadding, padding: EditorStyleCustomizer.documentPadding,
), ),
header: buildCoverAndIcon(context, state), header: buildCoverAndIcon(context, state),
initialSelection: widget.initialSelection, initialSelection: _calculateInitialSelection(editorState),
), ),
); );
} }
@ -242,16 +248,54 @@ class _DocumentPageState extends State<DocumentPage>
BuildContext context, BuildContext context,
ActionNavigationState state, ActionNavigationState state,
) { ) {
if (state.action != null && state.action!.type == ActionType.jumpToBlock) { final action = state.action;
final path = state.action?.arguments?[ActionArgumentKeys.nodePath]; if (action == null ||
action.type != ActionType.jumpToBlock ||
action.objectId != widget.view.id) {
return;
}
final editorState = context.read<DocumentBloc>().state.editorState; final editorState = context.read<DocumentBloc>().state.editorState;
if (editorState != null && widget.view.id == state.action?.objectId) { if (editorState == null) {
editorState.updateSelectionWithReason( return;
Selection.collapsed(Position(path: [path])), }
);
final Path? path = _getPathFromAction(action, editorState);
if (path != null) {
debugPrint('jump to block: $path');
editorState.updateSelectionWithReason(
Selection.collapsed(Position(path: path)),
);
}
}
Path? _getPathFromAction(NavigationAction action, EditorState editorState) {
Path? path = action.arguments?[ActionArgumentKeys.nodePath];
if (path == null || path.isEmpty) {
final blockId = action.arguments?[ActionArgumentKeys.blockId];
if (blockId != null) {
path = _findNodePathByBlockId(editorState, blockId);
} }
} }
return path;
}
Path? _findNodePathByBlockId(EditorState editorState, String blockId) {
final document = editorState.document;
final startNode = document.root.children.firstOrNull;
if (startNode == null) {
return null;
}
final nodeIterator = NodeIterator(document: document, startNode: startNode);
while (nodeIterator.moveNext()) {
final node = nodeIterator.current;
if (node.id == blockId) {
return node.path;
}
}
return null;
} }
bool shouldRebuildDocument(DocumentState previous, DocumentState current) { bool shouldRebuildDocument(DocumentState previous, DocumentState current) {
@ -362,4 +406,24 @@ class _DocumentPageState extends State<DocumentPage>
isPaste = false; isPaste = false;
} }
} }
Selection? _calculateInitialSelection(EditorState editorState) {
if (widget.initialSelection != null) {
return widget.initialSelection;
}
if (widget.initialBlockId != null) {
final path = _findNodePathByBlockId(editorState, widget.initialBlockId!);
if (path != null) {
editorState.selectionType = SelectionType.block;
return Selection.collapsed(
Position(
path: path,
),
);
}
}
return null;
}
} }

View File

@ -177,8 +177,14 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage>
focusManager = AFFocusManager.maybeOf(context); focusManager = AFFocusManager.maybeOf(context);
focusManager?.loseFocusNotifier.addListener(_loseFocus); focusManager?.loseFocusNotifier.addListener(_loseFocus);
if (widget.initialSelection != null) { final initialSelection = widget.initialSelection;
widget.editorState.updateSelectionWithReason(widget.initialSelection); final path = initialSelection?.start.path;
if (initialSelection != null && path != null && path.isNotEmpty) {
editorScrollController.itemScrollController.jumpTo(
index: path.first,
alignment: 0.5,
);
widget.editorState.updateSelectionWithReason(initialSelection);
} }
widget.editorState.service.keyboardService?.registerInterceptor( widget.editorState.service.keyboardService?.registerInterceptor(

View File

@ -12,12 +12,14 @@ class BlockActionButton extends StatelessWidget {
required this.richMessage, required this.richMessage,
required this.onTap, required this.onTap,
this.showTooltip = true, this.showTooltip = true,
this.onPointerDown,
}); });
final FlowySvgData svg; final FlowySvgData svg;
final bool showTooltip; final bool showTooltip;
final InlineSpan richMessage; final InlineSpan richMessage;
final VoidCallback onTap; final VoidCallback onTap;
final VoidCallback? onPointerDown;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -26,6 +28,7 @@ class BlockActionButton extends StatelessWidget {
? SystemMouseCursors.click ? SystemMouseCursors.click
: SystemMouseCursors.grab, : SystemMouseCursors.grab,
child: IgnoreParentGestureWidget( child: IgnoreParentGestureWidget(
onPress: onPointerDown,
child: GestureDetector( child: GestureDetector(
onTap: onTap, onTap: onTap,
behavior: HitTestBehavior.deferToChild, behavior: HitTestBehavior.deferToChild,

View File

@ -324,6 +324,11 @@ class _OptionButtonState extends State<_OptionButton> {
), ),
], ],
), ),
onPointerDown: () {
if (widget.editorState.selection != null) {
beforeSelection = widget.editorState.selection;
}
},
onTap: () { onTap: () {
if (widget.editorState.selection != null) { if (widget.editorState.selection != null) {
beforeSelection = widget.editorState.selection; beforeSelection = widget.editorState.selection;
@ -369,6 +374,7 @@ class _OptionButtonState extends State<_OptionButton> {
} else { } else {
beforeSelection = null; beforeSelection = null;
} }
return result; return result;
} }
} }

View File

@ -7,12 +7,24 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/me
import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mobile_page_selector_sheet.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mobile_page_selector_sheet.dart';
import 'package:appflowy/plugins/trash/application/trash_service.dart'; import 'package:appflowy/plugins/trash/application/trash_service.dart';
import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart'; import 'package:appflowy/workspace/application/action_navigation/action_navigation_bloc.dart';
import 'package:appflowy/workspace/application/action_navigation/navigation_action.dart';
import 'package:appflowy/workspace/application/view/prelude.dart'; import 'package:appflowy/workspace/application/view/prelude.dart';
import 'package:appflowy/workspace/application/view/view_ext.dart'; import 'package:appflowy/workspace/application/view/view_ext.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
import 'package:appflowy_editor/appflowy_editor.dart' import 'package:appflowy_editor/appflowy_editor.dart'
show Delta, EditorState, Node, TextInsert, TextTransaction, paragraphNode; show
Delta,
EditorState,
Node,
TextInsert,
TextTransaction,
paragraphNode,
NodeIterator,
Path,
Selection,
Position,
SelectionType;
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart';
@ -116,14 +128,37 @@ class _MentionPageBlockState extends State<MentionPageBlock> {
} }
Future<void> handleTap(ViewPB view) async { Future<void> handleTap(ViewPB view) async {
final blockId = widget.blockId;
final currentViewId = context.read<DocumentBloc>().documentId;
if (currentViewId == widget.pageId && blockId != null) {
// same page
final path = _findNodePathByBlockId(editorState, blockId);
if (path != null) {
editorState.scrollService?.jumpTo(path.first);
await editorState.updateSelectionWithReason(
Selection.collapsed(Position(path: path)),
customSelectionType: SelectionType.block,
);
}
return;
}
if (UniversalPlatform.isMobile) { if (UniversalPlatform.isMobile) {
final currentViewId = context.read<DocumentBloc>().documentId;
if (mounted && currentViewId != widget.pageId) { if (mounted && currentViewId != widget.pageId) {
await context.pushView(view); await context.pushView(view);
} }
} else { } else {
getIt<TabsBloc>().add( final action = NavigationAction(
TabsEvent.openPlugin(plugin: view.plugin(), view: view), objectId: view.id,
arguments: {
ActionArgumentKeys.view: view,
ActionArgumentKeys.blockId: blockId,
},
);
getIt<ActionNavigationBloc>().add(
ActionNavigationEvent.performAction(
action: action,
),
); );
} }
} }
@ -188,6 +223,27 @@ class _MentionPageBlockState extends State<MentionPageBlock> {
); );
}); });
} }
Path? _findNodePathByBlockId(EditorState editorState, String blockId) {
final document = editorState.document;
final startNode = document.root.children.firstOrNull;
if (startNode == null) {
return null;
}
final nodeIterator = NodeIterator(
document: document,
startNode: startNode,
);
while (nodeIterator.moveNext()) {
final node = nodeIterator.current;
if (node.id == blockId) {
return node.path;
}
}
return null;
}
} }
class _MentionPageBlockContent extends StatelessWidget { class _MentionPageBlockContent extends StatelessWidget {
@ -225,12 +281,15 @@ class _MentionPageBlockContent extends StatelessWidget {
), ),
], ],
const HSpace(2), const HSpace(2),
FlowyText( Flexible(
text, child: FlowyText(
decoration: TextDecoration.underline, text,
fontSize: textStyle?.fontSize, decoration: TextDecoration.underline,
fontWeight: textStyle?.fontWeight, fontSize: textStyle?.fontSize,
lineHeight: textStyle?.height, fontWeight: textStyle?.fontWeight,
lineHeight: textStyle?.height,
overflow: TextOverflow.ellipsis,
),
), ),
const HSpace(4), const HSpace(4),
], ],

View File

@ -17,6 +17,7 @@ import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
import 'package:appflowy/workspace/application/view/view_ext.dart'; import 'package:appflowy/workspace/application/view/view_ext.dart';
import 'package:appflowy/workspace/presentation/command_palette/command_palette.dart'; import 'package:appflowy/workspace/presentation/command_palette/command_palette.dart';
import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/theme.dart';
@ -176,12 +177,17 @@ class _ApplicationWidgetState extends State<ApplicationWidget> {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (action?.type == ActionType.openView && if (action?.type == ActionType.openView &&
UniversalPlatform.isDesktop) { UniversalPlatform.isDesktop) {
final view = action!.arguments?[ActionArgumentKeys.view]; final view =
action!.arguments?[ActionArgumentKeys.view] as ViewPB?;
final nodePath = action.arguments?[ActionArgumentKeys.nodePath]; final nodePath = action.arguments?[ActionArgumentKeys.nodePath];
final blockId = action.arguments?[ActionArgumentKeys.blockId];
if (view != null) { if (view != null) {
getIt<TabsBloc>().openPlugin( getIt<TabsBloc>().openPlugin(
view.plugin(), view,
arguments: {PluginArgumentKeys.selection: nodePath}, arguments: {
PluginArgumentKeys.selection: nodePath,
PluginArgumentKeys.blockId: blockId,
},
); );
} }
} else if (action?.type == ActionType.openRow && } else if (action?.type == ActionType.openRow &&

View File

@ -7,6 +7,7 @@ enum ActionType {
class ActionArgumentKeys { class ActionArgumentKeys {
static String view = "view"; static String view = "view";
static String nodePath = "node_path"; static String nodePath = "node_path";
static String blockId = "block_id";
static String rowId = "row_id"; static String rowId = "row_id";
} }

View File

@ -22,6 +22,7 @@ import 'package:flutter/material.dart';
class PluginArgumentKeys { class PluginArgumentKeys {
static String selection = "selection"; static String selection = "selection";
static String rowId = "row_id"; static String rowId = "row_id";
static String blockId = "block_id";
} }
class ViewExtKeys { class ViewExtKeys {
@ -90,11 +91,13 @@ extension ViewExtension on ViewPB {
case ViewLayoutPB.Document: case ViewLayoutPB.Document:
final Selection? initialSelection = final Selection? initialSelection =
arguments[PluginArgumentKeys.selection]; arguments[PluginArgumentKeys.selection];
final String? initialBlockId = arguments[PluginArgumentKeys.blockId];
return DocumentPlugin( return DocumentPlugin(
view: this, view: this,
pluginType: pluginType, pluginType: pluginType,
initialSelection: initialSelection, initialSelection: initialSelection,
initialBlockId: initialBlockId,
); );
case ViewLayoutPB.Chat: case ViewLayoutPB.Chat:
return AIChatPagePlugin(view: this); return AIChatPagePlugin(view: this);

View File

@ -219,6 +219,11 @@ class HomeSideBar extends StatelessWidget {
); );
} }
final blockId = action.arguments?[ActionArgumentKeys.blockId];
if (blockId != null) {
arguments[PluginArgumentKeys.blockId] = blockId;
}
final rowId = action.arguments?[ActionArgumentKeys.rowId]; final rowId = action.arguments?[ActionArgumentKeys.rowId];
if (rowId != null) { if (rowId != null) {
arguments[PluginArgumentKeys.rowId] = rowId; arguments[PluginArgumentKeys.rowId] = rowId;

View File

@ -78,10 +78,8 @@ class _AccountDeletionButtonState extends State<AccountDeletionButton> {
radius: Corners.s8Border, radius: Corners.s8Border,
hoverColor: Theme.of(context).colorScheme.error.withOpacity(0.1), hoverColor: Theme.of(context).colorScheme.error.withOpacity(0.1),
fontColor: Theme.of(context).colorScheme.error, fontColor: Theme.of(context).colorScheme.error,
fontHoverColor: Colors.white,
fontSize: 12, fontSize: 12,
isDangerous: true, isDangerous: true,
lineHeight: 18.0 / 12.0,
onPressed: () { onPressed: () {
isCheckedNotifier.value = false; isCheckedNotifier.value = false;
textEditingController.clear(); textEditingController.clear();

View File

@ -53,8 +53,8 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
path: "." path: "."
ref: bcd1208 ref: "4509123"
resolved-ref: bcd12082fea75cdbbea8b090bf938aae7dc9f4ad resolved-ref: "450912305a2cdf98776b09ad4dbdb11498bdf9ce"
url: "https://github.com/AppFlowy-IO/appflowy-editor.git" url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
source: git source: git
version: "4.0.0" version: "4.0.0"

View File

@ -171,7 +171,7 @@ dependency_overrides:
appflowy_editor: appflowy_editor:
git: git:
url: https://github.com/AppFlowy-IO/appflowy-editor.git url: https://github.com/AppFlowy-IO/appflowy-editor.git
ref: "bcd1208" ref: "4509123"
appflowy_editor_plugins: appflowy_editor_plugins:
git: git: