mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-10-09 02:54:14 +00:00
fix flutter issues
This commit is contained in:
parent
ced68167d1
commit
76a9455c7c
30 changed files with 149 additions and 138 deletions
|
|
@ -1,3 +1,5 @@
|
|||
// ignore_for_file: constant_identifier_names
|
||||
|
||||
/*
|
||||
* Modified version of https://github.com/Fintasys/emoji_picker_flutter
|
||||
* MIT License
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
* Copyright (c) 2024 Stefan Humm
|
||||
*/
|
||||
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
|
||||
/// Template class for custom implementation
|
||||
/// Inhert this class to create your own Category view
|
||||
|
|
@ -89,7 +89,7 @@ class DefaultCategoryView extends CategoryView {
|
|||
class DefaultCategoryViewState extends CategoryViewState<DefaultCategoryView> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
return ColoredBox(
|
||||
color: widget.config.categoryViewConfig.backgroundColor,
|
||||
child: Row(
|
||||
children: [
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
// ignore_for_file: avoid_equals_and_hash_code_on_mutable_classes
|
||||
|
||||
/*
|
||||
* Modified version of https://github.com/Fintasys/emoji_picker_flutter
|
||||
* MIT License
|
||||
* Copyright (c) 2024 Stefan Humm
|
||||
*/
|
||||
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
|
||||
/// Callback function for custom category view
|
||||
typedef CategoryViewBuilder =
|
||||
|
|
@ -77,7 +79,7 @@ class CategoryViewConfig {
|
|||
final CategoryViewBuilder? customCategoryView;
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
bool operator ==(Object other) {
|
||||
return (other is CategoryViewConfig) &&
|
||||
other.tabBarHeight == tabBarHeight &&
|
||||
other.tabIndicatorAnimDuration == tabIndicatorAnimDuration &&
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
// ignore_for_file: avoid_equals_and_hash_code_on_mutable_classes, prefer_asserts_with_message
|
||||
|
||||
/*
|
||||
* Modified version of https://github.com/Fintasys/emoji_picker_flutter
|
||||
* MIT License
|
||||
* Copyright (c) 2024 Stefan Humm
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/locales/default_emoji_set_locale.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Number of skin tone icons
|
||||
const kSkinToneCount = 6;
|
||||
|
|
@ -89,7 +91,7 @@ class Config {
|
|||
final ResizeConfig resizeConfig;
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
bool operator ==(Object other) {
|
||||
return (other is Config) &&
|
||||
other.height == height &&
|
||||
other.viewOrderConfig == viewOrderConfig &&
|
||||
|
|
@ -143,7 +145,7 @@ class ViewOrderConfig {
|
|||
final EmojiPickerItem bottom;
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
bool operator ==(Object other) {
|
||||
return other is ViewOrderConfig &&
|
||||
other.top == top &&
|
||||
other.middle == middle &&
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@
|
|||
* Copyright (c) 2024 Stefan Humm
|
||||
*/
|
||||
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
|
||||
/// List of categories of emojis
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
// ignore_for_file: avoid_dynamic_calls, prefer_constructors_over_static_methods
|
||||
|
||||
/*
|
||||
* Modified version of https://github.com/Fintasys/emoji_picker_flutter
|
||||
* MIT License
|
||||
|
|
@ -39,9 +41,7 @@ class Emoji {
|
|||
return Emoji(
|
||||
json['emoji'] as String,
|
||||
json['name'] as String,
|
||||
hasSkinTone: json['hasSkinTone'] != null
|
||||
? json['hasSkinTone'] as bool
|
||||
: false,
|
||||
hasSkinTone: json['hasSkinTone'] != null && json['hasSkinTone'] as bool,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
* Copyright (c) 2024 Stefan Humm
|
||||
*/
|
||||
|
||||
export 'locales/emoji_set.dart';
|
||||
export 'bottom_action_bar.dart';
|
||||
export 'category_view/category.dart';
|
||||
export 'category_view/category_view.dart';
|
||||
|
|
@ -19,6 +18,7 @@ export 'emoji_text_editing_controller.dart';
|
|||
export 'emoji_view/default_emoji_picker_view.dart';
|
||||
export 'emoji_view/emoji_picker_view.dart';
|
||||
export 'emoji_view/emoji_view_config.dart';
|
||||
export 'locales/emoji_set.dart';
|
||||
export 'search_view.dart';
|
||||
export 'skin_tones/emoji_skin_tones.dart';
|
||||
export 'skin_tones/skin_tone_config.dart';
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
// ignore_for_file: comment_references
|
||||
|
||||
/*
|
||||
* Modified version of https://github.com/Fintasys/emoji_picker_flutter
|
||||
* MIT License
|
||||
* Copyright (c) 2024 Stefan Humm
|
||||
*/
|
||||
|
||||
import 'package:flutter/foundation.dart' hide Category;
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart'
|
||||
show Category;
|
||||
import 'package:flutter/foundation.dart' hide Category;
|
||||
|
||||
/// Controller for EmojiPicker widget that allows reading and changing
|
||||
/// the selected category programmatically.
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ import 'dart:convert';
|
|||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:flutter/foundation.dart' show visibleForTesting;
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
|
||||
/// Initial value for RecentEmoji
|
||||
const initVal = 1;
|
||||
|
|
@ -107,11 +107,11 @@ class EmojiPickerInternalUtils {
|
|||
|
||||
return Future(() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
var emojiJson = prefs.getString('recent');
|
||||
final emojiJson = prefs.getString('recent');
|
||||
if (emojiJson == null) {
|
||||
return _recentEmojis = [];
|
||||
}
|
||||
var json = jsonDecode(emojiJson) as List<dynamic>;
|
||||
final json = jsonDecode(emojiJson) as List<dynamic>;
|
||||
return _recentEmojis = json
|
||||
.map<RecentEmoji>(RecentEmoji.fromJson)
|
||||
.toList();
|
||||
|
|
@ -128,7 +128,7 @@ class EmojiPickerInternalUtils {
|
|||
emoji = removeSkinTone(emoji);
|
||||
}
|
||||
var recentEmoji = await getRecentEmojis();
|
||||
var recentEmojiIndex = recentEmoji.indexWhere(
|
||||
final recentEmojiIndex = recentEmoji.indexWhere(
|
||||
(element) => element.emoji.emoji == emoji.emoji,
|
||||
);
|
||||
if (recentEmojiIndex != -1) {
|
||||
|
|
@ -147,7 +147,7 @@ class EmojiPickerInternalUtils {
|
|||
|
||||
// save locally
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
prefs.setString('recent', jsonEncode(recentEmoji));
|
||||
unawaited(prefs.setString('recent', jsonEncode(recentEmoji)));
|
||||
|
||||
return _recentEmojis = recentEmoji;
|
||||
}
|
||||
|
|
@ -162,7 +162,7 @@ class EmojiPickerInternalUtils {
|
|||
emoji = removeSkinTone(emoji);
|
||||
}
|
||||
var recentEmoji = await getRecentEmojis();
|
||||
var recentEmojiIndex = recentEmoji.indexWhere(
|
||||
final recentEmojiIndex = recentEmoji.indexWhere(
|
||||
(element) => element.emoji.emoji == emoji.emoji,
|
||||
);
|
||||
if (recentEmojiIndex != -1) {
|
||||
|
|
@ -188,7 +188,7 @@ class EmojiPickerInternalUtils {
|
|||
|
||||
// save locally
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
prefs.setString('recent', jsonEncode(recentEmoji));
|
||||
unawaited(prefs.setString('recent', jsonEncode(recentEmoji)));
|
||||
|
||||
return _recentEmojis = recentEmoji;
|
||||
}
|
||||
|
|
@ -196,7 +196,7 @@ class EmojiPickerInternalUtils {
|
|||
/// Clears the list of recent emojis in local storage
|
||||
Future<void> clearRecentEmojisInLocalStorage() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
prefs.setString('recent', jsonEncode([]));
|
||||
unawaited(prefs.setString('recent', jsonEncode([])));
|
||||
_recentEmojis = [];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,13 +6,14 @@
|
|||
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker_internal_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Emoji Regex
|
||||
/// Keycap Sequence '((\u0023|\u002a|[\u0030-\u0039])\ufe0f\u20e3){1}'
|
||||
/// Issue: https://github.com/flutter/flutter/issues/36062
|
||||
// ignore: constant_identifier_names
|
||||
const EmojiRegex =
|
||||
r'((\u0023|\u002a|[\u0030-\u0039])\ufe0f\u20e3){1}|\p{Emoji}|\u200D|\uFE0F';
|
||||
|
||||
|
|
@ -56,7 +57,7 @@ class EmojiPickerUtils {
|
|||
: data;
|
||||
|
||||
// Set all the emoji entities
|
||||
for (var emojis in availableCategoryEmoji) {
|
||||
for (final emojis in availableCategoryEmoji) {
|
||||
_allAvailableEmojiEntities.addAll(emojis.emoji);
|
||||
}
|
||||
}
|
||||
|
|
@ -186,7 +187,7 @@ class EmojiPickerUtils {
|
|||
/// instead of an invalid double-modifier one (e.g. 👋🏻🏽).
|
||||
Emoji applySkinTone(Emoji emoji, String color) {
|
||||
final codeUnits = removeSkinTone(emoji).emoji.codeUnits;
|
||||
var result = List<int>.empty(growable: true)
|
||||
final result = List<int>.empty(growable: true)
|
||||
// Basic emoji without gender (until char 2)
|
||||
..addAll(codeUnits.sublist(0, min(codeUnits.length, 2)))
|
||||
// Skin tone
|
||||
|
|
@ -246,9 +247,9 @@ class EmojiPickerUtils {
|
|||
Future<void> clearRecentEmojis({
|
||||
required GlobalKey<EmojiPickerState> key,
|
||||
}) async {
|
||||
return await EmojiPickerInternalUtils()
|
||||
.clearRecentEmojisInLocalStorage()
|
||||
.then((_) => key.currentState?.updateRecentEmoji([], refresh: true));
|
||||
return EmojiPickerInternalUtils().clearRecentEmojisInLocalStorage().then(
|
||||
(_) => key.currentState?.updateRecentEmoji([], refresh: true),
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns the emoji regex
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
// ignore_for_file: constant_identifier_names
|
||||
|
||||
/*
|
||||
* Modified version of https://github.com/Fintasys/emoji_picker_flutter
|
||||
* MIT License
|
||||
|
|
@ -6,17 +8,17 @@
|
|||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:twonly/src/visual/components/emoji_picker/locales/default_emoji_set_locale.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/category_view/category.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/config.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker_controller.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker_internal_utils.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_view/default_emoji_picker_view.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_view/emoji_view_config.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_view/emoji_picker_view.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_view/emoji_view_config.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/locales/default_emoji_set_locale.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/search_view.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// All the possible categories that [Emoji] can be put into
|
||||
///
|
||||
|
|
@ -342,7 +344,7 @@ class EmojiPickerState extends State<EmojiPicker> {
|
|||
if (cursorPosition >= 0) {
|
||||
final selection = controller.value.selection;
|
||||
final newTextBeforeCursor = _deleteWordByWord(
|
||||
selection.textBefore(text).toString(),
|
||||
selection.textBefore(text),
|
||||
);
|
||||
controller.value = controller.value.copyWith(
|
||||
text: newTextBeforeCursor + selection.textAfter(text),
|
||||
|
|
@ -558,8 +560,7 @@ class EmojiPickerState extends State<EmojiPicker> {
|
|||
final maximumHeight = _maximumPickerHeight(initialHeight);
|
||||
final nextHeight =
|
||||
((_currentPickerHeight ?? initialHeight) - details.delta.dy)
|
||||
.clamp(initialHeight, maximumHeight)
|
||||
.toDouble();
|
||||
.clamp(initialHeight, maximumHeight);
|
||||
if (nextHeight != _currentPickerHeight) {
|
||||
setState(() => _currentPickerHeight = nextHeight);
|
||||
}
|
||||
|
|
@ -596,12 +597,10 @@ class EmojiPickerState extends State<EmojiPicker> {
|
|||
final resizeConfig = widget.config.resizeConfig;
|
||||
final configuredMaximum =
|
||||
resizeConfig.maxHeight ?? safeHeight * resizeConfig.maxHeightFactor;
|
||||
return configuredMaximum
|
||||
.clamp(
|
||||
initialHeight,
|
||||
safeHeight < initialHeight ? initialHeight : safeHeight,
|
||||
)
|
||||
.toDouble();
|
||||
return configuredMaximum.clamp(
|
||||
initialHeight,
|
||||
safeHeight < initialHeight ? initialHeight : safeHeight,
|
||||
);
|
||||
}
|
||||
|
||||
void _showSearchView() {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
// ignore_for_file: constant_identifier_names, prefer_asserts_with_message
|
||||
|
||||
/*
|
||||
* Modified version of https://github.com/Fintasys/emoji_picker_flutter
|
||||
* MIT License
|
||||
* Copyright (c) 2024 Stefan Humm
|
||||
*/
|
||||
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
|
||||
/// Default delimiter for regex
|
||||
const delimiter = '|';
|
||||
|
|
@ -14,7 +16,7 @@ const delimiter = '|';
|
|||
/// a particular style to emoji characters.
|
||||
class EmojiTextEditingController extends TextEditingController {
|
||||
/// Constructor, requres emojiStyle, since otherwise this class has no effect
|
||||
EmojiTextEditingController({super.text, required this.emojiTextStyle});
|
||||
EmojiTextEditingController({required this.emojiTextStyle, super.text});
|
||||
|
||||
/// The style used for the emoji characters
|
||||
final TextStyle emojiTextStyle;
|
||||
|
|
@ -25,8 +27,8 @@ class EmojiTextEditingController extends TextEditingController {
|
|||
@override
|
||||
TextSpan buildTextSpan({
|
||||
required BuildContext context,
|
||||
TextStyle? style,
|
||||
required bool withComposing,
|
||||
TextStyle? style,
|
||||
}) {
|
||||
assert(
|
||||
!value.composing.isValid || !withComposing || value.isComposingRangeValid,
|
||||
|
|
@ -83,7 +85,6 @@ class EmojiTextEditingController extends TextEditingController {
|
|||
|
||||
/// Emoji text style providing commonly available fallback fonts.
|
||||
const DefaultEmojiTextStyle = TextStyle(
|
||||
inherit: true,
|
||||
fontFamilyFallback: [
|
||||
'Apple Color Emoji',
|
||||
'Noto Color Emoji',
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
* Copyright (c) 2024 Stefan Humm
|
||||
*/
|
||||
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
|
||||
/// Default EmojiPicker Implementation
|
||||
class DefaultEmojiPickerView extends EmojiPickerView {
|
||||
|
|
@ -254,7 +254,6 @@ class _DefaultEmojiPickerViewState extends State<DefaultEmojiPickerView>
|
|||
),
|
||||
sliver: SliverGrid.builder(
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
childAspectRatio: 1,
|
||||
crossAxisCount: viewConfig.columns,
|
||||
mainAxisSpacing: viewConfig.verticalSpacing,
|
||||
crossAxisSpacing: viewConfig.horizontalSpacing,
|
||||
|
|
|
|||
|
|
@ -32,11 +32,11 @@ abstract class EmojiPickerView extends StatefulWidget {
|
|||
class EmojiContainer extends StatelessWidget {
|
||||
/// Constructor.
|
||||
const EmojiContainer({
|
||||
super.key,
|
||||
required this.color,
|
||||
required this.buttonMode,
|
||||
this.padding,
|
||||
required this.child,
|
||||
super.key,
|
||||
this.padding,
|
||||
});
|
||||
|
||||
final Color color;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
// ignore_for_file: avoid_equals_and_hash_code_on_mutable_classes, constant_identifier_names
|
||||
|
||||
/*
|
||||
* Modified version of https://github.com/Fintasys/emoji_picker_flutter
|
||||
* MIT License
|
||||
|
|
@ -6,8 +8,8 @@
|
|||
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
|
||||
/// Callback function for custom view
|
||||
typedef EmojiViewBuilder =
|
||||
|
|
@ -40,6 +42,7 @@ class EmojiViewConfig {
|
|||
this.noRecents = DefaultNoRecentsWidget,
|
||||
this.loadingIndicator = const SizedBox.shrink(),
|
||||
this.buttonMode = ButtonMode.MATERIAL,
|
||||
// ignore: prefer_asserts_with_message
|
||||
}) : assert(categorySpacing >= 0);
|
||||
|
||||
/// Number of emojis per row
|
||||
|
|
@ -95,7 +98,7 @@ class EmojiViewConfig {
|
|||
}
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
bool operator ==(Object other) {
|
||||
return (other is EmojiViewConfig) &&
|
||||
other.columns == columns &&
|
||||
other.emojiSizeMax == emojiSizeMax &&
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
* Copyright (c) 2024 Stefan Humm
|
||||
*/
|
||||
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
|
||||
/// Default method for locale selection
|
||||
List<CategoryEmoji> getDefaultEmojiLocale(Locale locale) {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
// ignore_for_file: avoid_equals_and_hash_code_on_mutable_classes
|
||||
|
||||
/*
|
||||
* Modified version of https://github.com/Fintasys/emoji_picker_flutter
|
||||
* MIT License
|
||||
* Copyright (c) 2024 Stefan Humm
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker_internal_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Template class for custom implementation
|
||||
/// Inhert this class to create your own search view
|
||||
|
|
@ -138,7 +140,7 @@ class SearchViewState<T extends SearchView> extends State<T>
|
|||
emojiBoxPosition,
|
||||
emoji,
|
||||
emojiSize,
|
||||
null, // Todo: check if we can provide the category
|
||||
null,
|
||||
widget.config,
|
||||
_onSkinTonedEmojiSelected,
|
||||
links[emoji.emoji]!,
|
||||
|
|
@ -205,7 +207,7 @@ class SearchViewConfig {
|
|||
final SearchViewBuilder? customSearchView;
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
bool operator ==(Object other) {
|
||||
return other is SearchViewConfig &&
|
||||
other.backgroundColor == backgroundColor &&
|
||||
other.buttonIconColor == buttonIconColor &&
|
||||
|
|
@ -251,7 +253,7 @@ class DefaultSearchViewState extends SearchViewState<DefaultSearchView> {
|
|||
constraints.maxWidth,
|
||||
);
|
||||
|
||||
return Container(
|
||||
return ColoredBox(
|
||||
color: widget.config.searchViewConfig.backgroundColor,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
|
|
|
|||
|
|
@ -24,5 +24,11 @@ class SkinTone {
|
|||
static const String dark = '🏿';
|
||||
|
||||
/// Return all values as Array
|
||||
static const values = [light, mediumLight, medium, mediumDark, dark];
|
||||
static const List<String> values = [
|
||||
light,
|
||||
mediumLight,
|
||||
medium,
|
||||
mediumDark,
|
||||
dark,
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
// ignore_for_file: avoid_equals_and_hash_code_on_mutable_classes
|
||||
|
||||
/*
|
||||
* Modified version of https://github.com/Fintasys/emoji_picker_flutter
|
||||
* MIT License
|
||||
|
|
@ -37,7 +39,7 @@ class SkinToneConfig {
|
|||
final bool rememberSkinTone;
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
bool operator ==(Object other) {
|
||||
return (other is SkinToneConfig) &&
|
||||
other.enabled == enabled &&
|
||||
other.dialogBackgroundColor == dialogBackgroundColor &&
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
|
||||
/// Skin tone overlay mixin
|
||||
mixin SkinToneOverlayStateMixin<T extends StatefulWidget> on State<T> {
|
||||
|
|
@ -52,7 +52,7 @@ mixin SkinToneOverlayStateMixin<T extends StatefulWidget> on State<T> {
|
|||
.toList();
|
||||
|
||||
final screenWidth = MediaQuery.of(context).size.width;
|
||||
final emojiPickerRenderbox = context.findRenderObject() as RenderBox;
|
||||
final emojiPickerRenderbox = context.findRenderObject()! as RenderBox;
|
||||
final emojiBoxSize = config.emojiViewConfig.getEmojiBoxSize(
|
||||
emojiPickerRenderbox.size.width,
|
||||
);
|
||||
|
|
@ -74,9 +74,9 @@ mixin SkinToneOverlayStateMixin<T extends StatefulWidget> on State<T> {
|
|||
child: TapRegion(
|
||||
onTapOutside: (_) => closeSkinToneOverlay(),
|
||||
child: Material(
|
||||
elevation: 4.0,
|
||||
elevation: 4,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
color: config.skinToneConfig.dialogBackgroundColor,
|
||||
child: Row(
|
||||
children: [
|
||||
|
|
@ -120,7 +120,7 @@ mixin SkinToneOverlayStateMixin<T extends StatefulWidget> on State<T> {
|
|||
}
|
||||
|
||||
double _calculateTopOffset(double emojiBoxSize) {
|
||||
final verticalPaddingOverlay = 8.0;
|
||||
const verticalPaddingOverlay = 8.0;
|
||||
final top = -emojiBoxSize - verticalPaddingOverlay;
|
||||
return top;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class _TriangleShapePainter extends BoxPainter {
|
|||
// per documentation, the size should be always not null here, no need
|
||||
// for null checks
|
||||
final s = configuration.size!;
|
||||
var path = Path()
|
||||
final path = Path()
|
||||
..moveTo(s.width + offset.dx, s.height - _size + offset.dy)
|
||||
..lineTo(s.width - _size + offset.dx, s.height + offset.dy)
|
||||
..lineTo(s.width + offset.dx, s.height + offset.dy)
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
|
||||
/// Backspace Button Widget
|
||||
class BackspaceButton extends StatefulWidget {
|
||||
|
|
@ -72,7 +72,7 @@ class _BackspaceButtonState extends State<BackspaceButton> {
|
|||
var millisecondsSincePressed = 0;
|
||||
|
||||
// Callback function executed on each timer tick
|
||||
void _callback(Timer timer) {
|
||||
void callback(Timer timer) {
|
||||
// Accumulate elapsed time since the last tick
|
||||
millisecondsSincePressed += callbackInterval.inMilliseconds;
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ class _BackspaceButtonState extends State<BackspaceButton> {
|
|||
_onBackspacePressedCallbackTimer?.cancel();
|
||||
_onBackspacePressedCallbackTimer = Timer.periodic(
|
||||
callbackInterval,
|
||||
_callback,
|
||||
callback,
|
||||
);
|
||||
|
||||
// Reset the elapsed time for the new interval
|
||||
|
|
@ -105,7 +105,7 @@ class _BackspaceButtonState extends State<BackspaceButton> {
|
|||
// Start the initial timer with the short-press interval
|
||||
_onBackspacePressedCallbackTimer = Timer.periodic(
|
||||
callbackInterval,
|
||||
_callback,
|
||||
callback,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
* Copyright (c) 2024 Stefan Humm
|
||||
*/
|
||||
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
|
||||
/// A widget that represents an individual clickable emoji cell.
|
||||
/// Can have a long pressed listener [onSkinToneDialogRequested] that
|
||||
|
|
@ -14,30 +14,30 @@ import 'package:flutter/material.dart';
|
|||
class EmojiCell extends StatelessWidget {
|
||||
/// Constructor for manually setting all properties
|
||||
const EmojiCell({
|
||||
super.key,
|
||||
required this.emoji,
|
||||
required this.emojiSize,
|
||||
required this.emojiBoxSize,
|
||||
this.categoryEmoji,
|
||||
required this.buttonMode,
|
||||
required this.enableSkinTones,
|
||||
required this.textStyle,
|
||||
required this.skinToneIndicatorColor,
|
||||
this.onSkinToneDialogRequested,
|
||||
required this.onEmojiSelected,
|
||||
super.key,
|
||||
this.categoryEmoji,
|
||||
this.onSkinToneDialogRequested,
|
||||
});
|
||||
|
||||
/// Constructor that can retrieve as much information as possible from
|
||||
/// [Config]
|
||||
EmojiCell.fromConfig({
|
||||
super.key,
|
||||
required this.emoji,
|
||||
required this.emojiSize,
|
||||
required this.emojiBoxSize,
|
||||
this.categoryEmoji,
|
||||
required this.onEmojiSelected,
|
||||
this.onSkinToneDialogRequested,
|
||||
required Config config,
|
||||
super.key,
|
||||
this.categoryEmoji,
|
||||
this.onSkinToneDialogRequested,
|
||||
}) : buttonMode = config.emojiViewConfig.buttonMode,
|
||||
enableSkinTones = config.skinToneConfig.enabled,
|
||||
textStyle = config.emojiTextStyle,
|
||||
|
|
@ -77,12 +77,12 @@ class EmojiCell extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
onPressed() {
|
||||
void onPressed() {
|
||||
onEmojiSelected(categoryEmoji?.category, emoji);
|
||||
}
|
||||
|
||||
onLongPressed() {
|
||||
final renderBox = context.findRenderObject() as RenderBox;
|
||||
void onLongPressed() {
|
||||
final renderBox = context.findRenderObject()! as RenderBox;
|
||||
final emojiBoxPosition = renderBox.localToGlobal(Offset.zero);
|
||||
onSkinToneDialogRequested?.call(
|
||||
emojiBoxPosition,
|
||||
|
|
@ -106,8 +106,8 @@ class EmojiCell extends StatelessWidget {
|
|||
/// Build different Button based on ButtonMode
|
||||
Widget _buildButtonWidget({
|
||||
required VoidCallback onPressed,
|
||||
VoidCallback? onLongPressed,
|
||||
required Widget child,
|
||||
VoidCallback? onLongPressed,
|
||||
}) {
|
||||
if (buttonMode == ButtonMode.MATERIAL) {
|
||||
return MaterialButton(
|
||||
|
|
@ -116,7 +116,7 @@ class EmojiCell extends StatelessWidget {
|
|||
elevation: 0,
|
||||
highlightElevation: 0,
|
||||
padding: EdgeInsets.zero,
|
||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero),
|
||||
shape: const RoundedRectangleBorder(),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
|
@ -126,7 +126,6 @@ class EmojiCell extends StatelessWidget {
|
|||
child: CupertinoButton(
|
||||
onPressed: onPressed,
|
||||
padding: EdgeInsets.zero,
|
||||
alignment: Alignment.center,
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
|
|
@ -142,7 +141,7 @@ class EmojiCell extends StatelessWidget {
|
|||
Widget _buildEmoji() {
|
||||
final emojiText = Text(
|
||||
emoji.emoji,
|
||||
textScaler: const TextScaler.linear(1.0),
|
||||
textScaler: TextScaler.noScaling,
|
||||
style: _getEmojiTextStyle(),
|
||||
);
|
||||
|
||||
|
|
@ -152,7 +151,7 @@ class EmojiCell extends StatelessWidget {
|
|||
? Container(
|
||||
decoration: TriangleDecoration(
|
||||
color: skinToneIndicatorColor,
|
||||
size: 8.0,
|
||||
size: 8,
|
||||
),
|
||||
child: emojiText,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -143,7 +143,6 @@ class _StartNewChatView extends State<StartNewChatView> {
|
|||
padding: const EdgeInsets.only(
|
||||
bottom: 40,
|
||||
left: 10,
|
||||
top: 0,
|
||||
right: 10,
|
||||
),
|
||||
child: Column(
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use crate::error::{Result, TwonlyError};
|
|||
pub(crate) struct GroupRecord {
|
||||
pub group_id: String,
|
||||
pub group_name: String,
|
||||
#[allow(dead_code)]
|
||||
pub state_version_id: i64,
|
||||
pub state_encryption_key: Option<Vec<u8>>,
|
||||
pub my_group_private_key: Option<Vec<u8>>,
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
* Copyright (c) 2024 Stefan Humm
|
||||
*/
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker_internal_utils.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
skinToneTests();
|
||||
|
|
@ -100,7 +100,7 @@ void skinToneTests() {
|
|||
utils
|
||||
.applyDisplaySkinTone(
|
||||
toneable,
|
||||
const SkinToneConfig(rememberSkinTone: false),
|
||||
const SkinToneConfig(),
|
||||
SkinTone.medium,
|
||||
)
|
||||
.emoji,
|
||||
|
|
@ -123,7 +123,7 @@ void skinToneTests() {
|
|||
|
||||
void emojiModelTests() {
|
||||
test('encode Emoji', () {
|
||||
final encode = const Emoji('🤣', 'name');
|
||||
const encode = Emoji('🤣', 'name');
|
||||
expect(encode.toJson(), <String, dynamic>{
|
||||
'emoji': '🤣',
|
||||
'name': 'name',
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@
|
|||
* Copyright (c) 2024 Stefan Humm
|
||||
*/
|
||||
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker_internal_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker_internal_utils.dart';
|
||||
|
||||
// Use for golden tests, helpful in debugging
|
||||
// await expectLater(
|
||||
|
|
@ -21,24 +21,23 @@ void main() {
|
|||
setUp(EmojiPickerInternalUtils.resetCaches);
|
||||
|
||||
testWidgets('Should allow user to select an emoji', (
|
||||
WidgetTester tester,
|
||||
tester,
|
||||
) async {
|
||||
final _controller = TextEditingController();
|
||||
Emoji? _emojiSelected;
|
||||
Category? _categorySelected;
|
||||
final controller0 = TextEditingController();
|
||||
Emoji? emojiSelected;
|
||||
Category? categorySelected;
|
||||
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
body: EmojiPicker(
|
||||
textEditingController: _controller,
|
||||
textEditingController: controller0,
|
||||
onEmojiSelected: (category, emoji) {
|
||||
_emojiSelected = emoji;
|
||||
_categorySelected = category;
|
||||
emojiSelected = emoji;
|
||||
categorySelected = category;
|
||||
},
|
||||
config: const Config(
|
||||
height: 256,
|
||||
categoryViewConfig: CategoryViewConfig(
|
||||
recentTabBehavior: RecentTabBehavior.NONE,
|
||||
),
|
||||
|
|
@ -64,20 +63,20 @@ void main() {
|
|||
await tester.pumpAndSettle();
|
||||
|
||||
// Check if the emoji is added to the text controller
|
||||
expect(_controller.text, contains('🙂'));
|
||||
expect(controller0.text, contains('🙂'));
|
||||
|
||||
// Check if the emoji been passed to the 'onEmojiSelected' callback
|
||||
expect(
|
||||
_emojiSelected,
|
||||
emojiSelected,
|
||||
equals(const Emoji('🙂', 'face | happy | slightly | smile | smiling')),
|
||||
);
|
||||
|
||||
// Check if the category been passed to the 'onEmojiSelected' callback
|
||||
expect(_categorySelected, equals(Category.SMILEYS));
|
||||
expect(categorySelected, equals(Category.SMILEYS));
|
||||
});
|
||||
|
||||
testWidgets('Shows the redesigned header and one continuous emoji list', (
|
||||
WidgetTester tester,
|
||||
tester,
|
||||
) async {
|
||||
var stickerPressed = false;
|
||||
final controller = EmojiPickerController(
|
||||
|
|
@ -137,7 +136,7 @@ void main() {
|
|||
});
|
||||
|
||||
testWidgets('Drag handle grows picker from its configured height', (
|
||||
WidgetTester tester,
|
||||
tester,
|
||||
) async {
|
||||
var showing = true;
|
||||
late StateSetter setHarnessState;
|
||||
|
|
@ -158,7 +157,6 @@ void main() {
|
|||
child: EmojiPicker(
|
||||
controller: pickerController,
|
||||
config: const Config(
|
||||
height: 256,
|
||||
resizeConfig: ResizeConfig(maxHeight: 420),
|
||||
emojiViewConfig: EmojiViewConfig(
|
||||
backgroundColor: pickerColor,
|
||||
|
|
@ -192,7 +190,7 @@ void main() {
|
|||
final dragIndicator = tester.widget<Container>(
|
||||
find.byKey(const Key('emojiPickerDragIndicator')),
|
||||
);
|
||||
final dragDecoration = dragIndicator.decoration as BoxDecoration;
|
||||
final dragDecoration = dragIndicator.decoration! as BoxDecoration;
|
||||
expect(dragDecoration.color, ThemeData.dark().colorScheme.outline);
|
||||
expect(dragDecoration.borderRadius, BorderRadius.circular(32));
|
||||
|
||||
|
|
@ -212,13 +210,12 @@ void main() {
|
|||
expect(tester.getSize(picker).height, 256);
|
||||
});
|
||||
|
||||
testWidgets('Drag handle can be hidden', (WidgetTester tester) async {
|
||||
testWidgets('Drag handle can be hidden', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
const MaterialApp(
|
||||
home: Scaffold(
|
||||
body: EmojiPicker(
|
||||
config: Config(
|
||||
height: 256,
|
||||
resizeConfig: ResizeConfig(showDragHandle: false),
|
||||
categoryViewConfig: CategoryViewConfig(
|
||||
recentTabBehavior: RecentTabBehavior.NONE,
|
||||
|
|
@ -240,25 +237,25 @@ void main() {
|
|||
});
|
||||
|
||||
testWidgets('Should allow to select an emoji with skintone on longPress', (
|
||||
WidgetTester tester,
|
||||
tester,
|
||||
) async {
|
||||
final _controller = TextEditingController();
|
||||
final _utils = EmojiPickerUtils();
|
||||
final emoji = const Emoji('👍', 'Thumbs Up', hasSkinTone: true);
|
||||
Emoji? _emojiSelected;
|
||||
Category? _categorySelected;
|
||||
final controller0 = TextEditingController();
|
||||
final utils = EmojiPickerUtils();
|
||||
const emoji = Emoji('👍', 'Thumbs Up', hasSkinTone: true);
|
||||
Emoji? emojiSelected;
|
||||
Category? categorySelected;
|
||||
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Scaffold(
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.only(top: 64.0),
|
||||
padding: const EdgeInsets.only(top: 64),
|
||||
child: EmojiPicker(
|
||||
textEditingController: _controller,
|
||||
textEditingController: controller0,
|
||||
onEmojiSelected: (category, emoji) {
|
||||
_emojiSelected = emoji;
|
||||
_categorySelected = category;
|
||||
emojiSelected = emoji;
|
||||
categorySelected = category;
|
||||
},
|
||||
config: const Config(
|
||||
height: 500,
|
||||
|
|
@ -298,7 +295,7 @@ void main() {
|
|||
Finder? skinToneVariantToFind;
|
||||
for (var i = 0; i < SkinTone.values.length; i++) {
|
||||
skinToneVariantToFind = find.text(
|
||||
_utils.applySkinTone(emoji, SkinTone.values[i]).emoji,
|
||||
utils.applySkinTone(emoji, SkinTone.values[i]).emoji,
|
||||
);
|
||||
// Verify if we can find the skintone variant
|
||||
expect(skinToneVariantToFind, findsOneWidget);
|
||||
|
|
@ -308,24 +305,24 @@ void main() {
|
|||
await tester.tap(skinToneVariantToFind!);
|
||||
|
||||
// Check if the emoji is added to the text controller
|
||||
expect(_controller.text, contains('👍🏿'));
|
||||
expect(controller0.text, contains('👍🏿'));
|
||||
|
||||
// Check if the emoji been passed to the 'onEmojiSelected' callback
|
||||
expect(_emojiSelected?.emoji, equals('👍🏿'));
|
||||
expect(emojiSelected?.emoji, equals('👍🏿'));
|
||||
expect(
|
||||
_emojiSelected?.name,
|
||||
emojiSelected?.name,
|
||||
equals('+1 | good | hand | like | thumb | up | yes'),
|
||||
);
|
||||
expect(_emojiSelected?.hasSkinTone, equals(true));
|
||||
expect(emojiSelected?.hasSkinTone, equals(true));
|
||||
|
||||
// Check if the category been passed to the 'onEmojiSelected' callback
|
||||
expect(_categorySelected, equals(Category.SMILEYS));
|
||||
expect(categorySelected, equals(Category.SMILEYS));
|
||||
});
|
||||
|
||||
testWidgets('Clips overflow when constrained tighter than natural height', (
|
||||
WidgetTester tester,
|
||||
tester,
|
||||
) async {
|
||||
final _controller = TextEditingController();
|
||||
final controller0 = TextEditingController();
|
||||
|
||||
// Constrain the picker far below the natural sum of the category bar
|
||||
// and bottom action bar to force the inner Column to overflow (#256).
|
||||
|
|
@ -337,7 +334,7 @@ void main() {
|
|||
width: 300,
|
||||
height: 30,
|
||||
child: EmojiPicker(
|
||||
textEditingController: _controller,
|
||||
textEditingController: controller0,
|
||||
config: const Config(
|
||||
height: 30,
|
||||
categoryViewConfig: CategoryViewConfig(
|
||||
|
|
|
|||
|
|
@ -4,18 +4,18 @@
|
|||
* Copyright (c) 2024 Stefan Humm
|
||||
*/
|
||||
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
|
||||
void main() {
|
||||
group('EmojiTextEditingController', () {
|
||||
testWidgets('should apply emojiTextStyle to emojis', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
Builder(
|
||||
builder: (BuildContext context) {
|
||||
final emojiStyle = const TextStyle(color: Colors.red);
|
||||
final regularStyle = const TextStyle(color: Colors.black);
|
||||
builder: (context) {
|
||||
const emojiStyle = TextStyle(color: Colors.red);
|
||||
const regularStyle = TextStyle(color: Colors.black);
|
||||
final controller = EmojiTextEditingController(
|
||||
text: 'Hello 👋 World',
|
||||
emojiTextStyle: emojiStyle,
|
||||
|
|
|
|||
|
|
@ -4,17 +4,17 @@
|
|||
* Copyright (c) 2024 Stefan Humm
|
||||
*/
|
||||
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
|
||||
void main() {
|
||||
group('EmojiTextStyle', () {
|
||||
testWidgets('should apply EmojiTextStyle to emoji in text', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
Builder(
|
||||
builder: (BuildContext context) {
|
||||
final text = 'Hello 👋 World';
|
||||
builder: (context) {
|
||||
const text = 'Hello 👋 World';
|
||||
final result = EmojiPickerUtils().setEmojiTextStyle(
|
||||
text,
|
||||
emojiStyle: const TextStyle(color: Colors.red),
|
||||
|
|
|
|||
|
|
@ -4,19 +4,19 @@
|
|||
* Copyright (c) 2024 Stefan Humm
|
||||
*/
|
||||
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker_internal_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker.dart';
|
||||
import 'package:twonly/src/visual/components/emoji_picker/emoji_picker_internal_utils.dart';
|
||||
|
||||
/// Test harness that lets us trigger a rebuild of [EmojiPicker] from its
|
||||
/// parent, mimicking an unrelated `setState()` higher up in the widget tree.
|
||||
class _RebuildHarness extends StatefulWidget {
|
||||
const _RebuildHarness({
|
||||
super.key,
|
||||
required this.pickerKey,
|
||||
required this.config,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final GlobalKey<EmojiPickerState> pickerKey;
|
||||
|
|
@ -59,10 +59,6 @@ void main() {
|
|||
|
||||
const config = Config(
|
||||
height: 400,
|
||||
categoryViewConfig: CategoryViewConfig(
|
||||
initCategory: Category.RECENT,
|
||||
recentTabBehavior: RecentTabBehavior.RECENT,
|
||||
),
|
||||
);
|
||||
|
||||
// Deliberately not part of the built-in set. In the continuous picker a
|
||||
|
|
|
|||
Loading…
Reference in a new issue