Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/emoji_picker_flutter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export 'package:emoji_picker_flutter/src/category_view/category_view.dart';
export 'package:emoji_picker_flutter/src/category_view/category_view_config.dart';
export 'package:emoji_picker_flutter/src/category_view/default_category_tab_bar.dart';
export 'package:emoji_picker_flutter/src/category_view/default_category_view.dart';
export 'package:emoji_picker_flutter/src/category_view/recent_emojis_state_update_policy.dart';
export 'package:emoji_picker_flutter/src/category_view/recent_tab_behavior.dart';
export 'package:emoji_picker_flutter/src/config.dart';
export 'package:emoji_picker_flutter/src/default_emoji_set.dart';
Expand Down
15 changes: 13 additions & 2 deletions lib/src/category_view/category_view_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class CategoryViewConfig {
this.dividerColor,
this.categoryIcons = const CategoryIcons(),
this.customCategoryView,
this.recentEmojisUpdatePolicy = RecentEmojisStateUpdatePolicy.notFromRecent,
});

/// Tab bar height
Expand Down Expand Up @@ -69,6 +70,14 @@ class CategoryViewConfig {
/// Hot reload is not supported
final CategoryViewBuilder? customCategoryView;

/// Determines the behavior of recent emojis list update in the state.
/// It can be configured to prevent recent emojis list from jumping when
/// user selects and emoji.
/// Defaults [RecentEmojisStateUpdatePolicy.notFromRecent].
/// NOTE: This affects only the widget state changes. Locally stored recent
/// emojis list is getting updated regardless of this setting.
final RecentEmojisStateUpdatePolicy recentEmojisUpdatePolicy;

@override
bool operator ==(other) {
return (other is CategoryViewConfig) &&
Expand All @@ -83,7 +92,8 @@ class CategoryViewConfig {
other.iconColorSelected == iconColorSelected &&
other.backspaceColor == backspaceColor &&
other.dividerColor == dividerColor &&
other.categoryIcons == categoryIcons;
other.categoryIcons == categoryIcons &&
other.recentEmojisUpdatePolicy == recentEmojisUpdatePolicy;
}

@override
Expand All @@ -99,5 +109,6 @@ class CategoryViewConfig {
iconColorSelected.hashCode ^
backspaceColor.hashCode ^
dividerColor.hashCode ^
categoryIcons.hashCode;
categoryIcons.hashCode ^
recentEmojisUpdatePolicy.hashCode;
}
20 changes: 20 additions & 0 deletions lib/src/category_view/recent_emojis_state_update_policy.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/// Enum for defining the state update policy for recent emojis.
enum RecentEmojisStateUpdatePolicy {
/// No state updates.
never,

/// State updates only when selected emoji is not from the recent list.
notFromRecent,

/// State updates on every emoji selection.
always;

/// Returns true if the policy is [never].
bool get isNever => this == never;

/// Returns true if the policy is [notFromRecent].
bool get isNotFromRecent => this == notFromRecent;

/// Returns true if the policy is [always].
bool get isAlways => this == always;
}
42 changes: 23 additions & 19 deletions lib/src/emoji_picker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -154,17 +154,14 @@ class EmojiPickerState extends State<EmojiPicker> {
final _emojiPickerInternalUtils = EmojiPickerInternalUtils();

/// Update recentEmoji list from outside using EmojiPickerUtils
void updateRecentEmoji(List<RecentEmoji> recentEmoji,
{bool refresh = false}) {
void updateRecentEmoji(List<RecentEmoji> recentEmoji) {
_recentEmoji = recentEmoji;
final recentTabIndex = _categoryEmoji
.indexWhere((element) => element.category == Category.RECENT);
if (recentTabIndex != -1) {
_categoryEmoji[recentTabIndex] = _categoryEmoji[recentTabIndex]
.copyWith(emoji: _recentEmoji.map((e) => e.emoji).toList());
if (mounted && refresh) {
setState(() {});
}
setState(() {});
}
}

Expand Down Expand Up @@ -300,24 +297,20 @@ class EmojiPickerState extends State<EmojiPicker> {
RecentTabBehavior.POPULAR) {
_emojiPickerInternalUtils
.addEmojiToPopularUsed(emoji: emoji, config: widget.config)
.then((newRecentEmoji) => {
// we don't want to rebuild the widget if user is currently on
// the RECENT tab, it will make emojis jump since sorting
// is based on the use frequency
updateRecentEmoji(newRecentEmoji,
refresh: category != Category.RECENT),
});
.then((newRecentEmoji) {
if (_considerRecentEmojisStateUpdate(category)) {
updateRecentEmoji(newRecentEmoji);
}
});
} else if (widget.config.categoryViewConfig.recentTabBehavior ==
RecentTabBehavior.RECENT) {
_emojiPickerInternalUtils
.addEmojiToRecentlyUsed(emoji: emoji, config: widget.config)
.then((newRecentEmoji) => {
// we don't want to rebuild the widget if user is currently on
// the RECENT tab, it will make emojis jump since sorting
// is based on the use frequency
updateRecentEmoji(newRecentEmoji,
refresh: category != Category.RECENT),
});
.then((newRecentEmoji) {
if (_considerRecentEmojisStateUpdate(category)) {
updateRecentEmoji(newRecentEmoji);
}
});
}

if (widget.textEditingController != null) {
Expand Down Expand Up @@ -356,6 +349,17 @@ class EmojiPickerState extends State<EmojiPicker> {
}
}

bool _considerRecentEmojisStateUpdate(Category? category) {
switch (widget.config.categoryViewConfig.recentEmojisUpdatePolicy) {
case RecentEmojisStateUpdatePolicy.never:
return false;
case RecentEmojisStateUpdatePolicy.notFromRecent:
return category != Category.RECENT;
case RecentEmojisStateUpdatePolicy.always:
return true;
}
}

// Initialize emoji data
Future<void> _updateEmojis() async {
_categoryEmoji.clear();
Expand Down
2 changes: 1 addition & 1 deletion lib/src/emoji_picker_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ class EmojiPickerUtils {
{required GlobalKey<EmojiPickerState> key}) async {
return await EmojiPickerInternalUtils()
.clearRecentEmojisInLocalStorage()
.then((_) => key.currentState?.updateRecentEmoji([], refresh: true));
.then((_) => key.currentState?.updateRecentEmoji([]));
}

/// Returns the emoji regex
Expand Down