fix flutter issues

This commit is contained in:
otsmr 2026-10-05 22:54:46 +02:00
parent ced68167d1
commit 76a9455c7c
30 changed files with 149 additions and 138 deletions

View file

@ -1,3 +1,5 @@
// ignore_for_file: constant_identifier_names
/*
* Modified version of https://github.com/Fintasys/emoji_picker_flutter
* MIT License

View file

@ -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: [

View file

@ -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 &&

View file

@ -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 &&

View file

@ -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

View file

@ -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,
);
}

View file

@ -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';

View file

@ -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.

View file

@ -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 = [];
}

View file

@ -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

View file

@ -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(
return configuredMaximum.clamp(
initialHeight,
safeHeight < initialHeight ? initialHeight : safeHeight,
)
.toDouble();
);
}
void _showSearchView() {

View file

@ -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',

View file

@ -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,

View file

@ -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;

View file

@ -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 &&

View file

@ -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) {

View file

@ -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,

View file

@ -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,
];
}

View file

@ -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 &&

View file

@ -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;
}

View file

@ -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)

View file

@ -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,
);
}

View file

@ -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,
)

View file

@ -143,7 +143,6 @@ class _StartNewChatView extends State<StartNewChatView> {
padding: const EdgeInsets.only(
bottom: 40,
left: 10,
top: 0,
right: 10,
),
child: Column(

View file

@ -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>>,

View file

@ -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',

View file

@ -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(

View file

@ -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,

View file

@ -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),

View file

@ -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