From eb20c7c117331b180a4ddb644b943e2da376b7db Mon Sep 17 00:00:00 2001 From: Yijing Huang Date: Wed, 4 Oct 2023 18:36:29 -0700 Subject: [PATCH] feat: emoji picker improvement (#3591) --- .../util/database_test_op.dart | 2 +- .../database_view/widgets/row/row_banner.dart | 3 +- .../document/presentation/editor_page.dart | 1 + .../base/emoji_picker_button.dart | 3 +- .../emoji_picker/emoji_picker.dart | 4 - .../emoji_picker/src/config.dart | 165 - .../emoji_picker/src/emoji_picker.dart | 338 -- .../header/document_header_node_widget.dart | 4 +- .../editor_plugins/header/emoji_popover.dart | 15 +- .../presentation/editor_plugins/plugins.dart | 1 - .../emoji_picker/emoji_menu_item.dart | 12 +- .../widgets/emoji_picker/emoji_picker.dart | 6 + .../src/default_emoji_picker_view.dart | 143 +- .../emoji_picker/src/emji_picker_config.dart | 94 + .../emoji_picker/src/emoji_lists.dart | 0 .../emoji_picker/src/emoji_picker.dart | 102 +- .../src/emoji_picker_builder.dart | 4 +- .../emoji_picker/src/emoji_view_state.dart | 8 +- .../src/flowy_emoji_picker_config.dart | 34 + .../src/models/emoji_category_models.dart} | 44 +- .../emoji_picker/src/models/emoji_model.dart | 0 .../src/models/recent_emoji_model.dart | 0 .../widgets/emoji_picker/emoji_picker.dart | 4 - .../widgets/emoji_picker/src/config.dart | 169 - .../src/default_emoji_picker_view.dart | 321 -- .../widgets/emoji_picker/src/emoji_lists.dart | 3223 ----------------- .../src/emoji_picker_builder.dart | 18 - .../emoji_picker/src/emoji_view_state.dart | 21 - .../src/models/category_models.dart | 91 - .../emoji_picker/src/models/emoji_model.dart | 32 - .../src/models/recent_emoji_model.dart | 30 - .../lib/colorscheme/dandelion.dart | 4 +- .../flowy_infra/lib/colorscheme/lavender.dart | 2 +- .../scrolling/styled_scroll_bar.dart | 7 +- frontend/resources/translations/en.json | 3 + 35 files changed, 302 insertions(+), 4606 deletions(-) delete mode 100644 frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/emoji_picker.dart delete mode 100644 frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/config.dart delete mode 100644 frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/emoji_picker.dart rename frontend/appflowy_flutter/lib/{plugins/document/presentation/editor_plugins => workspace/presentation/settings/widgets}/emoji_picker/emoji_menu_item.dart (89%) create mode 100644 frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/emoji_picker.dart rename frontend/appflowy_flutter/lib/{plugins/document/presentation/editor_plugins => workspace/presentation/settings/widgets}/emoji_picker/src/default_emoji_picker_view.dart (63%) create mode 100644 frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/emji_picker_config.dart rename frontend/appflowy_flutter/lib/{plugins/document/presentation/editor_plugins => workspace/presentation/settings/widgets}/emoji_picker/src/emoji_lists.dart (100%) rename frontend/appflowy_flutter/lib/workspace/presentation/{ => settings}/widgets/emoji_picker/src/emoji_picker.dart (76%) rename frontend/appflowy_flutter/lib/{plugins/document/presentation/editor_plugins => workspace/presentation/settings/widgets}/emoji_picker/src/emoji_picker_builder.dart (86%) rename frontend/appflowy_flutter/lib/{plugins/document/presentation/editor_plugins => workspace/presentation/settings/widgets}/emoji_picker/src/emoji_view_state.dart (65%) create mode 100644 frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/flowy_emoji_picker_config.dart rename frontend/appflowy_flutter/lib/{plugins/document/presentation/editor_plugins/emoji_picker/src/models/category_models.dart => workspace/presentation/settings/widgets/emoji_picker/src/models/emoji_category_models.dart} (62%) rename frontend/appflowy_flutter/lib/{plugins/document/presentation/editor_plugins => workspace/presentation/settings/widgets}/emoji_picker/src/models/emoji_model.dart (100%) rename frontend/appflowy_flutter/lib/{plugins/document/presentation/editor_plugins => workspace/presentation/settings/widgets}/emoji_picker/src/models/recent_emoji_model.dart (100%) delete mode 100644 frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/emoji_picker.dart delete mode 100644 frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/config.dart delete mode 100644 frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/default_emoji_picker_view.dart delete mode 100644 frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/emoji_lists.dart delete mode 100644 frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/emoji_picker_builder.dart delete mode 100644 frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/emoji_view_state.dart delete mode 100644 frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/models/category_models.dart delete mode 100644 frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/models/emoji_model.dart delete mode 100644 frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/models/recent_emoji_model.dart diff --git a/frontend/appflowy_flutter/integration_test/util/database_test_op.dart b/frontend/appflowy_flutter/integration_test/util/database_test_op.dart index b2f4c4a2f2..4458b3adad 100644 --- a/frontend/appflowy_flutter/integration_test/util/database_test_op.dart +++ b/frontend/appflowy_flutter/integration_test/util/database_test_op.dart @@ -54,7 +54,7 @@ import 'package:appflowy/plugins/database_view/widgets/row/row_document.dart'; import 'package:appflowy/plugins/database_view/widgets/row/row_property.dart'; import 'package:appflowy/plugins/database_view/widgets/setting/database_setting.dart'; import 'package:appflowy/plugins/database_view/widgets/setting/setting_button.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/emoji_picker/emoji_menu_item.dart'; +import 'package:appflowy/workspace/presentation/settings/widgets/emoji_picker/emoji_menu_item.dart'; import 'package:appflowy/workspace/presentation/widgets/dialogs.dart'; import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart'; import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/row_banner.dart b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/row_banner.dart index e31b1e3291..8a99d638ee 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/row_banner.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/row_banner.dart @@ -5,8 +5,7 @@ import 'package:appflowy/plugins/database_view/application/field/field_info.dart import 'package:appflowy/plugins/database_view/application/row/row_banner_bloc.dart'; import 'package:appflowy/plugins/database_view/application/row/row_controller.dart'; import 'package:appflowy/plugins/database_view/widgets/row/row_action.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/emoji_picker/emoji_picker.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart'; +import 'package:appflowy/workspace/presentation/settings/widgets/emoji_picker/emoji_picker.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart index 2dfa2b93c7..16b6ba770b 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart @@ -8,6 +8,7 @@ import 'package:appflowy/plugins/inline_actions/inline_actions_command.dart'; import 'package:appflowy/plugins/inline_actions/inline_actions_service.dart'; import 'package:appflowy/workspace/application/appearance.dart'; import 'package:appflowy/workspace/application/settings/shortcuts/settings_shortcuts_service.dart'; +import 'package:appflowy/workspace/presentation/settings/widgets/emoji_picker/emoji_picker.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:collection/collection.dart'; import 'package:flowy_infra/theme_extension.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/emoji_picker_button.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/emoji_picker_button.dart index 19fca1d08b..8b4bf37ffb 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/emoji_picker_button.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/emoji_picker_button.dart @@ -1,5 +1,4 @@ -import 'package:appflowy/plugins/document/presentation/editor_plugins/emoji_picker/emoji_picker.dart'; -import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart'; +import 'package:appflowy/workspace/presentation/settings/widgets/emoji_picker/emoji_picker.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/emoji_picker.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/emoji_picker.dart deleted file mode 100644 index fe4580db04..0000000000 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/emoji_picker.dart +++ /dev/null @@ -1,4 +0,0 @@ -export 'src/config.dart'; -export 'src/emoji_picker.dart'; -export 'src/emoji_picker_builder.dart'; -export 'src/models/emoji_model.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/config.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/config.dart deleted file mode 100644 index e8ddc7f883..0000000000 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/config.dart +++ /dev/null @@ -1,165 +0,0 @@ -import 'dart:math'; - -import 'package:flutter/material.dart'; - -import 'models/category_models.dart'; -import 'emoji_picker.dart'; - -/// Config for customizations -class Config { - /// Constructor - const Config({ - this.columns = 7, - this.emojiSizeMax = 32.0, - this.verticalSpacing = 0, - this.horizontalSpacing = 0, - this.initCategory = Category.RECENT, - this.bgColor = const Color(0xFFEBEFF2), - this.indicatorColor = Colors.blue, - this.iconColor = Colors.grey, - this.iconColorSelected = Colors.blue, - this.progressIndicatorColor = Colors.blue, - this.backspaceColor = Colors.blue, - this.showRecentsTab = true, - this.recentsLimit = 28, - this.noRecentsText = 'No Recents', - this.noRecentsStyle = const TextStyle(fontSize: 20, color: Colors.black26), - this.tabIndicatorAnimDuration = kTabScrollDuration, - this.categoryIcons = const CategoryIcons(), - this.buttonMode = ButtonMode.MATERIAL, - }); - - /// Number of emojis per row - final int columns; - - /// Width and height the emoji will be maximal displayed - /// Can be smaller due to screen size and amount of columns - final double emojiSizeMax; - - /// Vertical spacing between emojis - final double verticalSpacing; - - /// Horizontal spacing between emojis - final double horizontalSpacing; - - /// The initial [Category] that will be selected - /// This [Category] will have its button in the bottombar darkened - final Category initCategory; - - /// The background color of the Widget - final Color bgColor; - - /// The color of the category indicator - final Color indicatorColor; - - /// The color of the category icons - final Color iconColor; - - /// The color of the category icon when selected - final Color iconColorSelected; - - /// The color of the loading indicator during initialization - final Color progressIndicatorColor; - - /// The color of the backspace icon button - final Color backspaceColor; - - /// Show extra tab with recently used emoji - final bool showRecentsTab; - - /// Limit of recently used emoji that will be saved - final int recentsLimit; - - /// The text to be displayed if no recent emojis to display - final String noRecentsText; - - /// The text style for [noRecentsText] - final TextStyle noRecentsStyle; - - /// Duration of tab indicator to animate to next category - final Duration tabIndicatorAnimDuration; - - /// Determines the icon to display for each [Category] - final CategoryIcons categoryIcons; - - /// Change between Material and Cupertino button style - final ButtonMode buttonMode; - - /// Get Emoji size based on properties and screen width - double getEmojiSize(double width) { - final maxSize = width / columns; - return min(maxSize, emojiSizeMax); - } - - /// Returns the icon for the category - IconData getIconForCategory(Category category) { - switch (category) { - case Category.RECENT: - return categoryIcons.recentIcon; - case Category.SMILEYS: - return categoryIcons.smileyIcon; - case Category.ANIMALS: - return categoryIcons.animalIcon; - case Category.FOODS: - return categoryIcons.foodIcon; - case Category.TRAVEL: - return categoryIcons.travelIcon; - case Category.ACTIVITIES: - return categoryIcons.activityIcon; - case Category.OBJECTS: - return categoryIcons.objectIcon; - case Category.SYMBOLS: - return categoryIcons.symbolIcon; - case Category.FLAGS: - return categoryIcons.flagIcon; - case Category.SEARCH: - return categoryIcons.searchIcon; - default: - throw Exception('Unsupported Category'); - } - } - - @override - bool operator ==(other) { - return (other is Config) && - other.columns == columns && - other.emojiSizeMax == emojiSizeMax && - other.verticalSpacing == verticalSpacing && - other.horizontalSpacing == horizontalSpacing && - other.initCategory == initCategory && - other.bgColor == bgColor && - other.indicatorColor == indicatorColor && - other.iconColor == iconColor && - other.iconColorSelected == iconColorSelected && - other.progressIndicatorColor == progressIndicatorColor && - other.backspaceColor == backspaceColor && - other.showRecentsTab == showRecentsTab && - other.recentsLimit == recentsLimit && - other.noRecentsText == noRecentsText && - other.noRecentsStyle == noRecentsStyle && - other.tabIndicatorAnimDuration == tabIndicatorAnimDuration && - other.categoryIcons == categoryIcons && - other.buttonMode == buttonMode; - } - - @override - int get hashCode => - columns.hashCode ^ - emojiSizeMax.hashCode ^ - verticalSpacing.hashCode ^ - horizontalSpacing.hashCode ^ - initCategory.hashCode ^ - bgColor.hashCode ^ - indicatorColor.hashCode ^ - iconColor.hashCode ^ - iconColorSelected.hashCode ^ - progressIndicatorColor.hashCode ^ - backspaceColor.hashCode ^ - showRecentsTab.hashCode ^ - recentsLimit.hashCode ^ - noRecentsText.hashCode ^ - noRecentsStyle.hashCode ^ - tabIndicatorAnimDuration.hashCode ^ - categoryIcons.hashCode ^ - buttonMode.hashCode; -} diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/emoji_picker.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/emoji_picker.dart deleted file mode 100644 index 0a8793a5d5..0000000000 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/emoji_picker.dart +++ /dev/null @@ -1,338 +0,0 @@ -// ignore_for_file: constant_identifier_names - -import 'dart:convert'; -import 'dart:io'; -import 'dart:math'; - -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'models/category_models.dart'; -import 'config.dart'; -import 'default_emoji_picker_view.dart'; -import 'models/emoji_model.dart'; -import 'emoji_lists.dart' as emoji_list; -import 'emoji_view_state.dart'; -import 'models/recent_emoji_model.dart'; - -/// All the possible categories that [Emoji] can be put into -/// -/// All [Category] are shown in the category bar -enum Category { - /// Searched emojis - SEARCH, - - /// Recent emojis - RECENT, - - /// Smiley emojis - SMILEYS, - - /// Animal emojis - ANIMALS, - - /// Food emojis - FOODS, - - /// Activity emojis - ACTIVITIES, - - /// Travel emojis - TRAVEL, - - /// Objects emojis - OBJECTS, - - /// Sumbol emojis - SYMBOLS, - - /// Flag emojis - FLAGS, -} - -/// Enum to alter the keyboard button style -enum ButtonMode { - /// Android button style - gives the button a splash color with ripple effect - MATERIAL, - - /// iOS button style - gives the button a fade out effect when pressed - CUPERTINO -} - -/// Callback function for when emoji is selected -/// -/// The function returns the selected [Emoji] as well -/// as the [Category] from which it originated -typedef OnEmojiSelected = void Function(Category category, Emoji emoji); - -/// Callback function for backspace button -typedef OnBackspacePressed = void Function(); - -/// Callback function for custom view -typedef EmojiViewBuilder = Widget Function(Config config, EmojiViewState state); - -/// The Emoji Keyboard widget -/// -/// This widget displays a grid of [Emoji] sorted by [Category] -/// which the user can horizontally scroll through. -/// -/// There is also a bottombar which displays all the possible [Category] -/// and allow the user to quickly switch to that [Category] -class EmojiPicker extends StatefulWidget { - /// EmojiPicker for flutter - const EmojiPicker({ - Key? key, - required this.onEmojiSelected, - this.onBackspacePressed, - this.config = const Config(), - this.customWidget, - }) : super(key: key); - - /// Custom widget - final EmojiViewBuilder? customWidget; - - /// The function called when the emoji is selected - final OnEmojiSelected onEmojiSelected; - - /// The function called when backspace button is pressed - final OnBackspacePressed? onBackspacePressed; - - /// Config for customizations - final Config config; - - @override - EmojiPickerState createState() => EmojiPickerState(); -} - -class EmojiPickerState extends State { - static const platform = MethodChannel('emoji_picker_flutter'); - - List categoryEmoji = List.empty(growable: true); - List recentEmoji = List.empty(growable: true); - late Future updateEmojiFuture; - - // Prevent emojis to be reloaded with every build - bool loaded = false; - - @override - void initState() { - super.initState(); - updateEmojiFuture = _updateEmojis(); - } - - @override - void didUpdateWidget(covariant EmojiPicker oldWidget) { - if (oldWidget.config != widget.config) { - // Config changed - rebuild EmojiPickerView completely - loaded = false; - updateEmojiFuture = _updateEmojis(); - } - super.didUpdateWidget(oldWidget); - } - - @override - Widget build(BuildContext context) { - if (!loaded) { - // Load emojis - updateEmojiFuture.then( - (value) => WidgetsBinding.instance.addPostFrameCallback((_) { - if (!mounted) return; - setState(() { - loaded = true; - }); - }), - ); - - // Show loading indicator - return const Center(child: CircularProgressIndicator()); - } - if (widget.config.showRecentsTab) { - categoryEmoji[0].emoji = - recentEmoji.map((e) => e.emoji).toList().cast(); - } - - final state = EmojiViewState( - categoryEmoji, - _getOnEmojiListener(), - widget.onBackspacePressed, - ); - - // Build - return widget.customWidget == null - ? DefaultEmojiPickerView(widget.config, state) - : widget.customWidget!(widget.config, state); - } - - // Add recent emoji handling to tap listener - OnEmojiSelected _getOnEmojiListener() { - return (category, emoji) { - if (widget.config.showRecentsTab) { - _addEmojiToRecentlyUsed(emoji).then((value) { - if (category != Category.RECENT && mounted) { - setState(() { - // rebuild to update recent emoji tab - // when it is not current tab - }); - } - }); - } - widget.onEmojiSelected(category, emoji); - }; - } - - // Initialize emoji data - Future _updateEmojis() async { - categoryEmoji.clear(); - if (widget.config.showRecentsTab) { - recentEmoji = await _getRecentEmojis(); - final List recentEmojiMap = - recentEmoji.map((e) => e.emoji).toList().cast(); - categoryEmoji.add(CategoryEmoji(Category.RECENT, recentEmojiMap)); - } - categoryEmoji.addAll([ - CategoryEmoji( - Category.SMILEYS, - await _getAvailableEmojis(emoji_list.smileys, title: 'smileys'), - ), - CategoryEmoji( - Category.ANIMALS, - await _getAvailableEmojis(emoji_list.animals, title: 'animals'), - ), - CategoryEmoji( - Category.FOODS, - await _getAvailableEmojis(emoji_list.foods, title: 'foods'), - ), - CategoryEmoji( - Category.ACTIVITIES, - await _getAvailableEmojis( - emoji_list.activities, - title: 'activities', - ), - ), - CategoryEmoji( - Category.TRAVEL, - await _getAvailableEmojis(emoji_list.travel, title: 'travel'), - ), - CategoryEmoji( - Category.OBJECTS, - await _getAvailableEmojis(emoji_list.objects, title: 'objects'), - ), - CategoryEmoji( - Category.SYMBOLS, - await _getAvailableEmojis(emoji_list.symbols, title: 'symbols'), - ), - CategoryEmoji( - Category.FLAGS, - await _getAvailableEmojis(emoji_list.flags, title: 'flags'), - ) - ]); - } - - // Get available emoji for given category title - Future> _getAvailableEmojis( - Map map, { - required String title, - }) async { - Map? newMap; - - // Get Emojis cached locally if available - newMap = await _restoreFilteredEmojis(title); - - if (newMap == null) { - // Check if emoji is available on this platform - newMap = await _getPlatformAvailableEmoji(map); - // Save available Emojis to local storage for faster loading next time - if (newMap != null) { - await _cacheFilteredEmojis(title, newMap); - } - } - - // Map to Emoji Object - return newMap!.entries - .map((entry) => Emoji(entry.key, entry.value)) - .toList(); - } - - // Check if emoji is available on current platform - Future?> _getPlatformAvailableEmoji( - Map emoji, - ) async { - if (Platform.isAndroid) { - Map? filtered = {}; - const delimiter = '|'; - try { - final entries = emoji.values.join(delimiter); - final keys = emoji.keys.join(delimiter); - final result = (await platform.invokeMethod( - 'checkAvailability', - {'emojiKeys': keys, 'emojiEntries': entries}, - )) as String; - final resultKeys = result.split(delimiter); - for (var i = 0; i < resultKeys.length; i++) { - filtered[resultKeys[i]] = emoji[resultKeys[i]]!; - } - } on PlatformException catch (_) { - filtered = null; - } - return filtered; - } else { - return emoji; - } - } - - // Restore locally cached emoji - Future?> _restoreFilteredEmojis(String title) async { - final prefs = await SharedPreferences.getInstance(); - final emojiJson = prefs.getString(title); - if (emojiJson == null) { - return null; - } - final emojis = - Map.from(jsonDecode(emojiJson) as Map); - return emojis; - } - - // Stores filtered emoji locally for faster access next time - Future _cacheFilteredEmojis( - String title, - Map emojis, - ) async { - final prefs = await SharedPreferences.getInstance(); - final emojiJson = jsonEncode(emojis); - prefs.setString(title, emojiJson); - } - - // Returns list of recently used emoji from cache - Future> _getRecentEmojis() async { - final prefs = await SharedPreferences.getInstance(); - final emojiJson = prefs.getString('recent'); - if (emojiJson == null) { - return []; - } - final json = jsonDecode(emojiJson) as List; - return json.map(RecentEmoji.fromJson).toList(); - } - - // Add an emoji to recently used list or increase its counter - Future _addEmojiToRecentlyUsed(Emoji emoji) async { - final prefs = await SharedPreferences.getInstance(); - final recentEmojiIndex = - recentEmoji.indexWhere((element) => element.emoji.emoji == emoji.emoji); - if (recentEmojiIndex != -1) { - // Already exist in recent list - // Just update counter - recentEmoji[recentEmojiIndex].counter++; - } else { - recentEmoji.add(RecentEmoji(emoji, 1)); - } - // Sort by counter desc - recentEmoji.sort((a, b) => b.counter - a.counter); - // Limit entries to recentsLimit - recentEmoji = recentEmoji.sublist( - 0, - min(widget.config.recentsLimit, recentEmoji.length), - ); - // save locally - prefs.setString('recent', jsonEncode(recentEmoji)); - } -} diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/document_header_node_widget.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/document_header_node_widget.dart index 948cecf395..c958aac802 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/document_header_node_widget.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/document_header_node_widget.dart @@ -2,7 +2,7 @@ import 'dart:io'; import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; -import 'package:appflowy/workspace/presentation/widgets/emoji_picker/emoji_picker.dart'; +import 'package:appflowy/workspace/presentation/settings/widgets/emoji_picker/emoji_picker.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -257,7 +257,7 @@ class _DocumentHeaderToolbarState extends State { controller: _popoverController, offset: const Offset(0, 8), direction: PopoverDirection.bottomWithCenterAligned, - constraints: BoxConstraints.loose(const Size(320, 380)), + constraints: BoxConstraints.loose(const Size(300, 250)), child: FlowyButton( leftIconSize: const Size.square(18), useIntrinsicWidth: true, diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/emoji_popover.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/emoji_popover.dart index 89ab6c072b..4dfd9ece38 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/emoji_popover.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/emoji_popover.dart @@ -1,6 +1,6 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; -import 'package:appflowy/workspace/presentation/widgets/emoji_picker/emoji_picker.dart'; +import 'package:appflowy/workspace/presentation/settings/widgets/emoji_picker/emoji_picker.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; @@ -8,6 +8,7 @@ import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; +/// Add icon menu in Header class EmojiPopover extends StatefulWidget { final EditorState editorState; final Node node; @@ -46,17 +47,7 @@ class _EmojiPopoverState extends State { onEmojiSelected: (category, emoji) { widget.onEmojiChanged(emoji); }, - config: Config( - columns: 8, - emojiSizeMax: 28, - bgColor: Colors.transparent, - iconColor: Theme.of(context).iconTheme.color!, - iconColorSelected: Theme.of(context).colorScheme.onSurface, - selectedHoverColor: Theme.of(context).colorScheme.secondary, - progressIndicatorColor: Theme.of(context).iconTheme.color!, - buttonMode: ButtonMode.CUPERTINO, - initCategory: Category.RECENT, - ), + config: buildFlowyEmojiPickerConfig(context), ), ), ], diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/plugins.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/plugins.dart index 435d35f42e..29915410c6 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/plugins.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/plugins.dart @@ -12,7 +12,6 @@ export 'copy_and_paste/custom_paste_command.dart'; export 'database/database_view_block_component.dart'; export 'database/inline_database_menu_item.dart'; export 'database/referenced_database_menu_item.dart'; -export 'emoji_picker/emoji_menu_item.dart'; export 'extensions/flowy_tint_extension.dart'; export 'find_and_replace/find_and_replace_menu.dart'; export 'font/customize_font_toolbar_item.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/emoji_menu_item.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/emoji_menu_item.dart similarity index 89% rename from frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/emoji_menu_item.dart rename to frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/emoji_menu_item.dart index e2a9a03f6f..4ea967b1f9 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/emoji_menu_item.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/emoji_menu_item.dart @@ -113,17 +113,7 @@ class _EmojiSelectionMenuState extends State { Widget build(BuildContext context) { return EmojiPicker( onEmojiSelected: (category, emoji) => widget.onSubmitted(emoji), - config: const Config( - columns: 7, - emojiSizeMax: 28, - bgColor: Colors.transparent, - iconColor: Colors.grey, - iconColorSelected: Color(0xff333333), - indicatorColor: Color(0xff333333), - progressIndicatorColor: Color(0xff333333), - buttonMode: ButtonMode.CUPERTINO, - initCategory: Category.RECENT, - ), + config: buildFlowyEmojiPickerConfig(context), ); } } diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/emoji_picker.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/emoji_picker.dart new file mode 100644 index 0000000000..573710742c --- /dev/null +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/emoji_picker.dart @@ -0,0 +1,6 @@ +export 'emoji_menu_item.dart'; +export 'src/emji_picker_config.dart'; +export 'src/emoji_picker.dart'; +export 'src/emoji_picker_builder.dart'; +export 'src/flowy_emoji_picker_config.dart'; +export 'src/models/emoji_model.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/default_emoji_picker_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/default_emoji_picker_view.dart similarity index 63% rename from frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/default_emoji_picker_view.dart rename to frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/default_emoji_picker_view.dart index e0b8e2188e..2052cf4951 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/default_emoji_picker_view.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/default_emoji_picker_view.dart @@ -1,16 +1,19 @@ -import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flowy_infra_ui/style_widget/hover.dart'; import 'package:flutter/material.dart'; -import 'config.dart'; +import 'emji_picker_config.dart'; import 'emoji_picker.dart'; import 'emoji_picker_builder.dart'; import 'emoji_view_state.dart'; -import 'models/category_models.dart'; +import 'models/emoji_category_models.dart'; import 'models/emoji_model.dart'; class DefaultEmojiPickerView extends EmojiPickerBuilder { - const DefaultEmojiPickerView(Config config, EmojiViewState state, {Key? key}) - : super(config, state, key: key); + const DefaultEmojiPickerView( + EmojiPickerConfig config, + EmojiViewState state, { + Key? key, + }) : super(config, state, key: key); @override DefaultEmojiPickerViewState createState() => DefaultEmojiPickerViewState(); @@ -22,11 +25,12 @@ class DefaultEmojiPickerViewState extends State TabController? _tabController; final TextEditingController _emojiController = TextEditingController(); final FocusNode _emojiFocusNode = FocusNode(); - CategoryEmoji searchEmojiList = CategoryEmoji(Category.SEARCH, []); + EmojiCategoryGroup searchEmojiList = + EmojiCategoryGroup(EmojiCategory.SEARCH, []); @override void initState() { - var initCategory = widget.state.categoryEmoji.indexWhere( + var initCategory = widget.state.emojiCategoryGroupList.indexWhere( (element) => element.category == widget.config.initCategory, ); if (initCategory == -1) { @@ -34,7 +38,7 @@ class DefaultEmojiPickerViewState extends State } _tabController = TabController( initialIndex: initCategory, - length: widget.state.categoryEmoji.length, + length: widget.state.emojiCategoryGroupList.length, vsync: this, ); _pageController = PageController(initialPage: initCategory); @@ -49,7 +53,7 @@ class DefaultEmojiPickerViewState extends State ); } else { searchEmojiList.emoji.clear(); - for (final element in widget.state.categoryEmoji) { + for (final element in widget.state.emojiCategoryGroupList) { searchEmojiList.emoji.addAll( element.emoji.where((item) { return item.name.toLowerCase().contains(query); @@ -66,6 +70,8 @@ class DefaultEmojiPickerViewState extends State void dispose() { _emojiController.dispose(); _emojiFocusNode.dispose(); + _pageController?.dispose(); + _tabController?.dispose(); super.dispose(); } @@ -100,56 +106,50 @@ class DefaultEmojiPickerViewState extends State return LayoutBuilder( builder: (context, constraints) { final emojiSize = widget.config.getEmojiSize(constraints.maxWidth); + final style = Theme.of(context); return Container( color: widget.config.bgColor, - padding: const EdgeInsets.all(5.0), + padding: const EdgeInsets.all(4), child: Column( children: [ + const VSpace(4), + // search bar SizedBox( - height: 25.0, + height: 32.0, child: TextField( controller: _emojiController, focusNode: _emojiFocusNode, autofocus: true, - style: const TextStyle(fontSize: 14.0), - cursorWidth: 1.0, - cursorColor: Colors.black, + style: style.textTheme.bodyMedium, + cursorColor: style.textTheme.bodyMedium?.color, decoration: InputDecoration( - contentPadding: const EdgeInsets.symmetric(horizontal: 5.0), - hintText: "Search emoji", - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(4.0), - borderSide: const BorderSide(), - gapPadding: 0.0, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(4.0), - borderSide: const BorderSide(), - gapPadding: 0.0, - ), - filled: true, - fillColor: Colors.white, - hoverColor: Colors.white, + contentPadding: const EdgeInsets.all(8), + hintText: widget.config.searchHintText, + hintStyle: widget.config.serachHintTextStyle, + enabledBorder: widget.config.serachBarEnableBorder, + focusedBorder: widget.config.serachBarFocusedBorder, ), ), ), + const VSpace(4), Row( children: [ Expanded( child: TabBar( - labelColor: widget.config.iconColorSelected, - unselectedLabelColor: widget.config.iconColor, + labelColor: widget.config.selectedCategoryIconColor, + unselectedLabelColor: widget.config.categoryIconColor, controller: isEmojiSearching() ? TabController(length: 1, vsync: this) : _tabController, labelPadding: EdgeInsets.zero, - indicatorColor: widget.config.indicatorColor, - padding: const EdgeInsets.symmetric(vertical: 5.0), + indicatorColor: + widget.config.selectedCategoryIconBackgroundColor, + padding: const EdgeInsets.symmetric(vertical: 4.0), indicator: BoxDecoration( border: Border.all(color: Colors.transparent), borderRadius: BorderRadius.circular(4.0), - color: Colors.grey.withOpacity(0.5), + color: style.colorScheme.secondary, ), onTap: (index) { _pageController!.animateToPage( @@ -159,8 +159,8 @@ class DefaultEmojiPickerViewState extends State ); }, tabs: isEmojiSearching() - ? [_buildCategory(Category.SEARCH, emojiSize)] - : widget.state.categoryEmoji + ? [_buildCategory(EmojiCategory.SEARCH, emojiSize)] + : widget.state.emojiCategoryGroupList .asMap() .entries .map( @@ -179,20 +179,15 @@ class DefaultEmojiPickerViewState extends State child: PageView.builder( itemCount: searchEmojiList.emoji.isNotEmpty ? 1 - : widget.state.categoryEmoji.length, + : widget.state.emojiCategoryGroupList.length, controller: _pageController, physics: const NeverScrollableScrollPhysics(), - // onPageChanged: (index) { - // _tabController!.animateTo( - // index, - // duration: widget.config.tabIndicatorAnimDuration, - // ); - // }, itemBuilder: (context, index) { - final CategoryEmoji catEmoji = isEmojiSearching() - ? searchEmojiList - : widget.state.categoryEmoji[index]; - return _buildPage(emojiSize, catEmoji); + final EmojiCategoryGroup emojiCategoryGroup = + isEmojiSearching() + ? searchEmojiList + : widget.state.emojiCategoryGroupList[index]; + return _buildPage(emojiSize, emojiCategoryGroup); }, ), ), @@ -203,7 +198,7 @@ class DefaultEmojiPickerViewState extends State ); } - Widget _buildCategory(Category category, double categorySize) { + Widget _buildCategory(EmojiCategory category, double categorySize) { return Tab( height: categorySize, child: Icon( @@ -229,39 +224,39 @@ class DefaultEmojiPickerViewState extends State ); } - Widget _buildPage(double emojiSize, CategoryEmoji categoryEmoji) { + Widget _buildPage(double emojiSize, EmojiCategoryGroup emojiCategoryGroup) { // Display notice if recent has no entries yet final scrollController = ScrollController(); - if (categoryEmoji.category == Category.RECENT && - categoryEmoji.emoji.isEmpty) { + if (emojiCategoryGroup.category == EmojiCategory.RECENT && + emojiCategoryGroup.emoji.isEmpty) { return _buildNoRecent(); - } else if (categoryEmoji.category == Category.SEARCH && - categoryEmoji.emoji.isEmpty) { - return const Center(child: Text("No Emoji Found")); + } else if (emojiCategoryGroup.category == EmojiCategory.SEARCH && + emojiCategoryGroup.emoji.isEmpty) { + return Center(child: Text(widget.config.noEmojiFoundText)); } // Build page normally return ScrollbarListStack( axis: Axis.vertical, controller: scrollController, barSize: 4.0, - scrollbarPadding: const EdgeInsets.symmetric(horizontal: 5.0), - handleColor: const Color(0xffDFE0E0), - trackColor: const Color(0xffDFE0E0), + scrollbarPadding: const EdgeInsets.symmetric(horizontal: 4.0), + handleColor: widget.config.scrollBarHandleColor, + showTrack: true, child: ScrollConfiguration( behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false), child: GridView.builder( controller: scrollController, padding: const EdgeInsets.all(0), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: widget.config.columns, + crossAxisCount: widget.config.emojiNumberPerRow, mainAxisSpacing: widget.config.verticalSpacing, crossAxisSpacing: widget.config.horizontalSpacing, ), - itemCount: categoryEmoji.emoji.length, + itemCount: emojiCategoryGroup.emoji.length, itemBuilder: (context, index) { - final item = categoryEmoji.emoji[index]; - return _buildEmoji(emojiSize, categoryEmoji, item); + final item = emojiCategoryGroup.emoji[index]; + return _buildEmoji(emojiSize, emojiCategoryGroup, item); }, cacheExtent: 10, ), @@ -271,21 +266,20 @@ class DefaultEmojiPickerViewState extends State Widget _buildEmoji( double emojiSize, - CategoryEmoji categoryEmoji, + EmojiCategoryGroup emojiCategoryGroup, Emoji emoji, ) { return _buildButtonWidget( onPressed: () { - widget.state.onEmojiSelected(categoryEmoji.category, emoji); + widget.state.onEmojiSelected(emojiCategoryGroup.category, emoji); }, - child: FittedBox( - fit: BoxFit.scaleDown, - child: Text( - emoji.emoji, - textScaleFactor: 1.0, - style: TextStyle( - fontSize: emojiSize, - backgroundColor: Colors.transparent, + child: FlowyHover( + child: FittedBox( + child: Text( + emoji.emoji, + style: TextStyle( + fontSize: emojiSize, + ), ), ), ), @@ -294,10 +288,9 @@ class DefaultEmojiPickerViewState extends State Widget _buildNoRecent() { return Center( - child: FlowyText.regular( + child: Text( widget.config.noRecentsText, - color: Theme.of(context).colorScheme.tertiary.withAlpha(77), - fontSize: widget.config.noRecentsStyle.fontSize, + style: widget.config.noRecentsStyle, textAlign: TextAlign.center, ), ); diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/emji_picker_config.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/emji_picker_config.dart new file mode 100644 index 0000000000..22d2bbe034 --- /dev/null +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/emji_picker_config.dart @@ -0,0 +1,94 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'models/emoji_category_models.dart'; +import 'emoji_picker.dart'; + +part 'emji_picker_config.freezed.dart'; + +@freezed +class EmojiPickerConfig with _$EmojiPickerConfig { + // private empty constructor is used to make method work in freezed + // https://pub.dev/packages/freezed#adding-getters-and-methods-to-our-models + const EmojiPickerConfig._(); + const factory EmojiPickerConfig({ + @Default(7) int emojiNumberPerRow, + // The maximum size(width and height) of emoji + // It also depaneds on the screen size and emojiNumberPerRow + @Default(32) double emojiSizeMax, + // Vertical spacing between emojis + @Default(0) double verticalSpacing, + // Horizontal spacing between emojis + @Default(0) double horizontalSpacing, + // The initial [EmojiCategory] that will be selected + @Default(EmojiCategory.RECENT) EmojiCategory initCategory, + // The background color of the Widget + @Default(Color(0xFFEBEFF2)) Color? bgColor, + // The color of the category icons + @Default(Colors.grey) Color? categoryIconColor, + // The color of the category icon when selected + @Default(Colors.blue) Color? selectedCategoryIconColor, + // The color of the category indicator + @Default(Colors.blue) Color? selectedCategoryIconBackgroundColor, + // The color of the loading indicator during initialization + @Default(Colors.blue) Color? progressIndicatorColor, + // The color of the backspace icon button + @Default(Colors.blue) Color? backspaceColor, + // Show extra tab with recently used emoji + @Default(true) bool showRecentsTab, + // Limit of recently used emoji that will be saved + @Default(28) int recentsLimit, + @Default('Search emoji') String searchHintText, + TextStyle? serachHintTextStyle, + InputBorder? serachBarEnableBorder, + InputBorder? serachBarFocusedBorder, + // The text to be displayed if no recent emojis to display + @Default('No recent emoji') String noRecentsText, + TextStyle? noRecentsStyle, + // The text to be displayed if no emoji found + @Default('No emoji found') String noEmojiFoundText, + Color? scrollBarHandleColor, + // Duration of tab indicator to animate to next category + @Default(kTabScrollDuration) Duration tabIndicatorAnimDuration, + // Determines the icon to display for each [EmojiCategory] + @Default(EmojiCategoryIcons()) EmojiCategoryIcons emojiCategoryIcons, + // Change between Material and Cupertino button style + @Default(ButtonMode.MATERIAL) ButtonMode buttonMode, + }) = _EmojiPickerConfig; + + /// Get Emoji size based on properties and screen width + double getEmojiSize(double width) { + final maxSize = width / emojiNumberPerRow; + return min(maxSize, emojiSizeMax); + } + + /// Returns the icon for the category + IconData getIconForCategory(EmojiCategory category) { + switch (category) { + case EmojiCategory.RECENT: + return emojiCategoryIcons.recentIcon; + case EmojiCategory.SMILEYS: + return emojiCategoryIcons.smileyIcon; + case EmojiCategory.ANIMALS: + return emojiCategoryIcons.animalIcon; + case EmojiCategory.FOODS: + return emojiCategoryIcons.foodIcon; + case EmojiCategory.TRAVEL: + return emojiCategoryIcons.travelIcon; + case EmojiCategory.ACTIVITIES: + return emojiCategoryIcons.activityIcon; + case EmojiCategory.OBJECTS: + return emojiCategoryIcons.objectIcon; + case EmojiCategory.SYMBOLS: + return emojiCategoryIcons.symbolIcon; + case EmojiCategory.FLAGS: + return emojiCategoryIcons.flagIcon; + case EmojiCategory.SEARCH: + return emojiCategoryIcons.searchIcon; + default: + throw Exception('Unsupported EmojiCategory'); + } + } +} diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/emoji_lists.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/emoji_lists.dart similarity index 100% rename from frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/emoji_lists.dart rename to frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/emoji_lists.dart diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/emoji_picker.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/emoji_picker.dart similarity index 76% rename from frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/emoji_picker.dart rename to frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/emoji_picker.dart index 0a8793a5d5..a1e4d60071 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/emoji_picker.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/emoji_picker.dart @@ -7,18 +7,16 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'models/category_models.dart'; -import 'config.dart'; +import 'models/emoji_category_models.dart'; +import 'emji_picker_config.dart'; import 'default_emoji_picker_view.dart'; import 'models/emoji_model.dart'; import 'emoji_lists.dart' as emoji_list; import 'emoji_view_state.dart'; import 'models/recent_emoji_model.dart'; -/// All the possible categories that [Emoji] can be put into -/// -/// All [Category] are shown in the category bar -enum Category { +/// The emoji category shown on the category tab +enum EmojiCategory { /// Searched emojis SEARCH, @@ -62,29 +60,32 @@ enum ButtonMode { /// Callback function for when emoji is selected /// /// The function returns the selected [Emoji] as well -/// as the [Category] from which it originated -typedef OnEmojiSelected = void Function(Category category, Emoji emoji); +/// as the [EmojiCategory] from which it originated +typedef OnEmojiSelected = void Function(EmojiCategory category, Emoji emoji); /// Callback function for backspace button typedef OnBackspacePressed = void Function(); /// Callback function for custom view -typedef EmojiViewBuilder = Widget Function(Config config, EmojiViewState state); +typedef EmojiViewBuilder = Widget Function( + EmojiPickerConfig config, + EmojiViewState state, +); /// The Emoji Keyboard widget /// -/// This widget displays a grid of [Emoji] sorted by [Category] +/// This widget displays a grid of [Emoji] sorted by [EmojiCategory] /// which the user can horizontally scroll through. /// -/// There is also a bottombar which displays all the possible [Category] -/// and allow the user to quickly switch to that [Category] +/// There is also a bottombar which displays all the possible [EmojiCategory] +/// and allow the user to quickly switch to that [EmojiCategory] class EmojiPicker extends StatefulWidget { /// EmojiPicker for flutter const EmojiPicker({ Key? key, required this.onEmojiSelected, this.onBackspacePressed, - this.config = const Config(), + this.config = const EmojiPickerConfig(), this.customWidget, }) : super(key: key); @@ -98,7 +99,7 @@ class EmojiPicker extends StatefulWidget { final OnBackspacePressed? onBackspacePressed; /// Config for customizations - final Config config; + final EmojiPickerConfig config; @override EmojiPickerState createState() => EmojiPickerState(); @@ -107,8 +108,8 @@ class EmojiPicker extends StatefulWidget { class EmojiPickerState extends State { static const platform = MethodChannel('emoji_picker_flutter'); - List categoryEmoji = List.empty(growable: true); - List recentEmoji = List.empty(growable: true); + List emojiCategoryGroupList = List.empty(growable: true); + List recentEmojiList = List.empty(growable: true); late Future updateEmojiFuture; // Prevent emojis to be reloaded with every build @@ -123,7 +124,7 @@ class EmojiPickerState extends State { @override void didUpdateWidget(covariant EmojiPicker oldWidget) { if (oldWidget.config != widget.config) { - // Config changed - rebuild EmojiPickerView completely + // EmojiPickerConfig changed - rebuild EmojiPickerView completely loaded = false; updateEmojiFuture = _updateEmojis(); } @@ -147,12 +148,12 @@ class EmojiPickerState extends State { return const Center(child: CircularProgressIndicator()); } if (widget.config.showRecentsTab) { - categoryEmoji[0].emoji = - recentEmoji.map((e) => e.emoji).toList().cast(); + emojiCategoryGroupList[0].emoji = + recentEmojiList.map((e) => e.emoji).toList().cast(); } final state = EmojiViewState( - categoryEmoji, + emojiCategoryGroupList, _getOnEmojiListener(), widget.onBackspacePressed, ); @@ -168,7 +169,7 @@ class EmojiPickerState extends State { return (category, emoji) { if (widget.config.showRecentsTab) { _addEmojiToRecentlyUsed(emoji).then((value) { - if (category != Category.RECENT && mounted) { + if (category != EmojiCategory.RECENT && mounted) { setState(() { // rebuild to update recent emoji tab // when it is not current tab @@ -182,47 +183,48 @@ class EmojiPickerState extends State { // Initialize emoji data Future _updateEmojis() async { - categoryEmoji.clear(); + emojiCategoryGroupList.clear(); if (widget.config.showRecentsTab) { - recentEmoji = await _getRecentEmojis(); + recentEmojiList = await _getRecentEmojis(); final List recentEmojiMap = - recentEmoji.map((e) => e.emoji).toList().cast(); - categoryEmoji.add(CategoryEmoji(Category.RECENT, recentEmojiMap)); + recentEmojiList.map((e) => e.emoji).toList().cast(); + emojiCategoryGroupList + .add(EmojiCategoryGroup(EmojiCategory.RECENT, recentEmojiMap)); } - categoryEmoji.addAll([ - CategoryEmoji( - Category.SMILEYS, + emojiCategoryGroupList.addAll([ + EmojiCategoryGroup( + EmojiCategory.SMILEYS, await _getAvailableEmojis(emoji_list.smileys, title: 'smileys'), ), - CategoryEmoji( - Category.ANIMALS, + EmojiCategoryGroup( + EmojiCategory.ANIMALS, await _getAvailableEmojis(emoji_list.animals, title: 'animals'), ), - CategoryEmoji( - Category.FOODS, + EmojiCategoryGroup( + EmojiCategory.FOODS, await _getAvailableEmojis(emoji_list.foods, title: 'foods'), ), - CategoryEmoji( - Category.ACTIVITIES, + EmojiCategoryGroup( + EmojiCategory.ACTIVITIES, await _getAvailableEmojis( emoji_list.activities, title: 'activities', ), ), - CategoryEmoji( - Category.TRAVEL, + EmojiCategoryGroup( + EmojiCategory.TRAVEL, await _getAvailableEmojis(emoji_list.travel, title: 'travel'), ), - CategoryEmoji( - Category.OBJECTS, + EmojiCategoryGroup( + EmojiCategory.OBJECTS, await _getAvailableEmojis(emoji_list.objects, title: 'objects'), ), - CategoryEmoji( - Category.SYMBOLS, + EmojiCategoryGroup( + EmojiCategory.SYMBOLS, await _getAvailableEmojis(emoji_list.symbols, title: 'symbols'), ), - CategoryEmoji( - Category.FLAGS, + EmojiCategoryGroup( + EmojiCategory.FLAGS, await _getAvailableEmojis(emoji_list.flags, title: 'flags'), ) ]); @@ -316,23 +318,23 @@ class EmojiPickerState extends State { // Add an emoji to recently used list or increase its counter Future _addEmojiToRecentlyUsed(Emoji emoji) async { final prefs = await SharedPreferences.getInstance(); - final recentEmojiIndex = - recentEmoji.indexWhere((element) => element.emoji.emoji == emoji.emoji); + final recentEmojiIndex = recentEmojiList + .indexWhere((element) => element.emoji.emoji == emoji.emoji); if (recentEmojiIndex != -1) { // Already exist in recent list // Just update counter - recentEmoji[recentEmojiIndex].counter++; + recentEmojiList[recentEmojiIndex].counter++; } else { - recentEmoji.add(RecentEmoji(emoji, 1)); + recentEmojiList.add(RecentEmoji(emoji, 1)); } // Sort by counter desc - recentEmoji.sort((a, b) => b.counter - a.counter); + recentEmojiList.sort((a, b) => b.counter - a.counter); // Limit entries to recentsLimit - recentEmoji = recentEmoji.sublist( + recentEmojiList = recentEmojiList.sublist( 0, - min(widget.config.recentsLimit, recentEmoji.length), + min(widget.config.recentsLimit, recentEmojiList.length), ); // save locally - prefs.setString('recent', jsonEncode(recentEmoji)); + prefs.setString('recent', jsonEncode(recentEmojiList)); } } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/emoji_picker_builder.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/emoji_picker_builder.dart similarity index 86% rename from frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/emoji_picker_builder.dart rename to frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/emoji_picker_builder.dart index fe526e01db..bb7d139633 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/emoji_picker_builder.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/emoji_picker_builder.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'config.dart'; +import 'emji_picker_config.dart'; import 'emoji_view_state.dart'; /// Template class for custom implementation @@ -11,7 +11,7 @@ abstract class EmojiPickerBuilder extends StatefulWidget { : super(key: key); /// Config for customizations - final Config config; + final EmojiPickerConfig config; /// State that holds current emoji data final EmojiViewState state; diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/emoji_view_state.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/emoji_view_state.dart similarity index 65% rename from frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/emoji_view_state.dart rename to frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/emoji_view_state.dart index 202f913715..e6d0c5d559 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/emoji_view_state.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/emoji_view_state.dart @@ -1,17 +1,17 @@ -import 'models/category_models.dart'; +import 'models/emoji_category_models.dart'; import 'emoji_picker.dart'; /// State that holds current emoji data class EmojiViewState { /// Constructor EmojiViewState( - this.categoryEmoji, + this.emojiCategoryGroupList, this.onEmojiSelected, this.onBackspacePressed, ); - /// List of all category including their emoji - final List categoryEmoji; + /// List of all categories including their emojis + final List emojiCategoryGroupList; /// Callback when pressed on emoji final OnEmojiSelected onEmojiSelected; diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/flowy_emoji_picker_config.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/flowy_emoji_picker_config.dart new file mode 100644 index 0000000000..066d63f380 --- /dev/null +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/flowy_emoji_picker_config.dart @@ -0,0 +1,34 @@ +import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/workspace/presentation/settings/widgets/emoji_picker/src/emji_picker_config.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +EmojiPickerConfig buildFlowyEmojiPickerConfig(BuildContext context) { + final style = Theme.of(context); + return EmojiPickerConfig( + bgColor: style.cardColor, + categoryIconColor: style.iconTheme.color, + selectedCategoryIconColor: style.colorScheme.onSurface, + selectedCategoryIconBackgroundColor: style.colorScheme.primary, + progressIndicatorColor: style.colorScheme.primary, + backspaceColor: style.colorScheme.primary, + searchHintText: LocaleKeys.emoji_search.tr(), + serachHintTextStyle: style.textTheme.bodyMedium?.copyWith( + color: style.hintColor, + ), + serachBarEnableBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(4), + borderSide: BorderSide(color: style.dividerColor), + ), + serachBarFocusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(4), + borderSide: BorderSide( + color: style.colorScheme.primary, + ), + ), + noRecentsText: LocaleKeys.emoji_noRecent.tr(), + noRecentsStyle: style.textTheme.bodyMedium, + noEmojiFoundText: LocaleKeys.emoji_noEmojiFound.tr(), + scrollBarHandleColor: style.colorScheme.onBackground, + ); +} diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/models/category_models.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/models/emoji_category_models.dart similarity index 62% rename from frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/models/category_models.dart rename to frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/models/emoji_category_models.dart index 885ff2ab0c..65d0d652a2 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/models/category_models.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/models/emoji_category_models.dart @@ -3,13 +3,11 @@ import 'package:flutter/material.dart'; import 'emoji_model.dart'; import '../emoji_picker.dart'; -/// Container for Category and their emoji -class CategoryEmoji { - /// Constructor - CategoryEmoji(this.category, this.emoji); +/// EmojiCategory with its emojis +class EmojiCategoryGroup { + EmojiCategoryGroup(this.category, this.emoji); - /// Category instance - final Category category; + final EmojiCategory category; /// List of emoji of this category List emoji; @@ -20,10 +18,10 @@ class CategoryEmoji { } } -/// Class that defines the icon representing a [Category] -class CategoryIcon { +/// Class that defines the icon representing a [EmojiCategory] +class EmojiCategoryIcon { /// Icon of Category - const CategoryIcon({ + const EmojiCategoryIcon({ required this.icon, this.color = const Color(0xffd3d3d3), this.selectedColor = const Color(0xffb2b2b2), @@ -39,14 +37,14 @@ class CategoryIcon { final Color selectedColor; } -/// Class used to define all the [CategoryIcon] shown for each [Category] +/// Class used to define all the [EmojiCategoryIcon] shown for each [EmojiCategory] /// /// This allows the keyboard to be personalized by changing icons shown. -/// If a [CategoryIcon] is set as null or not defined during initialization, +/// If a [EmojiCategoryIcon] is set as null or not defined during initialization, /// the default icons will be used instead -class CategoryIcons { +class EmojiCategoryIcons { /// Constructor - const CategoryIcons({ + const EmojiCategoryIcons({ this.recentIcon = Icons.access_time, this.smileyIcon = Icons.tag_faces, this.animalIcon = Icons.pets, @@ -59,33 +57,33 @@ class CategoryIcons { this.searchIcon = Icons.search, }); - /// Icon for [Category.RECENT] + /// Icon for [EmojiCategory.RECENT] final IconData recentIcon; - /// Icon for [Category.SMILEYS] + /// Icon for [EmojiCategory.SMILEYS] final IconData smileyIcon; - /// Icon for [Category.ANIMALS] + /// Icon for [EmojiCategory.ANIMALS] final IconData animalIcon; - /// Icon for [Category.FOODS] + /// Icon for [EmojiCategory.FOODS] final IconData foodIcon; - /// Icon for [Category.ACTIVITIES] + /// Icon for [EmojiCategory.ACTIVITIES] final IconData activityIcon; - /// Icon for [Category.TRAVEL] + /// Icon for [EmojiCategory.TRAVEL] final IconData travelIcon; - /// Icon for [Category.OBJECTS] + /// Icon for [EmojiCategory.OBJECTS] final IconData objectIcon; - /// Icon for [Category.SYMBOLS] + /// Icon for [EmojiCategory.SYMBOLS] final IconData symbolIcon; - /// Icon for [Category.FLAGS] + /// Icon for [EmojiCategory.FLAGS] final IconData flagIcon; - /// Icon for [Category.SEARCH] + /// Icon for [EmojiCategory.SEARCH] final IconData searchIcon; } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/models/emoji_model.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/models/emoji_model.dart similarity index 100% rename from frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/models/emoji_model.dart rename to frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/models/emoji_model.dart diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/models/recent_emoji_model.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/models/recent_emoji_model.dart similarity index 100% rename from frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/emoji_picker/src/models/recent_emoji_model.dart rename to frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/models/recent_emoji_model.dart diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/emoji_picker.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/emoji_picker.dart deleted file mode 100644 index 47a8f0d3b1..0000000000 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/emoji_picker.dart +++ /dev/null @@ -1,4 +0,0 @@ -export 'src/config.dart'; -export 'src/models/emoji_model.dart'; -export 'src/emoji_picker.dart'; -export 'src/emoji_picker_builder.dart'; diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/config.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/config.dart deleted file mode 100644 index a12d382f2c..0000000000 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/config.dart +++ /dev/null @@ -1,169 +0,0 @@ -import 'dart:math'; - -import 'package:flutter/material.dart'; - -import 'models/category_models.dart'; -import 'emoji_picker.dart'; - -/// Config for customizations -class Config { - /// Constructor - const Config({ - this.columns = 7, - this.emojiSizeMax = 32.0, - this.verticalSpacing = 0, - this.horizontalSpacing = 0, - this.initCategory = Category.RECENT, - this.bgColor = const Color(0xFFEBEFF2), - this.indicatorColor = Colors.blue, - this.selectedHoverColor = Colors.grey, - this.iconColor = Colors.grey, - this.iconColorSelected = Colors.blue, - this.progressIndicatorColor = Colors.blue, - this.backspaceColor = Colors.blue, - this.showRecentsTab = true, - this.recentsLimit = 28, - this.noRecentsText = 'No Recents', - this.noRecentsStyle = const TextStyle(fontSize: 20, color: Colors.black26), - this.tabIndicatorAnimDuration = kTabScrollDuration, - this.categoryIcons = const CategoryIcons(), - this.buttonMode = ButtonMode.MATERIAL, - }); - - /// Number of emojis per row - final int columns; - - /// Width and height the emoji will be maximal displayed - /// Can be smaller due to screen size and amount of columns - final double emojiSizeMax; - - /// Vertical spacing between emojis - final double verticalSpacing; - - /// Horizontal spacing between emojis - final double horizontalSpacing; - - /// The initial [Category] that will be selected - /// This [Category] will have its button in the bottombar darkened - final Category initCategory; - - /// The background color of the Widget - final Color bgColor; - - /// The color of the category indicator - final Color indicatorColor; - - /// The background color of the selected category - final Color selectedHoverColor; - - /// The color of the category icons - final Color iconColor; - - /// The color of the category icon when selected - final Color iconColorSelected; - - /// The color of the loading indicator during initialization - final Color progressIndicatorColor; - - /// The color of the backspace icon button - final Color backspaceColor; - - /// Show extra tab with recently used emoji - final bool showRecentsTab; - - /// Limit of recently used emoji that will be saved - final int recentsLimit; - - /// The text to be displayed if no recent emojis to display - final String noRecentsText; - - /// The text style for [noRecentsText] - final TextStyle noRecentsStyle; - - /// Duration of tab indicator to animate to next category - final Duration tabIndicatorAnimDuration; - - /// Determines the icon to display for each [Category] - final CategoryIcons categoryIcons; - - /// Change between Material and Cupertino button style - final ButtonMode buttonMode; - - /// Get Emoji size based on properties and screen width - double getEmojiSize(double width) { - final maxSize = width / columns; - return min(maxSize, emojiSizeMax); - } - - /// Returns the icon for the category - IconData getIconForCategory(Category category) { - switch (category) { - case Category.RECENT: - return categoryIcons.recentIcon; - case Category.SMILEYS: - return categoryIcons.smileyIcon; - case Category.ANIMALS: - return categoryIcons.animalIcon; - case Category.FOODS: - return categoryIcons.foodIcon; - case Category.TRAVEL: - return categoryIcons.travelIcon; - case Category.ACTIVITIES: - return categoryIcons.activityIcon; - case Category.OBJECTS: - return categoryIcons.objectIcon; - case Category.SYMBOLS: - return categoryIcons.symbolIcon; - case Category.FLAGS: - return categoryIcons.flagIcon; - case Category.SEARCH: - return categoryIcons.searchIcon; - default: - throw Exception('Unsupported Category'); - } - } - - @override - bool operator ==(other) { - return (other is Config) && - other.columns == columns && - other.emojiSizeMax == emojiSizeMax && - other.verticalSpacing == verticalSpacing && - other.horizontalSpacing == horizontalSpacing && - other.initCategory == initCategory && - other.bgColor == bgColor && - other.indicatorColor == indicatorColor && - other.iconColor == iconColor && - other.iconColorSelected == iconColorSelected && - other.progressIndicatorColor == progressIndicatorColor && - other.backspaceColor == backspaceColor && - other.showRecentsTab == showRecentsTab && - other.recentsLimit == recentsLimit && - other.noRecentsText == noRecentsText && - other.noRecentsStyle == noRecentsStyle && - other.tabIndicatorAnimDuration == tabIndicatorAnimDuration && - other.categoryIcons == categoryIcons && - other.buttonMode == buttonMode; - } - - @override - int get hashCode => - columns.hashCode ^ - emojiSizeMax.hashCode ^ - verticalSpacing.hashCode ^ - horizontalSpacing.hashCode ^ - initCategory.hashCode ^ - bgColor.hashCode ^ - indicatorColor.hashCode ^ - iconColor.hashCode ^ - iconColorSelected.hashCode ^ - progressIndicatorColor.hashCode ^ - backspaceColor.hashCode ^ - showRecentsTab.hashCode ^ - recentsLimit.hashCode ^ - noRecentsText.hashCode ^ - noRecentsStyle.hashCode ^ - tabIndicatorAnimDuration.hashCode ^ - categoryIcons.hashCode ^ - buttonMode.hashCode; -} diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/default_emoji_picker_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/default_emoji_picker_view.dart deleted file mode 100644 index a663f0b5cc..0000000000 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/default_emoji_picker_view.dart +++ /dev/null @@ -1,321 +0,0 @@ -import 'package:flowy_infra/size.dart'; -import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart'; -import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -import 'models/category_models.dart'; -import 'config.dart'; -import 'models/emoji_model.dart'; -import 'emoji_picker.dart'; -import 'emoji_picker_builder.dart'; -import 'emoji_view_state.dart'; - -class DefaultEmojiPickerView extends EmojiPickerBuilder { - const DefaultEmojiPickerView(Config config, EmojiViewState state, {Key? key}) - : super(config, state, key: key); - - @override - DefaultEmojiPickerViewState createState() => DefaultEmojiPickerViewState(); -} - -class DefaultEmojiPickerViewState extends State - with TickerProviderStateMixin { - PageController? _pageController; - TabController? _tabController; - final TextEditingController _emojiController = TextEditingController(); - final FocusNode _emojiFocusNode = FocusNode(); - final CategoryEmoji _categoryEmoji = - CategoryEmoji(Category.SEARCH, List.empty(growable: true)); - CategoryEmoji searchEmojiList = CategoryEmoji(Category.SEARCH, []); - - @override - void initState() { - var initCategory = widget.state.categoryEmoji.indexWhere( - (element) => element.category == widget.config.initCategory, - ); - if (initCategory == -1) { - initCategory = 0; - } - _tabController = TabController( - initialIndex: initCategory, - length: widget.state.categoryEmoji.length, - vsync: this, - ); - _pageController = PageController(initialPage: initCategory); - _emojiFocusNode.requestFocus(); - - _emojiController.addListener(() { - final String query = _emojiController.text.toLowerCase(); - if (query.isEmpty) { - searchEmojiList.emoji.clear(); - _pageController!.jumpToPage( - _tabController!.index, - ); - } else { - searchEmojiList.emoji.clear(); - for (final element in widget.state.categoryEmoji) { - searchEmojiList.emoji.addAll( - element.emoji.where((item) { - return item.name.toLowerCase().contains(query); - }).toList(), - ); - } - } - setState(() {}); - }); - super.initState(); - } - - @override - void dispose() { - _emojiController.dispose(); - _emojiFocusNode.dispose(); - super.dispose(); - } - - Widget _buildBackspaceButton() { - if (widget.state.onBackspacePressed != null) { - return Material( - type: MaterialType.transparency, - child: IconButton( - padding: const EdgeInsets.only(bottom: 2), - icon: Icon( - Icons.backspace, - color: widget.config.backspaceColor, - ), - onPressed: () { - widget.state.onBackspacePressed!(); - }, - ), - ); - } - return Container(); - } - - bool isEmojiSearching() { - final bool result = - searchEmojiList.emoji.isNotEmpty || _emojiController.text.isNotEmpty; - - return result; - } - - @override - Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - final emojiSize = widget.config.getEmojiSize(constraints.maxWidth); - - return Container( - color: widget.config.bgColor, - padding: const EdgeInsets.all(4.0), - child: Column( - children: [ - SizedBox( - height: 40, - child: TextField( - controller: _emojiController, - focusNode: _emojiFocusNode, - autofocus: true, - cursorWidth: 1.0, - cursorColor: Theme.of(context).colorScheme.tertiary, - style: Theme.of(context).textTheme.bodyMedium?.copyWith( - fontSize: FontSizes.s16, - fontWeight: FontWeight.w400, - ), - decoration: InputDecoration( - contentPadding: const EdgeInsets.symmetric(horizontal: 10), - hintText: "Search emoji", - focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).colorScheme.tertiary, - width: 2, - ), - ), - border: OutlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).colorScheme.tertiary, - ), - ), - filled: true, - fillColor: Colors.transparent, - hoverColor: Colors.transparent, - ), - ), - ), - const VSpace(6), - Row( - children: [ - Expanded( - child: TabBar( - labelColor: widget.config.iconColorSelected, - unselectedLabelColor: widget.config.iconColor, - controller: isEmojiSearching() - ? TabController(length: 1, vsync: this) - : _tabController, - labelPadding: EdgeInsets.zero, - indicatorColor: widget.config.indicatorColor, - padding: const EdgeInsets.symmetric(vertical: 5.0), - indicator: BoxDecoration( - borderRadius: BorderRadius.circular(4.0), - color: widget.config.selectedHoverColor, - ), - onTap: (index) { - _pageController!.animateToPage( - index, - duration: widget.config.tabIndicatorAnimDuration, - curve: Curves.ease, - ); - }, - tabs: isEmojiSearching() - ? [_buildCategory(Category.SEARCH, emojiSize)] - : widget.state.categoryEmoji - .asMap() - .entries - .map( - (item) => _buildCategory( - item.value.category, - emojiSize, - ), - ) - .toList(), - ), - ), - _buildBackspaceButton(), - ], - ), - Flexible( - child: PageView.builder( - itemCount: searchEmojiList.emoji.isNotEmpty - ? 1 - : widget.state.categoryEmoji.length, - controller: _pageController, - physics: const NeverScrollableScrollPhysics(), - // onPageChanged: (index) { - // _tabController!.animateTo( - // index, - // duration: widget.config.tabIndicatorAnimDuration, - // ); - // }, - itemBuilder: (context, index) { - final CategoryEmoji catEmoji = isEmojiSearching() - ? searchEmojiList - : widget.state.categoryEmoji[index]; - return _buildPage(emojiSize, catEmoji); - }, - ), - ), - ], - ), - ); - }, - ); - } - - Widget _buildCategory(Category category, double categorySize) { - return Tab( - height: categorySize, - child: Icon( - widget.config.getIconForCategory(category), - size: categorySize / 1.3, - ), - ); - } - - Widget _buildButtonWidget({ - required VoidCallback onPressed, - required Widget child, - }) { - if (widget.config.buttonMode == ButtonMode.MATERIAL) { - return TextButton( - onPressed: onPressed, - style: ButtonStyle(padding: MaterialStateProperty.all(EdgeInsets.zero)), - child: child, - ); - } - return CupertinoButton( - padding: EdgeInsets.zero, - onPressed: onPressed, - child: child, - ); - } - - Widget _buildPage(double emojiSize, CategoryEmoji categoryEmoji) { - // Display notice if recent has no entries yet - final scrollController = ScrollController(); - - if (categoryEmoji.category == Category.RECENT && - categoryEmoji.emoji.isEmpty) { - return _buildNoRecent(); - } else if (categoryEmoji.category == Category.SEARCH && - categoryEmoji.emoji.isEmpty) { - return const Center(child: Text("No Emoji Found")); - } - // Build page normally - return ScrollbarListStack( - axis: Axis.vertical, - controller: scrollController, - barSize: 4.0, - scrollbarPadding: const EdgeInsets.symmetric(horizontal: 5.0), - handleColor: const Color(0xffDFE0E0), - trackColor: const Color(0xffDFE0E0), - child: ScrollConfiguration( - behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false), - child: GridView.count( - scrollDirection: Axis.vertical, - physics: const ScrollPhysics(), - controller: scrollController, - shrinkWrap: true, - // primary: true, - padding: const EdgeInsets.all(0), - crossAxisCount: widget.config.columns, - mainAxisSpacing: widget.config.verticalSpacing, - crossAxisSpacing: widget.config.horizontalSpacing, - children: _categoryEmoji.emoji.isNotEmpty - ? _categoryEmoji.emoji - .map((e) => _buildEmoji(emojiSize, categoryEmoji, e)) - .toList() - : categoryEmoji.emoji - .map( - (item) => _buildEmoji(emojiSize, categoryEmoji, item), - ) - .toList(), - ), - ), - ); - } - - Widget _buildEmoji( - double emojiSize, - CategoryEmoji categoryEmoji, - Emoji emoji, - ) { - return _buildButtonWidget( - onPressed: () { - widget.state.onEmojiSelected(categoryEmoji.category, emoji); - }, - child: FittedBox( - fit: BoxFit.scaleDown, - child: Text( - emoji.emoji, - textScaleFactor: 1.0, - style: TextStyle( - fontSize: emojiSize, - backgroundColor: Colors.transparent, - color: Theme.of(context).iconTheme.color, - ), - ), - ), - ); - } - - Widget _buildNoRecent() { - return Center( - child: Text( - widget.config.noRecentsText, - style: widget.config.noRecentsStyle, - textAlign: TextAlign.center, - ), - ); - } -} diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/emoji_lists.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/emoji_lists.dart deleted file mode 100644 index 6cb3681206..0000000000 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/emoji_lists.dart +++ /dev/null @@ -1,3223 +0,0 @@ -// Copyright information -// File originally from https://github.com/JeffG05/emoji_picker - -// import 'emoji.dart'; - -// final List> temp = [smileys, animals, foods, activities, travel, objects, symbols, flags]; - -// final List emojiSearchList = temp -// .map((element) { -// return element.entries.map((entry) => Emoji(entry.key, entry.value)).toList(); -// }) -// .toList() -// .first; - -/// Map of all possible emojis along with their names in [Category.SMILEYS] -final Map smileys = Map.fromIterables([ - 'Grinning Face', - 'Grinning Face With Big Eyes', - 'Grinning Face With Smiling Eyes', - 'Beaming Face With Smiling Eyes', - 'Grinning Squinting Face', - 'Grinning Face With Sweat', - 'Rolling on the Floor Laughing', - 'Face With Tears of Joy', - 'Slightly Smiling Face', - 'Upside-Down Face', - 'Winking Face', - 'Smiling Face With Smiling Eyes', - 'Smiling Face With Halo', - 'Smiling Face With Hearts', - 'Smiling Face With Heart-Eyes', - 'Star-Struck', - 'Face Blowing a Kiss', - 'Kissing Face', - 'Smiling Face', - 'Kissing Face With Closed Eyes', - 'Kissing Face With Smiling Eyes', - 'Face Savoring Food', - 'Face With Tongue', - 'Winking Face With Tongue', - 'Zany Face', - 'Squinting Face With Tongue', - 'Money-Mouth Face', - 'Hugging Face', - 'Face With Hand Over Mouth', - 'Shushing Face', - 'Thinking Face', - 'Zipper-Mouth Face', - 'Face With Raised Eyebrow', - 'Neutral Face', - 'Expressionless Face', - 'Face Without Mouth', - 'Smirking Face', - 'Unamused Face', - 'Face With Rolling Eyes', - 'Grimacing Face', - 'Lying Face', - 'Relieved Face', - 'Pensive Face', - 'Sleepy Face', - 'Drooling Face', - 'Sleeping Face', - 'Face With Medical Mask', - 'Face With Thermometer', - 'Face With Head-Bandage', - 'Nauseated Face', - 'Face Vomiting', - 'Sneezing Face', - 'Hot Face', - 'Cold Face', - 'Woozy Face', - 'Dizzy Face', - 'Exploding Head', - 'Cowboy Hat Face', - 'Partying Face', - 'Smiling Face With Sunglasses', - 'Nerd Face', - 'Face With Monocle', - 'Confused Face', - 'Worried Face', - 'Slightly Frowning Face', - 'Frowning Face', - 'Face With Open Mouth', - 'Hushed Face', - 'Astonished Face', - 'Flushed Face', - 'Pleading Face', - 'Frowning Face With Open Mouth', - 'Anguished Face', - 'Fearful Face', - 'Anxious Face With Sweat', - 'Sad but Relieved Face', - 'Crying Face', - 'Loudly Crying Face', - 'Face Screaming in Fear', - 'Confounded Face', - 'Persevering Face', - 'Disappointed Face', - 'Downcast Face With Sweat', - 'Weary Face', - 'Tired Face', - 'Face With Steam From Nose', - 'Pouting Face', - 'Angry Face', - 'Face With Symbols on Mouth', - 'Smiling Face With Horns', - 'Angry Face With Horns', - 'Skull', - 'Skull and Crossbones', - 'Pile of Poo', - 'Clown Face', - 'Ogre', - 'Goblin', - 'Ghost', - 'Alien', - 'Alien Monster', - 'Robot Face', - 'Grinning Cat Face', - 'Grinning Cat Face With Smiling Eyes', - 'Cat Face With Tears of Joy', - 'Smiling Cat Face With Heart-Eyes', - 'Cat Face With Wry Smile', - 'Kissing Cat Face', - 'Weary Cat Face', - 'Crying Cat Face', - 'Pouting Cat Face', - 'Kiss Mark', - 'Waving Hand', - 'Raised Back of Hand', - 'Hand With Fingers Splayed', - 'Raised Hand', - 'Vulcan Salute', - 'OK Hand', - 'Victory Hand', - 'Crossed Fingers', - 'Love-You Gesture', - 'Sign of the Horns', - 'Call Me Hand', - 'Backhand Index Pointing Left', - 'Backhand Index Pointing Right', - 'Backhand Index Pointing Up', - 'Middle Finger', - 'Backhand Index Pointing Down', - 'Index Pointing Up', - 'Thumbs Up', - 'Thumbs Down', - 'Raised Fist', - 'Oncoming Fist', - 'Left-Facing Fist', - 'Right-Facing Fist', - 'Clapping Hands', - 'Raising Hands', - 'Open Hands', - 'Palms Up Together', - 'Handshake', - 'Folded Hands', - 'Writing Hand', - 'Nail Polish', - 'Selfie', - 'Flexed Biceps', - 'Leg', - 'Foot', - 'Ear', - 'Nose', - 'Brain', - 'Tooth', - 'Bone', - 'Eyes', - 'Eye', - 'Tongue', - 'Mouth', - 'Baby', - 'Child', - 'Boy', - 'Girl', - 'Person', - 'Man', - 'Man: Beard', - 'Man: Blond Hair', - 'Man: Red Hair', - 'Man: Curly Hair', - 'Man: White Hair', - 'Man: Bald', - 'Woman', - 'Woman: Blond Hair', - 'Woman: Red Hair', - 'Woman: Curly Hair', - 'Woman: White Hair', - 'Woman: Bald', - 'Older Person', - 'Old Man', - 'Old Woman', - 'Man Frowning', - 'Woman Frowning', - 'Man Pouting', - 'Woman Pouting', - 'Man Gesturing No', - 'Woman Gesturing No', - 'Man Gesturing OK', - 'Woman Gesturing OK', - 'Man Tipping Hand', - 'Woman Tipping Hand', - 'Man Raising Hand', - 'Woman Raising Hand', - 'Man Bowing', - 'Woman Bowing', - 'Man Facepalming', - 'Woman Facepalming', - 'Man Shrugging', - 'Woman Shrugging', - 'Man Health Worker', - 'Woman Health Worker', - 'Man Student', - 'Woman Student', - 'Man Teacher', - 'Woman Teacher', - 'Man Judge', - 'Woman Judge', - 'Man Farmer', - 'Woman Farmer', - 'Man Cook', - 'Woman Cook', - 'Man Mechanic', - 'Woman Mechanic', - 'Man Factory Worker', - 'Woman Factory Worker', - 'Man Office Worker', - 'Woman Office Worker', - 'Man Scientist', - 'Woman Scientist', - 'Man Technologist', - 'Woman Technologist', - 'Man Singer', - 'Woman Singer', - 'Man Artist', - 'Woman Artist', - 'Man Pilot', - 'Woman Pilot', - 'Man Astronaut', - 'Woman Astronaut', - 'Man Firefighter', - 'Woman Firefighter', - 'Man Police Officer', - 'Woman Police Officer', - 'Man Detective', - 'Woman Detective', - 'Man Guard', - 'Woman Guard', - 'Man Construction Worker', - 'Woman Construction Worker', - 'Prince', - 'Princess', - 'Man Wearing Turban', - 'Woman Wearing Turban', - 'Man With Chinese Cap', - 'Woman With Headscarf', - 'Man in Tuxedo', - 'Bride With Veil', - 'Pregnant Woman', - 'Breast-Feeding', - 'Baby Angel', - 'Santa Claus', - 'Mrs. Claus', - 'Man Superhero', - 'Woman Superhero', - 'Man Supervillain', - 'Woman Supervillain', - 'Man Mage', - 'Woman Mage', - 'Man Fairy', - 'Woman Fairy', - 'Man Vampire', - 'Woman Vampire', - 'Merman', - 'Mermaid', - 'Man Elf', - 'Woman Elf', - 'Man Genie', - 'Woman Genie', - 'Man Zombie', - 'Woman Zombie', - 'Man Getting Massage', - 'Woman Getting Massage', - 'Man Getting Haircut', - 'Woman Getting Haircut', - 'Man Walking', - 'Woman Walking', - 'Man Running', - 'Woman Running', - 'Woman Dancing', - 'Man Dancing', - 'Man in Suit Levitating', - 'Men With Bunny Ears', - 'Women With Bunny Ears', - 'Man in Steamy Room', - 'Woman in Steamy Room', - 'Person in Lotus Position', - 'Women Holding Hands', - 'Woman and Man Holding Hands', - 'Men Holding Hands', - 'Kiss', - 'Kiss: Man, Man', - 'Kiss: Woman, Woman', - 'Couple With Heart', - 'Couple With Heart: Man, Man', - 'Couple With Heart: Woman, Woman', - 'Family', - 'Family: Man, Woman, Boy', - 'Family: Man, Woman, Girl', - 'Family: Man, Woman, Girl, Boy', - 'Family: Man, Woman, Boy, Boy', - 'Family: Man, Woman, Girl, Girl', - 'Family: Man, Man, Boy', - 'Family: Man, Man, Girl', - 'Family: Man, Man, Girl, Boy', - 'Family: Man, Man, Boy, Boy', - 'Family: Man, Man, Girl, Girl', - 'Family: Woman, Woman, Boy', - 'Family: Woman, Woman, Girl', - 'Family: Woman, Woman, Girl, Boy', - 'Family: Woman, Woman, Boy, Boy', - 'Family: Woman, Woman, Girl, Girl', - 'Family: Man, Boy', - 'Family: Man, Boy, Boy', - 'Family: Man, Girl', - 'Family: Man, Girl, Boy', - 'Family: Man, Girl, Girl', - 'Family: Woman, Boy', - 'Family: Woman, Boy, Boy', - 'Family: Woman, Girl', - 'Family: Woman, Girl, Boy', - 'Family: Woman, Girl, Girl', - 'Speaking Head', - 'Bust in Silhouette', - 'Busts in Silhouette', - 'Footprints', - 'Luggage', - 'Closed Umbrella', - 'Umbrella', - 'Thread', - 'Yarn', - 'Glasses', - 'Sunglasses', - 'Goggles', - 'Lab Coat', - 'Necktie', - 'T-Shirt', - 'Jeans', - 'Scarf', - 'Gloves', - 'Coat', - 'Socks', - 'Dress', - 'Kimono', - 'Bikini', - 'Woman’s Clothes', - 'Purse', - 'Handbag', - 'Clutch Bag', - 'Backpack', - 'Man’s Shoe', - 'Running Shoe', - 'Hiking Boot', - 'Flat Shoe', - 'High-Heeled Shoe', - 'Woman’s Sandal', - 'Woman’s Boot', - 'Crown', - 'Woman’s Hat', - 'Top Hat', - 'Graduation Cap', - 'Billed Cap', - 'Rescue Worker’s Helmet', - 'Lipstick', - 'Ring', - 'Briefcase' -], [ - '😀', - '😃', - '😄', - '😁', - '😆', - '😅', - '🤣', - '😂', - '🙂', - '🙃', - '😉', - '😊', - '😇', - '🥰', - '😍', - '🤩', - '😘', - '😗', - '☺', - '😚', - '😙', - '😋', - '😛', - '😜', - '🤪', - '😝', - '🤑', - '🤗', - '🤭', - '🤫', - '🤔', - '🤐', - '🤨', - '😐', - '😑', - '😶', - '😏', - '😒', - '🙄', - '😬', - '🤥', - '😌', - '😔', - '😪', - '🤤', - '😴', - '😷', - '🤒', - '🤕', - '🤢', - '🤮', - '🤧', - '🥵', - '🥶', - '🥴', - '😵', - '🤯', - '🤠', - '🥳', - '😎', - '🤓', - '🧐', - '😕', - '😟', - '🙁', - '☹️', - '😮', - '😯', - '😲', - '😳', - '🥺', - '😦', - '😧', - '😨', - '😰', - '😥', - '😢', - '😭', - '😱', - '😖', - '😣', - '😞', - '😓', - '😩', - '😫', - '😤', - '😡', - '😠', - '🤬', - '😈', - '👿', - '💀', - '☠', - '💩', - '🤡', - '👹', - '👺', - '👻', - '👽', - '👾', - '🤖', - '😺', - '😸', - '😹', - '😻', - '😼', - '😽', - '🙀', - '😿', - '😾', - '💋', - '👋', - '🤚', - '🖐', - '✋', - '🖖', - '👌', - '✌', - '🤞', - '🤟', - '🤘', - '🤙', - '👈', - '👉', - '👆', - '🖕', - '👇', - '☝', - '👍', - '👎', - '✊', - '👊', - '🤛', - '🤜', - '👏', - '🙌', - '👐', - '🤲', - '🤝', - '🙏', - '✍', - '💅', - '🤳', - '💪', - '🦵', - '🦶', - '👂', - '👃', - '🧠', - '🦷', - '🦴', - '👀', - '👁', - '👅', - '👄', - '👶', - '🧒', - '👦', - '👧', - '🧑', - '👨', - '🧔', - '👱', - '👨‍🦰', - '👨‍🦱', - '👨‍🦳', - '👨‍🦲', - '👩', - '👱', - '👩‍🦰', - '👩‍🦱', - '👩‍🦳', - '👩‍🦲', - '🧓', - '👴', - '👵', - '🙍', - '🙍', - '🙎', - '🙎', - '🙅', - '🙅', - '🙆', - '🙆', - '💁', - '💁', - '🙋', - '🙋', - '🙇', - '🙇', - '🤦', - '🤦', - '🤷', - '🤷', - '👨‍⚕️', - '👩‍⚕️', - '👨‍🎓', - '👩‍🎓', - '👨‍🏫', - '👩‍🏫', - '👨‍⚖️', - '👩‍⚖️', - '👨‍🌾', - '👩‍🌾', - '👨‍🍳', - '👩‍🍳', - '👨‍🔧', - '👩‍🔧', - '👨‍🏭', - '👩‍🏭', - '👨‍💼', - '👩‍💼', - '👨‍🔬', - '👩‍🔬', - '👨‍💻', - '👩‍💻', - '👨‍🎤', - '👩‍🎤', - '👨‍🎨', - '👩‍🎨', - '👨‍✈️', - '👩‍✈️', - '👨‍🚀', - '👩‍🚀', - '👨‍🚒', - '👩‍🚒', - '👮', - '👮', - '🕵️', - '🕵️', - '💂', - '💂', - '👷', - '👷', - '🤴', - '👸', - '👳', - '👳', - '👲', - '🧕', - '🤵', - '👰', - '🤰', - '🤱', - '👼', - '🎅', - '🤶', - '🦸', - '🦸', - '🦹', - '🦹', - '🧙', - '🧙', - '🧚', - '🧚', - '🧛', - '🧛', - '🧜', - '🧜', - '🧝', - '🧝', - '🧞', - '🧞', - '🧟', - '🧟', - '💆', - '💆', - '💇', - '💇', - '🚶', - '🚶', - '🏃', - '🏃', - '💃', - '🕺', - '🕴', - '👯', - '👯', - '🧖', - '🧖', - '🧘', - '👭', - '👫', - '👬', - '💏', - '👨‍❤️‍💋‍👨', - '👩‍❤️‍💋‍👩', - '💑', - '👨‍❤️‍👨', - '👩‍❤️‍👩', - '👪', - '👨‍👩‍👦', - '👨‍👩‍👧', - '👨‍👩‍👧‍👦', - '👨‍👩‍👦‍👦', - '👨‍👩‍👧‍👧', - '👨‍👨‍👦', - '👨‍👨‍👧', - '👨‍👨‍👧‍👦', - '👨‍👨‍👦‍👦', - '👨‍👨‍👧‍👧', - '👩‍👩‍👦', - '👩‍👩‍👧', - '👩‍👩‍👧‍👦', - '👩‍👩‍👦‍👦', - '👩‍👩‍👧‍👧', - '👨‍👦', - '👨‍👦‍👦', - '👨‍👧', - '👨‍👧‍👦', - '👨‍👧‍👧', - '👩‍👦', - '👩‍👦‍👦', - '👩‍👧', - '👩‍👧‍👦', - '👩‍👧‍👧', - '🗣', - '👤', - '👥', - '👣', - '🧳', - '🌂', - '☂', - '🧵', - '🧶', - '👓', - '🕶', - '🥽', - '🥼', - '👔', - '👕', - '👖', - '🧣', - '🧤', - '🧥', - '🧦', - '👗', - '👘', - '👙', - '👚', - '👛', - '👜', - '👝', - '🎒', - '👞', - '👟', - '🥾', - '🥿', - '👠', - '👡', - '👢', - '👑', - '👒', - '🎩', - '🎓', - '🧢', - '⛑', - '💄', - '💍', - '💼' -]); - -/// Map of all possible emojis along with their names in [Category.ANIMALS] -final Map animals = Map.fromIterables([ - 'Dog Face', - 'Cat Face', - 'Mouse Face', - 'Hamster Face', - 'Rabbit Face', - 'Fox Face', - 'Bear Face', - 'Panda Face', - 'Koala Face', - 'Tiger Face', - 'Lion Face', - 'Cow Face', - 'Pig Face', - 'Pig Nose', - 'Frog Face', - 'Monkey Face', - 'See-No-Evil Monkey', - 'Hear-No-Evil Monkey', - 'Speak-No-Evil Monkey', - 'Monkey', - 'Collision', - 'Dizzy', - 'Sweat Droplets', - 'Dashing Away', - 'Gorilla', - 'Dog', - 'Poodle', - 'Wolf Face', - 'Raccoon', - 'Cat', - 'Tiger', - 'Leopard', - 'Horse Face', - 'Horse', - 'Unicorn Face', - 'Zebra', - 'Ox', - 'Water Buffalo', - 'Cow', - 'Pig', - 'Boar', - 'Ram', - 'Ewe', - 'Goat', - 'Camel', - 'Two-Hump Camel', - 'Llama', - 'Giraffe', - 'Elephant', - 'Rhinoceros', - 'Hippopotamus', - 'Mouse', - 'Rat', - 'Rabbit', - 'Chipmunk', - 'Hedgehog', - 'Bat', - 'Kangaroo', - 'Badger', - 'Paw Prints', - 'Turkey', - 'Chicken', - 'Rooster', - 'Hatching Chick', - 'Baby Chick', - 'Front-Facing Baby Chick', - 'Bird', - 'Penguin', - 'Dove', - 'Eagle', - 'Duck', - 'Swan', - 'Owl', - 'Peacock', - 'Parrot', - 'Crocodile', - 'Turtle', - 'Lizard', - 'Snake', - 'Dragon Face', - 'Dragon', - 'Sauropod', - 'T-Rex', - 'Spouting Whale', - 'Whale', - 'Dolphin', - 'Fish', - 'Tropical Fish', - 'Blowfish', - 'Shark', - 'Octopus', - 'Spiral Shell', - 'Snail', - 'Butterfly', - 'Bug', - 'Ant', - 'Honeybee', - 'Lady Beetle', - 'Cricket', - 'Spider', - 'Spider Web', - 'Scorpion', - 'Mosquito', - 'Microbe', - 'Bouquet', - 'Cherry Blossom', - 'White Flower', - 'Rosette', - 'Rose', - 'Wilted Flower', - 'Hibiscus', - 'Sunflower', - 'Blossom', - 'Tulip', - 'Seedling', - 'Evergreen Tree', - 'Deciduous Tree', - 'Palm Tree', - 'Cactus', - 'Sheaf of Rice', - 'Herb', - 'Shamrock', - 'Four Leaf Clover', - 'Maple Leaf', - 'Fallen Leaf', - 'Leaf Fluttering in Wind', - 'Mushroom', - 'Chestnut', - 'Crab', - 'Lobster', - 'Shrimp', - 'Squid', - 'Globe Showing Europe-Africa', - 'Globe Showing Americas', - 'Globe Showing Asia-Australia', - 'Globe With Meridians', - 'New Moon', - 'Waxing Crescent Moon', - 'First Quarter Moon', - 'Waxing Gibbous Moon', - 'Full Moon', - 'Waning Gibbous Moon', - 'Last Quarter Moon', - 'Waning Crescent Moon', - 'Crescent Moon', - 'New Moon Face', - 'First Quarter Moon Face', - 'Last Quarter Moon Face', - 'Sun', - 'Full Moon Face', - 'Sun With Face', - 'Star', - 'Glowing Star', - 'Shooting Star', - 'Cloud', - 'Sun Behind Cloud', - 'Cloud With Lightning and Rain', - 'Sun Behind Small Cloud', - 'Sun Behind Large Cloud', - 'Sun Behind Rain Cloud', - 'Cloud With Rain', - 'Cloud With Snow', - 'Cloud With Lightning', - 'Tornado', - 'Fog', - 'Wind Face', - 'Rainbow', - 'Umbrella', - 'Umbrella With Rain Drops', - 'High Voltage', - 'Snowflake', - 'Snowman Without Snow', - 'Snowman', - 'Comet', - 'Fire', - 'Droplet', - 'Water Wave', - 'Christmas Tree', - 'Sparkles', - 'Tanabata Tree', - 'Pine Decoration' -], [ - '🐶', - '🐱', - '🐭', - '🐹', - '🐰', - '🦊', - '🐻', - '🐼', - '🐨', - '🐯', - '🦁', - '🐮', - '🐷', - '🐽', - '🐸', - '🐵', - '🙈', - '🙉', - '🙊', - '🐒', - '💥', - '💫', - '💦', - '💨', - '🦍', - '🐕', - '🐩', - '🐺', - '🦝', - '🐈', - '🐅', - '🐆', - '🐴', - '🐎', - '🦄', - '🦓', - '🐂', - '🐃', - '🐄', - '🐖', - '🐗', - '🐏', - '🐑', - '🐐', - '🐪', - '🐫', - '🦙', - '🦒', - '🐘', - '🦏', - '🦛', - '🐁', - '🐀', - '🐇', - '🐿', - '🦔', - '🦇', - '🦘', - '🦡', - '🐾', - '🦃', - '🐔', - '🐓', - '🐣', - '🐤', - '🐥', - '🐦', - '🐧', - '🕊', - '🦅', - '🦆', - '🦢', - '🦉', - '🦚', - '🦜', - '🐊', - '🐢', - '🦎', - '🐍', - '🐲', - '🐉', - '🦕', - '🦖', - '🐳', - '🐋', - '🐬', - '🐟', - '🐠', - '🐡', - '🦈', - '🐙', - '🐚', - '🐌', - '🦋', - '🐛', - '🐜', - '🐝', - '🐞', - '🦗', - '🕷', - '🕸', - '🦂', - '🦟', - '🦠', - '💐', - '🌸', - '💮', - '🏵', - '🌹', - '🥀', - '🌺', - '🌻', - '🌼', - '🌷', - '🌱', - '🌲', - '🌳', - '🌴', - '🌵', - '🌾', - '🌿', - '☘', - '🍀', - '🍁', - '🍂', - '🍃', - '🍄', - '🌰', - '🦀', - '🦞', - '🦐', - '🦑', - '🌍', - '🌎', - '🌏', - '🌐', - '🌑', - '🌒', - '🌓', - '🌔', - '🌕', - '🌖', - '🌗', - '🌘', - '🌙', - '🌚', - '🌛', - '🌜', - '☀', - '🌝', - '🌞', - '⭐', - '🌟', - '🌠', - '☁', - '⛅', - '⛈', - '🌤', - '🌥', - '🌦', - '🌧', - '🌨', - '🌩', - '🌪', - '🌫', - '🌬', - '🌈', - '☂', - '☔', - '⚡', - '❄', - '☃', - '⛄', - '☄', - '🔥', - '💧', - '🌊', - '🎄', - '✨', - '🎋', - '🎍' -]); - -/// Map of all possible emojis along with their names in [Category.FOODS] -final Map foods = Map.fromIterables([ - 'Grapes', - 'Melon', - 'Watermelon', - 'Tangerine', - 'Lemon', - 'Banana', - 'Pineapple', - 'Mango', - 'Red Apple', - 'Green Apple', - 'Pear', - 'Peach', - 'Cherries', - 'Strawberry', - 'Kiwi Fruit', - 'Tomato', - 'Coconut', - 'Avocado', - 'Eggplant', - 'Potato', - 'Carrot', - 'Ear of Corn', - 'Hot Pepper', - 'Cucumber', - 'Leafy Green', - 'Broccoli', - 'Mushroom', - 'Peanuts', - 'Chestnut', - 'Bread', - 'Croissant', - 'Baguette Bread', - 'Pretzel', - 'Bagel', - 'Pancakes', - 'Cheese Wedge', - 'Meat on Bone', - 'Poultry Leg', - 'Cut of Meat', - 'Bacon', - 'Hamburger', - 'French Fries', - 'Pizza', - 'Hot Dog', - 'Sandwich', - 'Taco', - 'Burrito', - 'Stuffed Flatbread', - 'Cooking', - 'Shallow Pan of Food', - 'Pot of Food', - 'Bowl With Spoon', - 'Green Salad', - 'Popcorn', - 'Salt', - 'Canned Food', - 'Bento Box', - 'Rice Cracker', - 'Rice Ball', - 'Cooked Rice', - 'Curry Rice', - 'Steaming Bowl', - 'Spaghetti', - 'Roasted Sweet Potato', - 'Oden', - 'Sushi', - 'Fried Shrimp', - 'Fish Cake With Swirl', - 'Moon Cake', - 'Dango', - 'Dumpling', - 'Fortune Cookie', - 'Takeout Box', - 'Soft Ice Cream', - 'Shaved Ice', - 'Ice Cream', - 'Doughnut', - 'Cookie', - 'Birthday Cake', - 'Shortcake', - 'Cupcake', - 'Pie', - 'Chocolate Bar', - 'Candy', - 'Lollipop', - 'Custard', - 'Honey Pot', - 'Baby Bottle', - 'Glass of Milk', - 'Hot Beverage', - 'Teacup Without Handle', - 'Sake', - 'Bottle With Popping Cork', - 'Wine Glass', - 'Cocktail Glass', - 'Tropical Drink', - 'Beer Mug', - 'Clinking Beer Mugs', - 'Clinking Glasses', - 'Tumbler Glass', - 'Cup With Straw', - 'Chopsticks', - 'Fork and Knife With Plate', - 'Fork and Knife', - 'Spoon' -], [ - '🍇', - '🍈', - '🍉', - '🍊', - '🍋', - '🍌', - '🍍', - '🥭', - '🍎', - '🍏', - '🍐', - '🍑', - '🍒', - '🍓', - '🥝', - '🍅', - '🥥', - '🥑', - '🍆', - '🥔', - '🥕', - '🌽', - '🌶', - '🥒', - '🥬', - '🥦', - '🍄', - '🥜', - '🌰', - '🍞', - '🥐', - '🥖', - '🥨', - '🥯', - '🥞', - '🧀', - '🍖', - '🍗', - '🥩', - '🥓', - '🍔', - '🍟', - '🍕', - '🌭', - '🥪', - '🌮', - '🌯', - '🥙', - '🍳', - '🥘', - '🍲', - '🥣', - '🥗', - '🍿', - '🧂', - '🥫', - '🍱', - '🍘', - '🍙', - '🍚', - '🍛', - '🍜', - '🍝', - '🍠', - '🍢', - '🍣', - '🍤', - '🍥', - '🥮', - '🍡', - '🥟', - '🥠', - '🥡', - '🍦', - '🍧', - '🍨', - '🍩', - '🍪', - '🎂', - '🍰', - '🧁', - '🥧', - '🍫', - '🍬', - '🍭', - '🍮', - '🍯', - '🍼', - '🥛', - '☕', - '🍵', - '🍶', - '🍾', - '🍷', - '🍸', - '🍹', - '🍺', - '🍻', - '🥂', - '🥃', - '🥤', - '🥢', - '🍽', - '🍴', - '🥄' -]); - -/// Map of all possible emojis along with their names in [Category.TRAVEL] -final Map travel = Map.fromIterables([ - 'Person Rowing Boat', - 'Map of Japan', - 'Snow-Capped Mountain', - 'Mountain', - 'Volcano', - 'Mount Fuji', - 'Camping', - 'Beach With Umbrella', - 'Desert', - 'Desert Island', - 'National Park', - 'Stadium', - 'Classical Building', - 'Building Construction', - 'Houses', - 'Derelict House', - 'House', - 'House With Garden', - 'Office Building', - 'Japanese Post Office', - 'Post Office', - 'Hospital', - 'Bank', - 'Hotel', - 'Love Hotel', - 'Convenience Store', - 'School', - 'Department Store', - 'Factory', - 'Japanese Castle', - 'Castle', - 'Wedding', - 'Tokyo Tower', - 'Statue of Liberty', - 'Church', - 'Mosque', - 'Synagogue', - 'Shinto Shrine', - 'Kaaba', - 'Fountain', - 'Tent', - 'Foggy', - 'Night With Stars', - 'Cityscape', - 'Sunrise Over Mountains', - 'Sunrise', - 'Cityscape at Dusk', - 'Sunset', - 'Bridge at Night', - 'Carousel Horse', - 'Ferris Wheel', - 'Roller Coaster', - 'Locomotive', - 'Railway Car', - 'High-Speed Train', - 'Bullet Train', - 'Train', - 'Metro', - 'Light Rail', - 'Station', - 'Tram', - 'Monorail', - 'Mountain Railway', - 'Tram Car', - 'Bus', - 'Oncoming Bus', - 'Trolleybus', - 'Minibus', - 'Ambulance', - 'Fire Engine', - 'Police Car', - 'Oncoming Police Car', - 'Taxi', - 'Oncoming Taxi', - 'Automobile', - 'Oncoming Automobile', - 'Delivery Truck', - 'Articulated Lorry', - 'Tractor', - 'Racing Car', - 'Motorcycle', - 'Motor Scooter', - 'Bicycle', - 'Kick Scooter', - 'Bus Stop', - 'Railway Track', - 'Fuel Pump', - 'Police Car Light', - 'Horizontal Traffic Light', - 'Vertical Traffic Light', - 'Construction', - 'Anchor', - 'Sailboat', - 'Speedboat', - 'Passenger Ship', - 'Ferry', - 'Motor Boat', - 'Ship', - 'Airplane', - 'Small Airplane', - 'Airplane Departure', - 'Airplane Arrival', - 'Seat', - 'Helicopter', - 'Suspension Railway', - 'Mountain Cableway', - 'Aerial Tramway', - 'Satellite', - 'Rocket', - 'Flying Saucer', - 'Shooting Star', - 'Milky Way', - 'Umbrella on Ground', - 'Fireworks', - 'Sparkler', - 'Moon Viewing Ceremony', - 'Yen Banknote', - 'Dollar Banknote', - 'Euro Banknote', - 'Pound Banknote', - 'Moai', - 'Passport Control', - 'Customs', - 'Baggage Claim', - 'Left Luggage' -], [ - '🚣', - '🗾', - '🏔', - '⛰', - '🌋', - '🗻', - '🏕', - '🏖', - '🏜', - '🏝', - '🏞', - '🏟', - '🏛', - '🏗', - '🏘', - '🏚', - '🏠', - '🏡', - '🏢', - '🏣', - '🏤', - '🏥', - '🏦', - '🏨', - '🏩', - '🏪', - '🏫', - '🏬', - '🏭', - '🏯', - '🏰', - '💒', - '🗼', - '🗽', - '⛪', - '🕌', - '🕍', - '⛩', - '🕋', - '⛲', - '⛺', - '🌁', - '🌃', - '🏙', - '🌄', - '🌅', - '🌆', - '🌇', - '🌉', - '🎠', - '🎡', - '🎢', - '🚂', - '🚃', - '🚄', - '🚅', - '🚆', - '🚇', - '🚈', - '🚉', - '🚊', - '🚝', - '🚞', - '🚋', - '🚌', - '🚍', - '🚎', - '🚐', - '🚑', - '🚒', - '🚓', - '🚔', - '🚕', - '🚖', - '🚗', - '🚘', - '🚚', - '🚛', - '🚜', - '🏎', - '🏍', - '🛵', - '🚲', - '🛴', - '🚏', - '🛤', - '⛽', - '🚨', - '🚥', - '🚦', - '🚧', - '⚓', - '⛵', - '🚤', - '🛳', - '⛴', - '🛥', - '🚢', - '✈', - '🛩', - '🛫', - '🛬', - '💺', - '🚁', - '🚟', - '🚠', - '🚡', - '🛰', - '🚀', - '🛸', - '🌠', - '🌌', - '⛱', - '🎆', - '🎇', - '🎑', - '💴', - '💵', - '💶', - '💷', - '🗿', - '🛂', - '🛃', - '🛄', - '🛅' -]); - -/// Map of all possible emojis along with their names in [Category.ACTIVITIES] -final Map activities = Map.fromIterables([ - 'Man in Suit Levitating', - 'Man Climbing', - 'Woman Climbing', - 'Horse Racing', - 'Skier', - 'Snowboarder', - 'Man Golfing', - 'Woman Golfing', - 'Man Surfing', - 'Woman Surfing', - 'Man Rowing Boat', - 'Woman Rowing Boat', - 'Man Swimming', - 'Woman Swimming', - 'Man Bouncing Ball', - 'Woman Bouncing Ball', - 'Man Lifting Weights', - 'Woman Lifting Weights', - 'Man Biking', - 'Woman Biking', - 'Man Mountain Biking', - 'Woman Mountain Biking', - 'Man Cartwheeling', - 'Woman Cartwheeling', - 'Men Wrestling', - 'Women Wrestling', - 'Man Playing Water Polo', - 'Woman Playing Water Polo', - 'Man Playing Handball', - 'Woman Playing Handball', - 'Man Juggling', - 'Woman Juggling', - 'Man in Lotus Position', - 'Woman in Lotus Position', - 'Circus Tent', - 'Skateboard', - 'Reminder Ribbon', - 'Admission Tickets', - 'Ticket', - 'Military Medal', - 'Trophy', - 'Sports Medal', - '1st Place Medal', - '2nd Place Medal', - '3rd Place Medal', - 'Soccer Ball', - 'Baseball', - 'Softball', - 'Basketball', - 'Volleyball', - 'American Football', - 'Rugby Football', - 'Tennis', - 'Flying Disc', - 'Bowling', - 'Cricket Game', - 'FieldPB Hockey', - 'Ice Hockey', - 'Lacrosse', - 'Ping Pong', - 'Badminton', - 'Boxing Glove', - 'Martial Arts Uniform', - 'Flag in Hole', - 'Ice Skate', - 'Fishing Pole', - 'Running Shirt', - 'Skis', - 'Sled', - 'Curling Stone', - 'Direct Hit', - 'Pool 8 Ball', - 'Video Game', - 'Slot Machine', - 'Game Die', - 'Jigsaw', - 'Chess Pawn', - 'Performing Arts', - 'Artist Palette', - 'Thread', - 'Yarn', - 'Musical Score', - 'Microphone', - 'Headphone', - 'Saxophone', - 'Guitar', - 'Musical Keyboard', - 'Trumpet', - 'Violin', - 'Drum', - 'Clapper Board', - 'Bow and Arrow' -], [ - '🕴', - '🧗', - '🧗', - '🏇', - '⛷', - '🏂', - '🏌️', - '🏌️', - '🏄', - '🏄', - '🚣', - '🚣', - '🏊', - '🏊', - '⛹️', - '⛹️', - '🏋️', - '🏋️', - '🚴', - '🚴', - '🚵', - '🚵', - '🤸', - '🤸', - '🤼', - '🤼', - '🤽', - '🤽', - '🤾', - '🤾', - '🤹', - '🤹', - '🧘🏻‍♂️', - '🧘🏻‍♀️', - '🎪', - '🛹', - '🎗', - '🎟', - '🎫', - '🎖', - '🏆', - '🏅', - '🥇', - '🥈', - '🥉', - '⚽', - '⚾', - '🥎', - '🏀', - '🏐', - '🏈', - '🏉', - '🎾', - '🥏', - '🎳', - '🏏', - '🏑', - '🏒', - '🥍', - '🏓', - '🏸', - '🥊', - '🥋', - '⛳', - '⛸', - '🎣', - '🎽', - '🎿', - '🛷', - '🥌', - '🎯', - '🎱', - '🎮', - '🎰', - '🎲', - '🧩', - '♟', - '🎭', - '🎨', - '🧵', - '🧶', - '🎼', - '🎤', - '🎧', - '🎷', - '🎸', - '🎹', - '🎺', - '🎻', - '🥁', - '🎬', - '🏹' -]); - -/// Map of all possible emojis along with their names in [Category.OBJECTS] -final Map objects = Map.fromIterables([ - 'Love Letter', - 'Hole', - 'Bomb', - 'Person Taking Bath', - 'Person in Bed', - 'Kitchen Knife', - 'Amphora', - 'World Map', - 'Compass', - 'Brick', - 'Barber Pole', - 'Oil Drum', - 'Bellhop Bell', - 'Luggage', - 'Hourglass Done', - 'Hourglass Not Done', - 'Watch', - 'Alarm Clock', - 'Stopwatch', - 'Timer Clock', - 'Mantelpiece Clock', - 'Thermometer', - 'Umbrella on Ground', - 'Firecracker', - 'Balloon', - 'Party Popper', - 'Confetti Ball', - 'Japanese Dolls', - 'Carp Streamer', - 'Wind Chime', - 'Red Envelope', - 'Ribbon', - 'Wrapped Gift', - 'Crystal Ball', - 'Nazar Amulet', - 'Joystick', - 'Teddy Bear', - 'Framed Picture', - 'Thread', - 'Yarn', - 'Shopping Bags', - 'Prayer Beads', - 'Gem Stone', - 'Postal Horn', - 'Studio Microphone', - 'Level Slider', - 'Control Knobs', - 'Radio', - 'Mobile Phone', - 'Mobile Phone With Arrow', - 'Telephone', - 'Telephone Receiver', - 'Pager', - 'Fax Machine', - 'Battery', - 'Electric Plug', - 'Laptop Computer', - 'Desktop Computer', - 'Printer', - 'Keyboard', - 'Computer Mouse', - 'Trackball', - 'Computer Disk', - 'Floppy Disk', - 'Optical Disk', - 'DVD', - 'Abacus', - 'Movie Camera', - 'Film Frames', - 'Film Projector', - 'Television', - 'Camera', - 'Camera With Flash', - 'Video Camera', - 'Videocassette', - 'Magnifying Glass Tilted Left', - 'Magnifying Glass Tilted Right', - 'Candle', - 'Light Bulb', - 'Flashlight', - 'Red Paper Lantern', - 'Notebook With Decorative Cover', - 'Closed Book', - 'Open Book', - 'Green Book', - 'Blue Book', - 'Orange Book', - 'Books', - 'Notebook', - 'Page With Curl', - 'Scroll', - 'Page Facing Up', - 'Newspaper', - 'Rolled-Up Newspaper', - 'Bookmark Tabs', - 'Bookmark', - 'Label', - 'Money Bag', - 'Yen Banknote', - 'Dollar Banknote', - 'Euro Banknote', - 'Pound Banknote', - 'Money With Wings', - 'Credit Card', - 'Receipt', - 'Envelope', - 'E-Mail', - 'Incoming Envelope', - 'Envelope With Arrow', - 'Outbox Tray', - 'Inbox Tray', - 'Package', - 'Closed Mailbox With Raised Flag', - 'Closed Mailbox With Lowered Flag', - 'Open Mailbox With Raised Flag', - 'Open Mailbox With Lowered Flag', - 'Postbox', - 'Ballot Box With Ballot', - 'Pencil', - 'Black Nib', - 'Fountain Pen', - 'Pen', - 'Paintbrush', - 'Crayon', - 'Memo', - 'File Folder', - 'Open File Folder', - 'Card Index Dividers', - 'Calendar', - 'Tear-Off Calendar', - 'Spiral Notepad', - 'Spiral Calendar', - 'Card Index', - 'Chart Increasing', - 'Chart Decreasing', - 'Bar Chart', - 'Clipboard', - 'Pushpin', - 'Round Pushpin', - 'Paperclip', - 'Linked Paperclips', - 'Straight Ruler', - 'Triangular Ruler', - 'Scissors', - 'Card File Box', - 'File Cabinet', - 'Wastebasket', - 'Locked', - 'Unlocked', - 'Locked With Pen', - 'Locked With Key', - 'Key', - 'Old Key', - 'Hammer', - 'Pick', - 'Hammer and Pick', - 'Hammer and Wrench', - 'Dagger', - 'Crossed Swords', - 'Pistol', - 'Shield', - 'Wrench', - 'Nut and Bolt', - 'Gear', - 'Clamp', - 'Balance Scale', - 'Link', - 'Chains', - 'Toolbox', - 'Magnet', - 'Alembic', - 'Test Tube', - 'Petri Dish', - 'DNA', - 'Microscope', - 'Telescope', - 'Satellite Antenna', - 'Syringe', - 'Pill', - 'Door', - 'Bed', - 'Couch and Lamp', - 'Toilet', - 'Shower', - 'Bathtub', - 'Lotion Bottle', - 'Safety Pin', - 'Broom', - 'Basket', - 'Roll of Paper', - 'Soap', - 'Sponge', - 'Fire Extinguisher', - 'Cigarette', - 'Coffin', - 'Funeral Urn', - 'Moai', - 'Potable Water' -], [ - '💌', - '🕳', - '💣', - '🛀', - '🛌', - '🔪', - '🏺', - '🗺', - '🧭', - '🧱', - '💈', - '🛢', - '🛎', - '🧳', - '⌛', - '⏳', - '⌚', - '⏰', - '⏱', - '⏲', - '🕰', - '🌡', - '⛱', - '🧨', - '🎈', - '🎉', - '🎊', - '🎎', - '🎏', - '🎐', - '🧧', - '🎀', - '🎁', - '🔮', - '🧿', - '🕹', - '🧸', - '🖼', - '🧵', - '🧶', - '🛍', - '📿', - '💎', - '📯', - '🎙', - '🎚', - '🎛', - '📻', - '📱', - '📲', - '☎', - '📞', - '📟', - '📠', - '🔋', - '🔌', - '💻', - '🖥', - '🖨', - '⌨', - '🖱', - '🖲', - '💽', - '💾', - '💿', - '📀', - '🧮', - '🎥', - '🎞', - '📽', - '📺', - '📷', - '📸', - '📹', - '📼', - '🔍', - '🔎', - '🕯', - '💡', - '🔦', - '🏮', - '📔', - '📕', - '📖', - '📗', - '📘', - '📙', - '📚', - '📓', - '📃', - '📜', - '📄', - '📰', - '🗞', - '📑', - '🔖', - '🏷', - '💰', - '💴', - '💵', - '💶', - '💷', - '💸', - '💳', - '🧾', - '✉', - '📧', - '📨', - '📩', - '📤', - '📥', - '📦', - '📫', - '📪', - '📬', - '📭', - '📮', - '🗳', - '✏', - '✒', - '🖋', - '🖊', - '🖌', - '🖍', - '📝', - '📁', - '📂', - '🗂', - '📅', - '📆', - '🗒', - '🗓', - '📇', - '📈', - '📉', - '📊', - '📋', - '📌', - '📍', - '📎', - '🖇', - '📏', - '📐', - '✂', - '🗃', - '🗄', - '🗑', - '🔒', - '🔓', - '🔏', - '🔐', - '🔑', - '🗝', - '🔨', - '⛏', - '⚒', - '🛠', - '🗡', - '⚔', - '🔫', - '🛡', - '🔧', - '🔩', - '⚙', - '🗜', - '⚖', - '🔗', - '⛓', - '🧰', - '🧲', - '⚗', - '🧪', - '🧫', - '🧬', - '🔬', - '🔭', - '📡', - '💉', - '💊', - '🚪', - '🛏', - '🛋', - '🚽', - '🚿', - '🛁', - '🧴', - '🧷', - '🧹', - '🧺', - '🧻', - '🧼', - '🧽', - '🧯', - '🚬', - '⚰', - '⚱', - '🗿', - '🚰' -]); - -/// Map of all possible emojis along with their names in [Category.SYMBOLS] -final Map symbols = Map.fromIterables([ - 'Heart With Arrow', - 'Heart With Ribbon', - 'Sparkling Heart', - 'Growing Heart', - 'Beating Heart', - 'Revolving Hearts', - 'Two Hearts', - 'Heart Decoration', - 'Heavy Heart Exclamation', - 'Broken Heart', - 'Red Heart', - 'Orange Heart', - 'Yellow Heart', - 'Green Heart', - 'Blue Heart', - 'Purple Heart', - 'Black Heart', - 'Hundred Points', - 'Anger Symbol', - 'Speech Balloon', - 'Eye in Speech Bubble', - 'Right Anger Bubble', - 'Thought Balloon', - 'Zzz', - 'White Flower', - 'Hot Springs', - 'Barber Pole', - 'Stop Sign', - 'Twelve O’Clock', - 'Twelve-Thirty', - 'One O’Clock', - 'One-Thirty', - 'Two O’Clock', - 'Two-Thirty', - 'Three O’Clock', - 'Three-Thirty', - 'Four O’Clock', - 'Four-Thirty', - 'Five O’Clock', - 'Five-Thirty', - 'Six O’Clock', - 'Six-Thirty', - 'Seven O’Clock', - 'Seven-Thirty', - 'Eight O’Clock', - 'Eight-Thirty', - 'Nine O’Clock', - 'Nine-Thirty', - 'Ten O’Clock', - 'Ten-Thirty', - 'Eleven O’Clock', - 'Eleven-Thirty', - 'Cyclone', - 'Spade Suit', - 'Heart Suit', - 'Diamond Suit', - 'Club Suit', - 'Joker', - 'Mahjong Red Dragon', - 'Flower Playing Cards', - 'Muted Speaker', - 'Speaker Low Volume', - 'Speaker Medium Volume', - 'Speaker High Volume', - 'Loudspeaker', - 'Megaphone', - 'Postal Horn', - 'Bell', - 'Bell With Slash', - 'Musical Note', - 'Musical Notes', - 'ATM Sign', - 'Litter in Bin Sign', - 'Potable Water', - 'Wheelchair Symbol', - 'Men’s Room', - 'Women’s Room', - 'Restroom', - 'Baby Symbol', - 'Water Closet', - 'Warning', - 'Children Crossing', - 'No Entry', - 'Prohibited', - 'No Bicycles', - 'No Smoking', - 'No Littering', - 'Non-Potable Water', - 'No Pedestrians', - 'No One Under Eighteen', - 'Radioactive', - 'Biohazard', - 'Up Arrow', - 'Up-Right Arrow', - 'Right Arrow', - 'Down-Right Arrow', - 'Down Arrow', - 'Down-Left Arrow', - 'Left Arrow', - 'Up-Left Arrow', - 'Up-Down Arrow', - 'Left-Right Arrow', - 'Right Arrow Curving Left', - 'Left Arrow Curving Right', - 'Right Arrow Curving Up', - 'Right Arrow Curving Down', - 'Clockwise Vertical Arrows', - 'Counterclockwise Arrows Button', - 'Back Arrow', - 'End Arrow', - 'On! Arrow', - 'Soon Arrow', - 'Top Arrow', - 'Place of Worship', - 'Atom Symbol', - 'Om', - 'Star of David', - 'Wheel of Dharma', - 'Yin Yang', - 'Latin Cross', - 'Orthodox Cross', - 'Star and Crescent', - 'Peace Symbol', - 'Menorah', - 'Dotted Six-Pointed Star', - 'Aries', - 'Taurus', - 'Gemini', - 'Cancer', - 'Leo', - 'Virgo', - 'Libra', - 'Scorpio', - 'Sagittarius', - 'Capricorn', - 'Aquarius', - 'Pisces', - 'Ophiuchus', - 'Shuffle Tracks Button', - 'Repeat Button', - 'Repeat Single Button', - 'Play Button', - 'Fast-Forward Button', - 'Reverse Button', - 'Fast Reverse Button', - 'Upwards Button', - 'Fast Up Button', - 'Downwards Button', - 'Fast Down Button', - 'Stop Button', - 'Eject Button', - 'Cinema', - 'Dim Button', - 'Bright Button', - 'Antenna Bars', - 'Vibration Mode', - 'Mobile Phone Off', - 'Infinity', - 'Recycling Symbol', - 'Trident Emblem', - 'Name Badge', - 'Japanese Symbol for Beginner', - 'Heavy Large Circle', - 'White Heavy Check Mark', - 'Ballot Box With Check', - 'Heavy Check Mark', - 'Heavy Multiplication X', - 'Cross Mark', - 'Cross Mark Button', - 'Heavy Plus Sign', - 'Heavy Minus Sign', - 'Heavy Division Sign', - 'Curly Loop', - 'Double Curly Loop', - 'Part Alternation Mark', - 'Eight-Spoked Asterisk', - 'Eight-Pointed Star', - 'Sparkle', - 'Double Exclamation Mark', - 'Exclamation Question Mark', - 'Question Mark', - 'White Question Mark', - 'White Exclamation Mark', - 'Exclamation Mark', - 'Copyright', - 'Registered', - 'Trade Mark', - 'Keycap Number Sign', - 'Keycap Digit Zero', - 'Keycap Digit One', - 'Keycap Digit Two', - 'Keycap Digit Three', - 'Keycap Digit Four', - 'Keycap Digit Five', - 'Keycap Digit Six', - 'Keycap Digit Seven', - 'Keycap Digit Eight', - 'Keycap Digit Nine', - 'Keycap: 10', - 'Input Latin Uppercase', - 'Input Latin Lowercase', - 'Input Numbers', - 'Input Symbols', - 'Input Latin Letters', - 'A Button (Blood Type)', - 'AB Button (Blood Type)', - 'B Button (Blood Type)', - 'CL Button', - 'Cool Button', - 'Free Button', - 'Information', - 'ID Button', - 'Circled M', - 'New Button', - 'NG Button', - 'O Button (Blood Type)', - 'OK Button', - 'P Button', - 'SOS Button', - 'Up! Button', - 'Vs Button', - 'Japanese “Here” Button', - 'Japanese “Service Charge” Button', - 'Japanese “Monthly Amount” Button', - 'Japanese “Not Free of Charge” Button', - 'Japanese “Reserved” Button', - 'Japanese “Bargain” Button', - 'Japanese “Discount” Button', - 'Japanese “Free of Charge” Button', - 'Japanese “Prohibited” Button', - 'Japanese “Acceptable” Button', - 'Japanese “Application” Button', - 'Japanese “Passing Grade” Button', - 'Japanese “Vacancy” Button', - 'Japanese “Congratulations” Button', - 'Japanese “Secret” Button', - 'Japanese “Open for Business” Button', - 'Japanese “No Vacancy” Button', - 'Red Circle', - 'Blue Circle', - 'Black Circle', - 'White Circle', - 'Black Large Square', - 'White Large Square', - 'Black Medium Square', - 'White Medium Square', - 'Black Medium-Small Square', - 'White Medium-Small Square', - 'Black Small Square', - 'White Small Square', - 'Large Orange Diamond', - 'Large Blue Diamond', - 'Small Orange Diamond', - 'Small Blue Diamond', - 'Red Triangle Pointed Up', - 'Red Triangle Pointed Down', - 'Diamond With a Dot', - 'White Square Button', - 'Black Square Button' -], [ - '💘', - '💝', - '💖', - '💗', - '💓', - '💞', - '💕', - '💟', - '❣', - '💔', - '❤', - '🧡', - '💛', - '💚', - '💙', - '💜', - '🖤', - '💯', - '💢', - '💬', - '👁️‍🗨️', - '🗯', - '💭', - '💤', - '💮', - '♨', - '💈', - '🛑', - '🕛', - '🕧', - '🕐', - '🕜', - '🕑', - '🕝', - '🕒', - '🕞', - '🕓', - '🕟', - '🕔', - '🕠', - '🕕', - '🕡', - '🕖', - '🕢', - '🕗', - '🕣', - '🕘', - '🕤', - '🕙', - '🕥', - '🕚', - '🕦', - '🌀', - '♠', - '♥', - '♦', - '♣', - '🃏', - '🀄', - '🎴', - '🔇', - '🔈', - '🔉', - '🔊', - '📢', - '📣', - '📯', - '🔔', - '🔕', - '🎵', - '🎶', - '🏧', - '🚮', - '🚰', - '♿', - '🚹', - '🚺', - '🚻', - '🚼', - '🚾', - '⚠', - '🚸', - '⛔', - '🚫', - '🚳', - '🚭', - '🚯', - '🚱', - '🚷', - '🔞', - '☢', - '☣', - '⬆', - '↗', - '➡', - '↘', - '⬇', - '↙', - '⬅', - '↖', - '↕', - '↔', - '↩', - '↪', - '⤴', - '⤵', - '🔃', - '🔄', - '🔙', - '🔚', - '🔛', - '🔜', - '🔝', - '🛐', - '⚛', - '🕉', - '✡', - '☸', - '☯', - '✝', - '☦', - '☪', - '☮', - '🕎', - '🔯', - '♈', - '♉', - '♊', - '♋', - '♌', - '♍', - '♎', - '♏', - '♐', - '♑', - '♒', - '♓', - '⛎', - '🔀', - '🔁', - '🔂', - '▶', - '⏩', - '◀', - '⏪', - '🔼', - '⏫', - '🔽', - '⏬', - '⏹', - '⏏', - '🎦', - '🔅', - '🔆', - '📶', - '📳', - '📴', - '♾', - '♻', - '🔱', - '📛', - '🔰', - '⭕', - '✅', - '☑', - '✔', - '✖', - '❌', - '❎', - '➕', - '➖', - '➗', - '➰', - '➿', - '〽', - '✳', - '✴', - '❇', - '‼', - '⁉', - '❓', - '❔', - '❕', - '❗', - '©', - '®', - '™', - '#️⃣', - '0️⃣', - '1️⃣', - '2️⃣', - '3️⃣', - '4️⃣', - '5️⃣', - '6️⃣', - '7️⃣', - '8️⃣', - '9️⃣', - '🔟', - '🔠', - '🔡', - '🔢', - '🔣', - '🔤', - '🅰', - '🆎', - '🅱', - '🆑', - '🆒', - '🆓', - 'ℹ', - '🆔', - 'Ⓜ', - '🆕', - '🆖', - '🅾', - '🆗', - '🅿', - '🆘', - '🆙', - '🆚', - '🈁', - '🈂', - '🈷', - '🈶', - '🈯', - '🉐', - '🈹', - '🈚', - '🈲', - '🉑', - '🈸', - '🈴', - '🈳', - '㊗', - '㊙', - '🈺', - '🈵', - '🔴', - '🔵', - '⚫', - '⚪', - '⬛', - '⬜', - '◼', - '◻', - '◾', - '◽', - '▪', - '▫', - '🔶', - '🔷', - '🔸', - '🔹', - '🔺', - '🔻', - '💠', - '🔳', - '🔲' -]); - -/// Map of all possible emojis along with their names in [Category.FLAGS] -final Map flags = Map.fromIterables([ - 'Chequered Flag', - 'Triangular Flag', - 'Crossed Flags', - 'Black Flag', - 'White Flag', - 'Rainbow Flag', - 'Pirate Flag', - 'Flag: Ascension Island', - 'Flag: Andorra', - 'Flag: United Arab Emirates', - 'Flag: Afghanistan', - 'Flag: Antigua & Barbuda', - 'Flag: Anguilla', - 'Flag: Albania', - 'Flag: Armenia', - 'Flag: Angola', - 'Flag: Antarctica', - 'Flag: argentina', - 'Flag: American Samoa', - 'Flag: Austria', - 'Flag: Australia', - 'Flag: Aruba', - 'Flag: Åland Islands', - 'Flag: Azerbaijan', - 'Flag: Bosnia & Herzegovina', - 'Flag: Barbados', - 'Flag: Bangladesh', - 'Flag: Belgium', - 'Flag: Burkina Faso', - 'Flag: Bulgaria', - 'Flag: Bahrain', - 'Flag: Burundi', - 'Flag: Benin', - 'Flag: St. Barthélemy', - 'Flag: Bermuda', - 'Flag: Brunei', - 'Flag: Bolivia', - 'Flag: Caribbean Netherlands', - 'Flag: Brazil', - 'Flag: Bahamas', - 'Flag: Bhutan', - 'Flag: Bouvet Island', - 'Flag: Botswana', - 'Flag: Belarus', - 'Flag: Belize', - 'Flag: Canada', - 'Flag: Cocos (Keeling) Islands', - 'Flag: Congo - Kinshasa', - 'Flag: Central African Republic', - 'Flag: Congo - Brazzaville', - 'Flag: Switzerland', - 'Flag: Côte d’Ivoire', - 'Flag: Cook Islands', - 'Flag: Chile', - 'Flag: Cameroon', - 'Flag: China', - 'Flag: Colombia', - 'Flag: Clipperton Island', - 'Flag: Costa Rica', - 'Flag: Cuba', - 'Flag: Cape Verde', - 'Flag: Curaçao', - 'Flag: Christmas Island', - 'Flag: Cyprus', - 'Flag: Czechia', - 'Flag: Germany', - 'Flag: Diego Garcia', - 'Flag: Djibouti', - 'Flag: Denmark', - 'Flag: Dominica', - 'Flag: Dominican Republic', - 'Flag: Algeria', - 'Flag: Ceuta & Melilla', - 'Flag: Ecuador', - 'Flag: Estonia', - 'Flag: Egypt', - 'Flag: Western Sahara', - 'Flag: Eritrea', - 'Flag: Spain', - 'Flag: Ethiopia', - 'Flag: European Union', - 'Flag: Finland', - 'Flag: Fiji', - 'Flag: Falkland Islands', - 'Flag: Micronesia', - 'Flag: Faroe Islands', - 'Flag: france', - 'Flag: Gabon', - 'Flag: United Kingdom', - 'Flag: Grenada', - 'Flag: Georgia', - 'Flag: French Guiana', - 'Flag: Guernsey', - 'Flag: Ghana', - 'Flag: Gibraltar', - 'Flag: Greenland', - 'Flag: Gambia', - 'Flag: Guinea', - 'Flag: Guadeloupe', - 'Flag: Equatorial Guinea', - 'Flag: Greece', - 'Flag: South Georgia & South Sandwich Islands', - 'Flag: Guatemala', - 'Flag: Guam', - 'Flag: Guinea-Bissau', - 'Flag: Guyana', - 'Flag: Hong Kong SAR China', - 'Flag: Heard & McDonald Islands', - 'Flag: Honduras', - 'Flag: Croatia', - 'Flag: Haiti', - 'Flag: Hungary', - 'Flag: Canary Islands', - 'Flag: Indonesia', - 'Flag: Ireland', - 'Flag: Israel', - 'Flag: Isle of Man', - 'Flag: India', - 'Flag: British Indian Ocean Territory', - 'Flag: Iraq', - 'Flag: Iran', - 'Flag: Iceland', - 'Flag: Italy', - 'Flag: Jersey', - 'Flag: Jamaica', - 'Flag: Jordan', - 'Flag: Japan', - 'Flag: Kenya', - 'Flag: Kyrgyzstan', - 'Flag: Cambodia', - 'Flag: Kiribati', - 'Flag: Comoros', - 'Flag: St. Kitts & Nevis', - 'Flag: North Korea', - 'Flag: South Korea', - 'Flag: Kuwait', - 'Flag: Cayman Islands', - 'Flag: Kazakhstan', - 'Flag: Laos', - 'Flag: Lebanon', - 'Flag: St. Lucia', - 'Flag: Liechtenstein', - 'Flag: Sri Lanka', - 'Flag: Liberia', - 'Flag: Lesotho', - 'Flag: Lithuania', - 'Flag: Luxembourg', - 'Flag: Latvia', - 'Flag: Libya', - 'Flag: Morocco', - 'Flag: Monaco', - 'Flag: Moldova', - 'Flag: Montenegro', - 'Flag: St. Martin', - 'Flag: Madagascar', - 'Flag: Marshall Islands', - 'Flag: North Macedonia', - 'Flag: Mali', - 'Flag: Myanmar (Burma)', - 'Flag: Mongolia', - 'Flag: Macau Sar China', - 'Flag: Northern Mariana Islands', - 'Flag: Martinique', - 'Flag: Mauritania', - 'Flag: Montserrat', - 'Flag: Malta', - 'Flag: Mauritius', - 'Flag: Maldives', - 'Flag: Malawi', - 'Flag: Mexico', - 'Flag: Malaysia', - 'Flag: Mozambique', - 'Flag: Namibia', - 'Flag: New Caledonia', - 'Flag: Niger', - 'Flag: Norfolk Island', - 'Flag: Nigeria', - 'Flag: Nicaragua', - 'Flag: Netherlands', - 'Flag: Norway', - 'Flag: Nepal', - 'Flag: Nauru', - 'Flag: Niue', - 'Flag: New Zealand', - 'Flag: Oman', - 'Flag: Panama', - 'Flag: Peru', - 'Flag: French Polynesia', - 'Flag: Papua New Guinea', - 'Flag: Philippines', - 'Flag: Pakistan', - 'Flag: Poland', - 'Flag: St. Pierre & Miquelon', - 'Flag: Pitcairn Islands', - 'Flag: Puerto Rico', - 'Flag: Palestinian Territories', - 'Flag: Portugal', - 'Flag: Palau', - 'Flag: Paraguay', - 'Flag: Qatar', - 'Flag: Réunion', - 'Flag: Romania', - 'Flag: Serbia', - 'Flag: Russia', - 'Flag: Rwanda', - 'Flag: Saudi Arabia', - 'Flag: Solomon Islands', - 'Flag: Seychelles', - 'Flag: Sudan', - 'Flag: Sweden', - 'Flag: Singapore', - 'Flag: St. Helena', - 'Flag: Slovenia', - 'Flag: Svalbard & Jan Mayen', - 'Flag: Slovakia', - 'Flag: Sierra Leone', - 'Flag: San Marino', - 'Flag: Senegal', - 'Flag: Somalia', - 'Flag: Suriname', - 'Flag: South Sudan', - 'Flag: São Tomé & Príncipe', - 'Flag: El Salvador', - 'Flag: Sint Maarten', - 'Flag: Syria', - 'Flag: Swaziland', - 'Flag: Tristan Da Cunha', - 'Flag: Turks & Caicos Islands', - 'Flag: Chad', - 'Flag: French Southern Territories', - 'Flag: Togo', - 'Flag: Thailand', - 'Flag: Tajikistan', - 'Flag: Tokelau', - 'Flag: Timor-Leste', - 'Flag: Turkmenistan', - 'Flag: Tunisia', - 'Flag: Tonga', - 'Flag: Turkey', - 'Flag: Trinidad & Tobago', - 'Flag: Tuvalu', - 'Flag: Taiwan', - 'Flag: Tanzania', - 'Flag: Ukraine', - 'Flag: Uganda', - 'Flag: U.S. Outlying Islands', - 'Flag: United Nations', - 'Flag: United States', - 'Flag: Uruguay', - 'Flag: Uzbekistan', - 'Flag: Vatican City', - 'Flag: St. Vincent & Grenadines', - 'Flag: Venezuela', - 'Flag: British Virgin Islands', - 'Flag: U.S. Virgin Islands', - 'Flag: Vietnam', - 'Flag: Vanuatu', - 'Flag: Wallis & Futuna', - 'Flag: Samoa', - 'Flag: Kosovo', - 'Flag: Yemen', - 'Flag: Mayotte', - 'Flag: South Africa', - 'Flag: Zambia', - 'Flag: Zimbabwe' -], [ - '🏁', - '🚩', - '🎌', - '🏴', - '🏳', - '🏳️‍🌈', - '🏴‍☠️', - '🇦🇨', - '🇦🇩', - '🇦🇪', - '🇦🇫', - '🇦🇬', - '🇦🇮', - '🇦🇱', - '🇦🇲', - '🇦🇴', - '🇦🇶', - '🇦🇷', - '🇦🇸', - '🇦🇹', - '🇦🇺', - '🇦🇼', - '🇦🇽', - '🇦🇿', - '🇧🇦', - '🇧🇧', - '🇧🇩', - '🇧🇪', - '🇧🇫', - '🇧🇬', - '🇧🇭', - '🇧🇮', - '🇧🇯', - '🇧🇱', - '🇧🇲', - '🇧🇳', - '🇧🇴', - '🇧🇶', - '🇧🇷', - '🇧🇸', - '🇧🇹', - '🇧🇻', - '🇧🇼', - '🇧🇾', - '🇧🇿', - '🇨🇦', - '🇨🇨', - '🇨🇩', - '🇨🇫', - '🇨🇬', - '🇨🇭', - '🇨🇮', - '🇨🇰', - '🇨🇱', - '🇨🇲', - '🇨🇳', - '🇨🇴', - '🇨🇵', - '🇨🇷', - '🇨🇺', - '🇨🇻', - '🇨🇼', - '🇨🇽', - '🇨🇾', - '🇨🇿', - '🇩🇪', - '🇩🇬', - '🇩🇯', - '🇩🇰', - '🇩🇲', - '🇩🇴', - '🇩🇿', - '🇪🇦', - '🇪🇨', - '🇪🇪', - '🇪🇬', - '🇪🇭', - '🇪🇷', - '🇪🇸', - '🇪🇹', - '🇪🇺', - '🇫🇮', - '🇫🇯', - '🇫🇰', - '🇫🇲', - '🇫🇴', - '🇫🇷', - '🇬🇦', - '🇬🇧', - '🇬🇩', - '🇬🇪', - '🇬🇫', - '🇬🇬', - '🇬🇭', - '🇬🇮', - '🇬🇱', - '🇬🇲', - '🇬🇳', - '🇬🇵', - '🇬🇶', - '🇬🇷', - '🇬🇸', - '🇬🇹', - '🇬🇺', - '🇬🇼', - '🇬🇾', - '🇭🇰', - '🇭🇲', - '🇭🇳', - '🇭🇷', - '🇭🇹', - '🇭🇺', - '🇮🇨', - '🇮🇩', - '🇮🇪', - '🇮🇱', - '🇮🇲', - '🇮🇳', - '🇮🇴', - '🇮🇶', - '🇮🇷', - '🇮🇸', - '🇮🇹', - '🇯🇪', - '🇯🇲', - '🇯🇴', - '🇯🇵', - '🇰🇪', - '🇰🇬', - '🇰🇭', - '🇰🇮', - '🇰🇲', - '🇰🇳', - '🇰🇵', - '🇰🇷', - '🇰🇼', - '🇰🇾', - '🇰🇿', - '🇱🇦', - '🇱🇧', - '🇱🇨', - '🇱🇮', - '🇱🇰', - '🇱🇷', - '🇱🇸', - '🇱🇹', - '🇱🇺', - '🇱🇻', - '🇱🇾', - '🇲🇦', - '🇲🇨', - '🇲🇩', - '🇲🇪', - '🇲🇫', - '🇲🇬', - '🇲🇭', - '🇲🇰', - '🇲🇱', - '🇲🇲', - '🇲🇳', - '🇲🇴', - '🇲🇵', - '🇲🇶', - '🇲🇷', - '🇲🇸', - '🇲🇹', - '🇲🇺', - '🇲🇻', - '🇲🇼', - '🇲🇽', - '🇲🇾', - '🇲🇿', - '🇳🇦', - '🇳🇨', - '🇳🇪', - '🇳🇫', - '🇳🇬', - '🇳🇮', - '🇳🇱', - '🇳🇴', - '🇳🇵', - '🇳🇷', - '🇳🇺', - '🇳🇿', - '🇴🇲', - '🇵🇦', - '🇵🇪', - '🇵🇫', - '🇵🇬', - '🇵🇭', - '🇵🇰', - '🇵🇱', - '🇵🇲', - '🇵🇳', - '🇵🇷', - '🇵🇸', - '🇵🇹', - '🇵🇼', - '🇵🇾', - '🇶🇦', - '🇷🇪', - '🇷🇴', - '🇷🇸', - '🇷🇺', - '🇷🇼', - '🇸🇦', - '🇸🇧', - '🇸🇨', - '🇸🇩', - '🇸🇪', - '🇸🇬', - '🇸🇭', - '🇸🇮', - '🇸🇯', - '🇸🇰', - '🇸🇱', - '🇸🇲', - '🇸🇳', - '🇸🇴', - '🇸🇷', - '🇸🇸', - '🇸🇹', - '🇸🇻', - '🇸🇽', - '🇸🇾', - '🇸🇿', - '🇹🇦', - '🇹🇨', - '🇹🇩', - '🇹🇫', - '🇹🇬', - '🇹🇭', - '🇹🇯', - '🇹🇰', - '🇹🇱', - '🇹🇲', - '🇹🇳', - '🇹🇴', - '🇹🇷', - '🇹🇹', - '🇹🇻', - '🇹🇼', - '🇹🇿', - '🇺🇦', - '🇺🇬', - '🇺🇲', - '🇺🇳', - '🇺🇸', - '🇺🇾', - '🇺🇿', - '🇻🇦', - '🇻🇨', - '🇻🇪', - '🇻🇬', - '🇻🇮', - '🇻🇳', - '🇻🇺', - '🇼🇫', - '🇼🇸', - '🇽🇰', - '🇾🇪', - '🇾🇹', - '🇿🇦', - '🇿🇲', - '🇿🇼' -]); diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/emoji_picker_builder.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/emoji_picker_builder.dart deleted file mode 100644 index fe526e01db..0000000000 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/emoji_picker_builder.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'config.dart'; -import 'emoji_view_state.dart'; - -/// Template class for custom implementation -/// Inherit this class to create your own EmojiPicker -abstract class EmojiPickerBuilder extends StatefulWidget { - /// Constructor - const EmojiPickerBuilder(this.config, this.state, {Key? key}) - : super(key: key); - - /// Config for customizations - final Config config; - - /// State that holds current emoji data - final EmojiViewState state; -} diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/emoji_view_state.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/emoji_view_state.dart deleted file mode 100644 index 202f913715..0000000000 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/emoji_view_state.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'models/category_models.dart'; -import 'emoji_picker.dart'; - -/// State that holds current emoji data -class EmojiViewState { - /// Constructor - EmojiViewState( - this.categoryEmoji, - this.onEmojiSelected, - this.onBackspacePressed, - ); - - /// List of all category including their emoji - final List categoryEmoji; - - /// Callback when pressed on emoji - final OnEmojiSelected onEmojiSelected; - - /// Callback when pressed on backspace - final OnBackspacePressed? onBackspacePressed; -} diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/models/category_models.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/models/category_models.dart deleted file mode 100644 index 885ff2ab0c..0000000000 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/models/category_models.dart +++ /dev/null @@ -1,91 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'emoji_model.dart'; -import '../emoji_picker.dart'; - -/// Container for Category and their emoji -class CategoryEmoji { - /// Constructor - CategoryEmoji(this.category, this.emoji); - - /// Category instance - final Category category; - - /// List of emoji of this category - List emoji; - - @override - String toString() { - return 'Name: $category, Emoji: $emoji'; - } -} - -/// Class that defines the icon representing a [Category] -class CategoryIcon { - /// Icon of Category - const CategoryIcon({ - required this.icon, - this.color = const Color(0xffd3d3d3), - this.selectedColor = const Color(0xffb2b2b2), - }); - - /// The icon to represent the category - final IconData icon; - - /// The default color of the icon - final Color color; - - /// The color of the icon once the category is selected - final Color selectedColor; -} - -/// Class used to define all the [CategoryIcon] shown for each [Category] -/// -/// This allows the keyboard to be personalized by changing icons shown. -/// If a [CategoryIcon] is set as null or not defined during initialization, -/// the default icons will be used instead -class CategoryIcons { - /// Constructor - const CategoryIcons({ - this.recentIcon = Icons.access_time, - this.smileyIcon = Icons.tag_faces, - this.animalIcon = Icons.pets, - this.foodIcon = Icons.fastfood, - this.activityIcon = Icons.directions_run, - this.travelIcon = Icons.location_city, - this.objectIcon = Icons.lightbulb_outline, - this.symbolIcon = Icons.emoji_symbols, - this.flagIcon = Icons.flag, - this.searchIcon = Icons.search, - }); - - /// Icon for [Category.RECENT] - final IconData recentIcon; - - /// Icon for [Category.SMILEYS] - final IconData smileyIcon; - - /// Icon for [Category.ANIMALS] - final IconData animalIcon; - - /// Icon for [Category.FOODS] - final IconData foodIcon; - - /// Icon for [Category.ACTIVITIES] - final IconData activityIcon; - - /// Icon for [Category.TRAVEL] - final IconData travelIcon; - - /// Icon for [Category.OBJECTS] - final IconData objectIcon; - - /// Icon for [Category.SYMBOLS] - final IconData symbolIcon; - - /// Icon for [Category.FLAGS] - final IconData flagIcon; - - /// Icon for [Category.SEARCH] - final IconData searchIcon; -} diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/models/emoji_model.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/models/emoji_model.dart deleted file mode 100644 index a1808a9419..0000000000 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/models/emoji_model.dart +++ /dev/null @@ -1,32 +0,0 @@ -/// A class to store data for each individual emoji -class Emoji { - /// Emoji constructor - const Emoji(this.name, this.emoji); - - /// The name or description for this emoji - final String name; - - /// The unicode string for this emoji - /// - /// This is the string that should be displayed to view the emoji - final String emoji; - - @override - String toString() { - // return 'Name: $name, Emoji: $emoji'; - return name; - } - - /// Parse Emoji from json - static Emoji fromJson(Map json) { - return Emoji(json['name'] as String, json['emoji'] as String); - } - - /// Encode Emoji to json - Map toJson() { - return { - 'name': name, - 'emoji': emoji, - }; - } -} diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/models/recent_emoji_model.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/models/recent_emoji_model.dart deleted file mode 100644 index 1571bc9a92..0000000000 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/emoji_picker/src/models/recent_emoji_model.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'emoji_model.dart'; - -/// Class that holds an recent emoji -/// Recent Emoji has an instance of the emoji -/// And a counter, which counts how often this emoji -/// has been used before -class RecentEmoji { - /// Constructor - RecentEmoji(this.emoji, this.counter); - - /// Emoji instance - final Emoji emoji; - - /// Counter how often emoji has been used before - int counter = 0; - - /// Parse RecentEmoji from json - static RecentEmoji fromJson(dynamic json) { - return RecentEmoji( - Emoji.fromJson(json['emoji'] as Map), - json['counter'] as int, - ); - } - - /// Encode RecentEmoji to json - Map toJson() => { - 'emoji': emoji, - 'counter': counter, - }; -} diff --git a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/dandelion.dart b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/dandelion.dart index 306eaf4497..9814728650 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/dandelion.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/dandelion.dart @@ -57,7 +57,7 @@ class DandelionColorScheme extends FlowyColorScheme { main1: _lightDandelionYellow, // cursor color main2: _lightDandelionYellow, - shadow: _black, + shadow: const Color.fromRGBO(0, 0, 0, 0.15), sidebarBg: _lightDandelionGreen, divider: _lightShader6, topbarBg: _white, @@ -111,7 +111,7 @@ class DandelionColorScheme extends FlowyColorScheme { tint9: const Color(0x4d0029FF), main1: _darkMain1, main2: _darkMain1, - shadow: _black, + shadow: const Color(0xff0F131C), sidebarBg: const Color(0xff232B38), divider: _darkShader3, topbarBg: _darkShader1, diff --git a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lavender.dart b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lavender.dart index 90debfb47a..978963b8d8 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lavender.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lavender.dart @@ -107,7 +107,7 @@ class LavenderColorScheme extends FlowyColorScheme { tint9: const Color(0x4d0029FF), main1: _darkMain1, main2: _darkMain1, - shadow: _black, + shadow: const Color(0xff0F131C), sidebarBg: const Color(0xff2D223B), divider: _darkShader3, topbarBg: _darkShader1, diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart index 595991b5c4..909c2f98ce 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart @@ -124,8 +124,8 @@ class ScrollbarState extends State { // Track color var trackColor = widget.trackColor ?? (Theme.of(context).brightness == Brightness.dark - ? AFThemeExtension.of(context).greyHover.withOpacity(.1) - : AFThemeExtension.of(context).greyHover.withOpacity(.3)); + ? AFThemeExtension.of(context).lightGreyHover + : AFThemeExtension.of(context).greyHover); // Layout the stack, it just contains a child, and return Stack( @@ -225,6 +225,7 @@ class ScrollbarListStack extends StatelessWidget { final EdgeInsets? scrollbarPadding; final Color? handleColor; final Color? trackColor; + final bool showTrack; final bool autoHideScrollbar; const ScrollbarListStack({ @@ -238,6 +239,7 @@ class ScrollbarListStack extends StatelessWidget { this.handleColor, this.autoHideScrollbar = true, this.trackColor, + this.showTrack = false, }); @override @@ -262,6 +264,7 @@ class ScrollbarListStack extends StatelessWidget { trackColor: trackColor, handleColor: handleColor, autoHideScrollbar: autoHideScrollbar, + showTrack: showTrack, ), ) // The animate will be used by the children that using styled_widget. diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json index f850b3fc9d..386c86ff29 100644 --- a/frontend/resources/translations/en.json +++ b/frontend/resources/translations/en.json @@ -755,6 +755,9 @@ "gray": "Gray" }, "emoji": { + "search": "Search emoji", + "noRecent": "No recent emoji", + "noEmojiFound": "No emoji found", "filter": "Filter", "random": "Random", "selectSkinTone": "Select skin tone",