Skip to content

Commit b9b6733

Browse files
committed
fix: toolbar and link hover menu will not display together
1 parent d0bf641 commit b9b6733

7 files changed

Lines changed: 73 additions & 47 deletions

File tree

frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/desktop_toolbar/desktop_floating_toolbar.dart

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import 'package:appflowy/plugins/document/presentation/editor_plugins/base/toolbar_extension.dart';
2+
import 'package:appflowy/startup/startup.dart';
23
import 'package:appflowy_editor/appflowy_editor.dart';
34
import 'package:flutter/material.dart';
4-
import 'package:flutter_bloc/flutter_bloc.dart';
55

66
import 'toolbar_animation.dart';
7-
import 'toolbar_cubit.dart';
87

98
class DesktopFloatingToolbar extends StatefulWidget {
109
const DesktopFloatingToolbar({
@@ -39,24 +38,32 @@ class _DesktopFloatingToolbarState extends State<DesktopFloatingToolbar> {
3938
final selectionRect = editorState.selectionRects();
4039
if (selectionRect.isEmpty) return;
4140
position = calculateSelectionMenuOffset(selectionRect.first);
41+
getIt<FloatingToolbarController>()._addCallback(dismiss);
42+
}
43+
44+
@override
45+
void dispose() {
46+
getIt<FloatingToolbarController>()._removeCallback(dismiss);
47+
super.dispose();
4248
}
4349

4450
@override
4551
Widget build(BuildContext context) {
4652
if (position == null) return Container();
47-
return BlocProvider<ToolbarCubit>(
48-
create: (_) => ToolbarCubit(widget.onDismiss),
49-
child: Positioned(
50-
left: position!.left,
51-
top: position!.top,
52-
right: position!.right,
53-
child: widget.enableAnimation
54-
? ToolbarAnimationWidget(child: widget.child)
55-
: widget.child,
56-
),
53+
return Positioned(
54+
left: position!.left,
55+
top: position!.top,
56+
right: position!.right,
57+
child: widget.enableAnimation
58+
? ToolbarAnimationWidget(child: widget.child)
59+
: widget.child,
5760
);
5861
}
5962

63+
void dismiss() {
64+
widget.onDismiss.call();
65+
}
66+
6067
_Position calculateSelectionMenuOffset(
6168
Rect rect,
6269
) {
@@ -92,3 +99,33 @@ class _Position {
9299
final double? top;
93100
final double? right;
94101
}
102+
103+
class FloatingToolbarController {
104+
final Set<VoidCallback> _dismissCallbacks = {};
105+
final Set<VoidCallback> _displayListeners = {};
106+
107+
void _addCallback(VoidCallback callback) {
108+
_dismissCallbacks.add(callback);
109+
for (final listener in Set.of(_displayListeners)) {
110+
listener.call();
111+
}
112+
}
113+
114+
void _removeCallback(VoidCallback callback) =>
115+
_dismissCallbacks.remove(callback);
116+
117+
bool get isToolbarShowing => _dismissCallbacks.isNotEmpty;
118+
119+
void addDisplayListener(VoidCallback listener) =>
120+
_displayListeners.add(listener);
121+
122+
void removeDisplayListener(VoidCallback listener) =>
123+
_displayListeners.remove(listener);
124+
125+
void hideToolbar() {
126+
if (_dismissCallbacks.isEmpty) return;
127+
for (final callback in _dismissCallbacks) {
128+
callback.call();
129+
}
130+
}
131+
}

frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/desktop_toolbar/link/link_hover_menu.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:appflowy/core/helpers/url_launcher.dart';
44
import 'package:appflowy/generated/flowy_svgs.g.dart';
55
import 'package:appflowy/generated/locale_keys.g.dart';
66
import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_paste/clipboard_service.dart';
7+
import 'package:appflowy/plugins/document/presentation/editor_plugins/desktop_toolbar/desktop_floating_toolbar.dart';
78
import 'package:appflowy/plugins/document/presentation/editor_plugins/header/emoji_icon_widget.dart';
89
import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_page_block.dart';
910
import 'package:appflowy/plugins/document/presentation/editor_plugins/toolbar_item/custom_link_toolbar_item.dart';
@@ -50,6 +51,7 @@ class LinkHoverTrigger extends StatefulWidget {
5051
class _LinkHoverTriggerState extends State<LinkHoverTrigger> {
5152
final hoverMenuController = PopoverController();
5253
final editMenuController = PopoverController();
54+
final toolbarController = getIt<FloatingToolbarController>();
5355
bool isHoverMenuShowing = false;
5456
bool isHoverMenuHovering = false;
5557
bool isHoverTriggerHovering = false;
@@ -68,13 +70,15 @@ class _LinkHoverTriggerState extends State<LinkHoverTrigger> {
6870
void initState() {
6971
super.initState();
7072
getIt<LinkHoverTriggers>()._add(triggerKey, showLinkHoverMenu);
73+
toolbarController.addDisplayListener(onToolbarShow);
7174
}
7275

7376
@override
7477
void dispose() {
7578
hoverMenuController.close();
7679
editMenuController.close();
7780
getIt<LinkHoverTriggers>()._remove(triggerKey, showLinkHoverMenu);
81+
toolbarController.removeDisplayListener(onToolbarShow);
7882
super.dispose();
7983
}
8084

@@ -184,8 +188,10 @@ class _LinkHoverTriggerState extends State<LinkHoverTrigger> {
184188
);
185189
}
186190

191+
void onToolbarShow() => hoverMenuController.close();
192+
187193
void showLinkHoverMenu() {
188-
if (isHoverMenuShowing) return;
194+
if (isHoverMenuShowing || toolbarController.isToolbarShowing) return;
189195
keepEditorFocusNotifier.increase();
190196
hoverMenuController.show();
191197
}

frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/desktop_toolbar/toolbar_cubit.dart

Lines changed: 0 additions & 17 deletions
This file was deleted.

frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/toolbar_item/custom_link_toolbar_item.dart

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
import 'package:appflowy/generated/flowy_svgs.g.dart';
22
import 'package:appflowy/plugins/document/presentation/editor_plugins/base/toolbar_extension.dart';
3+
import 'package:appflowy/plugins/document/presentation/editor_plugins/desktop_toolbar/desktop_floating_toolbar.dart';
34
import 'package:appflowy/plugins/document/presentation/editor_plugins/desktop_toolbar/link/link_create_menu.dart';
45
import 'package:appflowy/plugins/document/presentation/editor_plugins/desktop_toolbar/link/link_hover_menu.dart';
5-
import 'package:appflowy/plugins/document/presentation/editor_plugins/desktop_toolbar/toolbar_cubit.dart';
66
import 'package:appflowy/plugins/document/presentation/editor_style.dart';
77
import 'package:appflowy/startup/startup.dart';
88
import 'package:appflowy/util/theme_extension.dart';
99
import 'package:appflowy_editor/appflowy_editor.dart';
1010
import 'package:flowy_infra/theme_extension_v2.dart';
1111
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
1212
import 'package:flutter/material.dart';
13-
import 'package:flutter_bloc/flutter_bloc.dart';
14-
1513
import 'toolbar_id_enum.dart';
1614

1715
const kIsPageLink = 'is_page_link';
@@ -34,7 +32,6 @@ final customLinkItem = ToolbarItem(
3432
final hoverColor = isHref
3533
? highlightColor
3634
: EditorStyleCustomizer.toolbarHoverColor(context);
37-
final toolbarCubit = context.read<ToolbarCubit?>();
3835

3936
final child = FlowyIconButton(
4037
width: 36,
@@ -45,11 +42,11 @@ final customLinkItem = ToolbarItem(
4542
FlowySvgs.toolbar_link_m,
4643
size: Size.square(20.0),
4744
color: (isDark && isHref)
48-
? Color(0xFF282E3A)
49-
: AFThemeExtensionV2.of(context).icon_primary,
45+
? Color(0xFF282E3A)
46+
: AFThemeExtensionV2.of(context).icon_primary,
5047
),
5148
onPressed: () {
52-
toolbarCubit?.dismiss();
49+
getIt<FloatingToolbarController>().hideToolbar();
5350
if (isHref) {
5451
getIt<LinkHoverTriggers>().call(
5552
HoverTriggerKey(nodes.first.id, selection),

frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/toolbar_item/more_option_toolbar_item.dart

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import 'package:appflowy/generated/flowy_svgs.g.dart';
22
import 'package:appflowy/generated/locale_keys.g.dart';
33
import 'package:appflowy/plugins/document/presentation/editor_page.dart';
4+
import 'package:appflowy/plugins/document/presentation/editor_plugins/desktop_toolbar/desktop_floating_toolbar.dart';
45
import 'package:appflowy/plugins/document/presentation/editor_plugins/desktop_toolbar/link/link_create_menu.dart';
56
import 'package:appflowy/plugins/document/presentation/editor_plugins/desktop_toolbar/link/link_hover_menu.dart';
6-
import 'package:appflowy/plugins/document/presentation/editor_plugins/desktop_toolbar/toolbar_cubit.dart';
77
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
88
import 'package:appflowy/plugins/document/presentation/editor_style.dart';
99
import 'package:appflowy/startup/startup.dart';
@@ -14,7 +14,6 @@ import 'package:appflowy_editor/src/editor/toolbar/desktop/items/utils/tooltip_u
1414
import 'package:easy_localization/easy_localization.dart';
1515
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
1616
import 'package:flutter/material.dart';
17-
import 'package:flutter_bloc/flutter_bloc.dart';
1817

1918
import 'custom_text_align_toolbar_item.dart';
2019
import 'text_suggestions_toolbar_item.dart';
@@ -288,7 +287,7 @@ class _MoreOptionActionListState extends State<MoreOptionActionList> {
288287
popoverController: suggestionsPopoverController,
289288
popoverDirection: PopoverDirection.leftWithTopAligned,
290289
showOffset: Offset(-8, height),
291-
onSelect: () => context.read<ToolbarCubit?>()?.dismiss(),
290+
onSelect: () => getIt<FloatingToolbarController>().hideToolbar(),
292291
child: buildCommandItem(
293292
MoreOptionCommand.suggestions,
294293
rightIcon: FlowySvg(FlowySvgs.toolbar_arrow_right_m),
@@ -308,7 +307,7 @@ class _MoreOptionActionListState extends State<MoreOptionActionList> {
308307
popoverController: textAlignPopoverController,
309308
popoverDirection: PopoverDirection.leftWithTopAligned,
310309
showOffset: Offset(-8, 0),
311-
onSelect: () => context.read<ToolbarCubit?>()?.dismiss(),
310+
onSelect: () => getIt<FloatingToolbarController>().hideToolbar(),
312311
highlightColor: highlightColor,
313312
child: buildCommandItem(
314313
MoreOptionCommand.textAlign,
@@ -379,7 +378,7 @@ enum MoreOptionCommand {
379378
(attributes) => attributes[AppFlowyRichTextKeys.href] != null,
380379
);
381380
});
382-
context.read<ToolbarCubit?>()?.dismiss();
381+
getIt<FloatingToolbarController>().hideToolbar();
383382
if (isHref) {
384383
getIt<LinkHoverTriggers>().call(
385384
HoverTriggerKey(nodes.first.id, selection),

frontend/appflowy_flutter/lib/startup/startup.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'dart:async';
22
import 'dart:io';
33

44
import 'package:appflowy/env/cloud_env.dart';
5+
import 'package:appflowy/plugins/document/presentation/editor_plugins/desktop_toolbar/desktop_floating_toolbar.dart';
56
import 'package:appflowy/plugins/document/presentation/editor_plugins/desktop_toolbar/link/link_hover_menu.dart';
67
import 'package:appflowy/util/expand_views.dart';
78
import 'package:appflowy/workspace/application/settings/prelude.dart';
@@ -187,6 +188,9 @@ Future<void> initGetIt(
187188
getIt.registerSingleton<PluginSandbox>(PluginSandbox());
188189
getIt.registerSingleton<ViewExpanderRegistry>(ViewExpanderRegistry());
189190
getIt.registerSingleton<LinkHoverTriggers>(LinkHoverTriggers());
191+
getIt.registerSingleton<FloatingToolbarController>(
192+
FloatingToolbarController(),
193+
);
190194

191195
await DependencyResolver.resolve(getIt, mode);
192196
}

frontend/appflowy_flutter/packages/flowy_infra/lib/theme_extension_v2.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ class AFThemeExtensionV2 extends ThemeExtension<AFThemeExtensionV2> {
4141
border_grey_quaternary:
4242
border_grey_quaternary ?? this.border_grey_quaternary,
4343
fill_theme_select: fill_theme_select ?? this.fill_theme_select,
44-
fill_grey_thick_alpha_1:fill_grey_thick_alpha_1 ?? this.fill_grey_thick_alpha_1,
45-
shadow_medium:shadow_medium ?? this.shadow_medium,
44+
fill_grey_thick_alpha_1:
45+
fill_grey_thick_alpha_1 ?? this.fill_grey_thick_alpha_1,
46+
shadow_medium: shadow_medium ?? this.shadow_medium,
4647
);
4748

4849
@override
@@ -65,9 +66,8 @@ class AFThemeExtensionV2 extends ThemeExtension<AFThemeExtensionV2> {
6566
fill_grey_thick_alpha_1: Color.lerp(
6667
fill_grey_thick_alpha_1, other.fill_grey_thick_alpha_1, t) ??
6768
fill_grey_thick_alpha_1,
68-
shadow_medium: Color.lerp(
69-
shadow_medium, other.shadow_medium, t) ??
70-
shadow_medium,
69+
shadow_medium:
70+
Color.lerp(shadow_medium, other.shadow_medium, t) ?? shadow_medium,
7171
);
7272
}
7373
}

0 commit comments

Comments
 (0)