From 63e2058409c34dc5e0be25bcc3f54ed980cce8d9 Mon Sep 17 00:00:00 2001 From: "Lucas.Xu" Date: Thu, 23 Nov 2023 12:39:13 +0800 Subject: [PATCH] feat: refactor keyboard height observer to support multiple listeners --- .../toolbar/mobile/mobile_toolbar_v2.dart | 35 +++++++++++------- .../utils/keyboard_height_observer.dart | 37 +++++++++++++++++++ 2 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 lib/src/editor/toolbar/mobile/utils/keyboard_height_observer.dart diff --git a/lib/src/editor/toolbar/mobile/mobile_toolbar_v2.dart b/lib/src/editor/toolbar/mobile/mobile_toolbar_v2.dart index 95249b1c0..9e3174766 100644 --- a/lib/src/editor/toolbar/mobile/mobile_toolbar_v2.dart +++ b/lib/src/editor/toolbar/mobile/mobile_toolbar_v2.dart @@ -1,6 +1,8 @@ import 'package:appflowy_editor/appflowy_editor.dart'; +import 'package:appflowy_editor/src/editor/toolbar/mobile/utils/keyboard_height_observer.dart'; import 'package:flutter/material.dart'; -import 'package:keyboard_height_plugin/keyboard_height_plugin.dart'; + +const String disableMobileToolbarKey = 'disableMobileToolbar'; class MobileToolbarV2 extends StatefulWidget { const MobileToolbarV2({ @@ -56,7 +58,7 @@ class MobileToolbarV2 extends StatefulWidget { class _MobileToolbarV2State extends State { OverlayEntry? toolbarOverlay; - final keyboardHeightPlugin = KeyboardHeightPlugin(); + final isKeyboardShow = ValueNotifier(false); @override @@ -64,15 +66,13 @@ class _MobileToolbarV2State extends State { super.initState(); _insertKeyboardToolbar(); - keyboardHeightPlugin.onKeyboardHeightChanged((height) { - isKeyboardShow.value = height > 0; - }); + KeyboardHeightObserver.instance.addListener(_onKeyboardHeightChanged); } @override void dispose() { _removeKeyboardToolbar(); - keyboardHeightPlugin.dispose(); + KeyboardHeightObserver.instance.removeListener(_onKeyboardHeightChanged); super.dispose(); } @@ -97,6 +97,10 @@ class _MobileToolbarV2State extends State { ); } + void _onKeyboardHeightChanged(double height) { + isKeyboardShow.value = height > 0; + } + void _removeKeyboardToolbar() { toolbarOverlay?.remove(); toolbarOverlay?.dispose(); @@ -110,7 +114,9 @@ class _MobileToolbarV2State extends State { valueListenable: widget.editorState.selectionNotifier, builder: (_, Selection? selection, __) { // if the selection is null, hide the toolbar - if (selection == null) { + if (selection == null || + widget.editorState.selectionExtraInfo?[disableMobileToolbarKey] == + true) { return const SizedBox.shrink(); } @@ -190,7 +196,6 @@ class _MobileToolbarState extends State<_MobileToolbar> // This is because we want to keep the same height when the menu is shown. bool canUpdateCachedKeyboardHeight = true; ValueNotifier cachedKeyboardHeight = ValueNotifier(0.0); - final keyboardHeightPlugin = KeyboardHeightPlugin(); // used to check if click the same item again int? selectedMenuIndex; @@ -202,11 +207,7 @@ class _MobileToolbarState extends State<_MobileToolbar> super.initState(); currentSelection = widget.editorState.selection; - keyboardHeightPlugin.onKeyboardHeightChanged((height) { - if (canUpdateCachedKeyboardHeight) { - cachedKeyboardHeight.value = height; - } - }); + KeyboardHeightObserver.instance.addListener(_onKeyboardHeightChanged); } @override @@ -223,7 +224,7 @@ class _MobileToolbarState extends State<_MobileToolbar> void dispose() { showMenuNotifier.dispose(); cachedKeyboardHeight.dispose(); - keyboardHeightPlugin.dispose(); + KeyboardHeightObserver.instance.removeListener(_onKeyboardHeightChanged); super.dispose(); } @@ -259,6 +260,12 @@ class _MobileToolbarState extends State<_MobileToolbar> showMenuNotifier.value = true; } + void _onKeyboardHeightChanged(double height) { + if (canUpdateCachedKeyboardHeight) { + cachedKeyboardHeight.value = height; + } + } + // toolbar list view and close keyboard/menu button Widget _buildToolbar(BuildContext context) { final width = MediaQuery.of(context).size.width; diff --git a/lib/src/editor/toolbar/mobile/utils/keyboard_height_observer.dart b/lib/src/editor/toolbar/mobile/utils/keyboard_height_observer.dart new file mode 100644 index 000000000..557c11c14 --- /dev/null +++ b/lib/src/editor/toolbar/mobile/utils/keyboard_height_observer.dart @@ -0,0 +1,37 @@ +import 'package:keyboard_height_plugin/keyboard_height_plugin.dart'; + +typedef KeyboardHeightCallback = void Function(double height); + +// the KeyboardHeightPlugin only accepts one listener, so we need to create a +// singleton class to manage the multiple listeners. +class KeyboardHeightObserver { + KeyboardHeightObserver._() { + _keyboardHeightPlugin.onKeyboardHeightChanged((height) { + notify(height); + }); + } + + static final KeyboardHeightObserver instance = KeyboardHeightObserver._(); + + final List _listeners = []; + final KeyboardHeightPlugin _keyboardHeightPlugin = KeyboardHeightPlugin(); + + void addListener(KeyboardHeightCallback listener) { + _listeners.add(listener); + } + + void removeListener(KeyboardHeightCallback listener) { + _listeners.remove(listener); + } + + void dispose() { + _listeners.clear(); + _keyboardHeightPlugin.dispose(); + } + + void notify(double height) { + for (final listener in _listeners) { + listener(height); + } + } +}