Skip to content

Commit

Permalink
feat: refactor keyboard height observer to support multiple listeners (
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasXu0 authored Nov 23, 2023
1 parent af9f97e commit 31acaff
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 14 deletions.
35 changes: 21 additions & 14 deletions lib/src/editor/toolbar/mobile/mobile_toolbar_v2.dart
Original file line number Diff line number Diff line change
@@ -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({
Expand Down Expand Up @@ -56,23 +58,21 @@ class MobileToolbarV2 extends StatefulWidget {

class _MobileToolbarV2State extends State<MobileToolbarV2> {
OverlayEntry? toolbarOverlay;
final keyboardHeightPlugin = KeyboardHeightPlugin();

final isKeyboardShow = ValueNotifier(false);

@override
void initState() {
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();
}
Expand All @@ -97,6 +97,10 @@ class _MobileToolbarV2State extends State<MobileToolbarV2> {
);
}

void _onKeyboardHeightChanged(double height) {
isKeyboardShow.value = height > 0;
}

void _removeKeyboardToolbar() {
toolbarOverlay?.remove();
toolbarOverlay?.dispose();
Expand All @@ -110,7 +114,9 @@ class _MobileToolbarV2State extends State<MobileToolbarV2> {
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();
}

Expand Down Expand Up @@ -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<double> cachedKeyboardHeight = ValueNotifier(0.0);
final keyboardHeightPlugin = KeyboardHeightPlugin();

// used to check if click the same item again
int? selectedMenuIndex;
Expand All @@ -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
Expand All @@ -223,7 +224,7 @@ class _MobileToolbarState extends State<_MobileToolbar>
void dispose() {
showMenuNotifier.dispose();
cachedKeyboardHeight.dispose();
keyboardHeightPlugin.dispose();
KeyboardHeightObserver.instance.removeListener(_onKeyboardHeightChanged);

super.dispose();
}
Expand Down Expand Up @@ -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;
Expand Down
37 changes: 37 additions & 0 deletions lib/src/editor/toolbar/mobile/utils/keyboard_height_observer.dart
Original file line number Diff line number Diff line change
@@ -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<KeyboardHeightCallback> _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);
}
}
}

0 comments on commit 31acaff

Please sign in to comment.