diff --git a/lib/controllers/emoji.dart b/lib/controllers/emoji.dart index caea3de..0c89896 100644 --- a/lib/controllers/emoji.dart +++ b/lib/controllers/emoji.dart @@ -1,6 +1,7 @@ import "dart:convert"; import "package:emoji_text_field/models/emoji_category.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart"; +import "package:flutter/foundation.dart"; import "package:flutter/material.dart"; import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:http/http.dart"; @@ -19,9 +20,12 @@ class EmojiController extends AsyncNotifier { throw Exception("Failed to load emoji data"); } - final data = json.decode(response.body); + return compute(_parseEmojiJson, response.body); + } - final entries = (data as List) + static EmojiTuple _parseEmojiJson(String body) { + final data = json.decode(body) as List; + final entries = data .cast>() .map(Emoji.fromJson) .toIList(); diff --git a/lib/widgets/emoji_picker_button.dart b/lib/widgets/emoji_picker_button.dart index 2ac906a..3516590 100644 --- a/lib/widgets/emoji_picker_button.dart +++ b/lib/widgets/emoji_picker_button.dart @@ -20,32 +20,46 @@ class EmojiPickerButton extends HookConsumerWidget { Widget build(_, WidgetRef ref) => IconButton( onPressed: () async { onPressed?.call(); - final controller = this.controller ?? .new(); + + final tempController = controller ?? TextEditingController(); + final shouldDispose = controller == null; + var hasPopped = false; + + void handler() { + if (tempController.text.isEmpty || hasPopped) return; + hasPopped = true; + + onSelection?.call(tempController.text); + + WidgetsBinding.instance.addPostFrameCallback((_) { + if (context.mounted) Navigator.of(context).maybePop(); + }); + } final emojis = await ref.watch(EmojiController.provider.future); - if (context.mounted) { - showModalBottomSheet( - context: context, - builder: (context) => EmojiKeyboardView( - config: .new( - showRecentTab: false, - customCategories: emojis.$1.unlock, - customKeywords: emojis.$2.unlock, - backgroundColor: Theme.of(context).colorScheme.surfaceContainer, - height: 600, - ), - textController: controller - ..addListener(() { - // Without this, there will sometimes be a debugLocked is not true error sometimes - // It might be preferable to use a microtask instead of a `Future.delayed`. - Future.delayed(.zero, () { - if (context.mounted) Navigator.of(context).pop(); - }); - onSelection?.call(controller.text); - }), - ), - ); + if (!context.mounted) { + if (shouldDispose) tempController.dispose(); + return; } + + await showModalBottomSheet( + context: context, + builder: (sheetContext) => EmojiKeyboardView( + config: .new( + showRecentTab: false, + customCategories: emojis.$1.unlock, + customKeywords: emojis.$2.unlock, + backgroundColor: Theme.of( + sheetContext, + ).colorScheme.surfaceContainer, + height: 600, + ), + textController: tempController..addListener(handler), + ), + ); + + tempController.removeListener(handler); + if (shouldDispose) tempController.dispose(); }, icon: Icon(Icons.emoji_emotions), );