From 0abd6f82f2f0ff4d696b1bc9ddcd1a6a63faace6 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Sun, 13 Nov 2022 11:57:47 +0100 Subject: [PATCH] fix: Remove emoji picker workaround --- lib/pages/chat/chat_emoji_picker.dart | 2 - lib/utils/fluffy_emoji_picker.dart | 398 -------------------------- 2 files changed, 400 deletions(-) delete mode 100644 lib/utils/fluffy_emoji_picker.dart diff --git a/lib/pages/chat/chat_emoji_picker.dart b/lib/pages/chat/chat_emoji_picker.dart index aeabf1fad..069c4fc12 100644 --- a/lib/pages/chat/chat_emoji_picker.dart +++ b/lib/pages/chat/chat_emoji_picker.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:emoji_picker_flutter/emoji_picker_flutter.dart'; -import 'package:fluffychat/utils/fluffy_emoji_picker.dart'; import 'chat.dart'; class ChatEmojiPicker extends StatelessWidget { @@ -20,7 +19,6 @@ class ChatEmojiPicker extends StatelessWidget { ? EmojiPicker( onEmojiSelected: controller.onEmojiSelected, onBackspacePressed: controller.emojiPickerBackspace, - customWidget: (c, s) => FluffyEmojiPickerView(c, s), ) : null, ); diff --git a/lib/utils/fluffy_emoji_picker.dart b/lib/utils/fluffy_emoji_picker.dart deleted file mode 100644 index fd767b72b..000000000 --- a/lib/utils/fluffy_emoji_picker.dart +++ /dev/null @@ -1,398 +0,0 @@ -// ignore_for_file: prefer_function_declarations_over_variables, implementation_imports - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -import 'package:emoji_picker_flutter/emoji_picker_flutter.dart'; -import 'package:emoji_picker_flutter/src/category_emoji.dart'; -import 'package:emoji_picker_flutter/src/emoji_picker_internal_utils.dart'; -import 'package:emoji_picker_flutter/src/emoji_skin_tones.dart'; -import 'package:emoji_picker_flutter/src/emoji_view_state.dart'; -import 'package:emoji_picker_flutter/src/triangle_shape.dart'; -import 'package:emojis/emoji.dart' as emoji; -import 'package:matrix/matrix.dart'; - -import 'package:fluffychat/widgets/matrix.dart'; - -/// Default EmojiPicker Implementation - adjusted for FluffyChat -/// -/// Copied and adjusted from: [DefaultEmojiPickerView] -class FluffyEmojiPickerView extends EmojiPickerBuilder { - /// Constructor - FluffyEmojiPickerView(Config config, EmojiViewState state) - : super(config, state); - - @override - DefaultEmojiPickerViewState createState() => DefaultEmojiPickerViewState(); -} - -class DefaultEmojiPickerViewState extends State - with SingleTickerProviderStateMixin { - PageController? _pageController; - TabController? _tabController; - OverlayEntry? _overlay; - late final _scrollController = ScrollController(); - late final _utils = EmojiPickerInternalUtils(); - final int _skinToneCount = 6; - final double tabBarHeight = 46; - - @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) - ..addListener(_closeSkinToneDialog); - _scrollController.addListener(_closeSkinToneDialog); - super.initState(); - } - - @override - void dispose() { - _closeSkinToneDialog(); - super.dispose(); - } - - void _closeSkinToneDialog() { - _overlay?.remove(); - _overlay = null; - } - - void _openSkinToneDialog( - Emoji emoji, - double emojiSize, - CategoryEmoji categoryEmoji, - int index, - ) { - _overlay = _buildSkinToneOverlay( - emoji, - emojiSize, - categoryEmoji, - index, - ); - Overlay.of(context)?.insert(_overlay!); - } - - 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(); - } - - @override - Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - final emojiSize = widget.config.getEmojiSize(constraints.maxWidth); - - return Container( - color: widget.config.bgColor, - child: Column( - children: [ - Row( - children: [ - Expanded( - child: SizedBox( - height: tabBarHeight, - child: TabBar( - labelColor: widget.config.iconColorSelected, - indicatorColor: widget.config.indicatorColor, - unselectedLabelColor: widget.config.iconColor, - controller: _tabController, - labelPadding: EdgeInsets.zero, - onTap: (index) { - _closeSkinToneDialog(); - _pageController!.jumpToPage(index); - }, - tabs: widget.state.categoryEmoji - .asMap() - .entries - .map((item) => - _buildCategory(item.key, item.value.category)) - .toList(), - ), - ), - ), - _buildBackspaceButton(), - ], - ), - Flexible( - child: PageView.builder( - itemCount: widget.state.categoryEmoji.length, - controller: _pageController, - onPageChanged: (index) { - _tabController!.animateTo( - index, - duration: widget.config.tabIndicatorAnimDuration, - ); - }, - itemBuilder: (context, index) => - _buildPage(emojiSize, widget.state.categoryEmoji[index]), - ), - ), - ], - ), - ); - }, - ); - } - - Widget _buildCategory(int index, Category category) { - return Tab( - icon: Icon( - widget.config.getIconForCategory(category), - ), - ); - } - - Widget _buildPage(double emojiSize, CategoryEmoji categoryEmoji) { - final matrix = Matrix.of(context); - - // Display notice if recent has no entries yet - if (categoryEmoji.category == Category.RECENT) { - final recent = matrix.client.recentEmojis; - final sorted = recent.keys.toList() - ..sort((a, b) => recent[b]!.compareTo(recent[a]!)); - categoryEmoji.emoji = sorted - .map((char) => Emoji(emoji.Emoji.byChar(char)?.name ?? '', char)) - .toList(); - if (categoryEmoji.emoji.isEmpty) { - return _buildNoRecent(); - } - } - // Build page normally - return GestureDetector( - onTap: _closeSkinToneDialog, - child: GridView.count( - scrollDirection: Axis.vertical, - physics: const ScrollPhysics(), - controller: _scrollController, - shrinkWrap: true, - primary: false, - padding: const EdgeInsets.all(0), - crossAxisCount: widget.config.columns, - mainAxisSpacing: widget.config.verticalSpacing, - crossAxisSpacing: widget.config.horizontalSpacing, - children: categoryEmoji.emoji.asMap().entries.map((item) { - final index = item.key; - final emoji = item.value; - final onPressed = () { - _closeSkinToneDialog(); - matrix.client.addRecentEmoji(emoji.emoji); - widget.state.onEmojiSelected(categoryEmoji.category, emoji); - }; - - final onLongPressed = () { - if (!emoji.hasSkinTone || !widget.config.enableSkinTones) { - _closeSkinToneDialog(); - return; - } - _closeSkinToneDialog(); - _openSkinToneDialog(emoji, emojiSize, categoryEmoji, index); - }; - - return _buildButtonWidget( - onPressed: onPressed, - onLongPressed: onLongPressed, - child: _buildEmoji( - emojiSize, - categoryEmoji, - emoji, - widget.config.enableSkinTones, - ), - ); - }).toList(), - ), - ); - } - - /// Build and display Emoji centered of its parent - Widget _buildEmoji( - double emojiSize, - CategoryEmoji categoryEmoji, - Emoji emoji, - bool showSkinToneIndicator, - ) { - // FittedBox needed for display, font scale settings - return FittedBox( - fit: BoxFit.fill, - child: Stack(children: [ - emoji.hasSkinTone && showSkinToneIndicator - ? Positioned( - bottom: 0, - right: 0, - child: CustomPaint( - size: const Size(8, 8), - painter: TriangleShape(widget.config.skinToneIndicatorColor), - ), - ) - : Container(), - Text( - emoji.emoji, - textScaleFactor: 1.0, - style: TextStyle( - fontSize: emojiSize, - backgroundColor: Colors.transparent, - ), - ), - ]), - ); - } - - /// Build different Button based on ButtonMode - Widget _buildButtonWidget({ - required VoidCallback onPressed, - required VoidCallback onLongPressed, - required Widget child, - }) { - if (widget.config.buttonMode == ButtonMode.MATERIAL) { - return TextButton( - onPressed: onPressed, - onLongPress: onLongPressed, - style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), - minimumSize: MaterialStateProperty.all(Size.zero), - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - ), - child: child, - ); - } - return GestureDetector( - onLongPress: onLongPressed, - child: CupertinoButton( - padding: EdgeInsets.zero, - onPressed: onPressed, - child: child, - ), - ); - } - - /// Build Widget for when no recent emoji are available - Widget _buildNoRecent() { - return Center( - child: Text( - widget.config.noRecentsText, - style: widget.config.noRecentsStyle, - textAlign: TextAlign.center, - )); - } - - /// Overlay for SkinTone - OverlayEntry _buildSkinToneOverlay( - Emoji emoji, - double emojiSize, - CategoryEmoji categoryEmoji, - int index, - ) { - // Calculate position of emoji in the grid - final row = index ~/ widget.config.columns; - final column = index % widget.config.columns; - // Calculate position for skin tone dialog - final renderBox = context.findRenderObject() as RenderBox; - final offset = renderBox.localToGlobal(Offset.zero); - final emojiSpace = renderBox.size.width / widget.config.columns; - final topOffset = emojiSpace; - final leftOffset = _getLeftOffset(emojiSpace, column); - final left = offset.dx + column * emojiSpace + leftOffset; - final top = tabBarHeight + - offset.dy + - row * emojiSpace - - _scrollController.offset - - topOffset; - - // Generate other skintone options - final skinTonesEmoji = SkinTone.values - .map((skinTone) => _utils.applySkinTone(emoji, skinTone)) - .toList(); - - return OverlayEntry( - builder: (context) => Positioned( - left: left, - top: top, - child: Material( - elevation: 4.0, - child: Container( - padding: const EdgeInsets.symmetric(vertical: 4.0), - color: widget.config.skinToneDialogBgColor, - child: Row( - children: [ - _buildSkinToneEmoji( - categoryEmoji, emoji, emojiSpace, emojiSize), - _buildSkinToneEmoji( - categoryEmoji, skinTonesEmoji[0], emojiSpace, emojiSize), - _buildSkinToneEmoji( - categoryEmoji, skinTonesEmoji[1], emojiSpace, emojiSize), - _buildSkinToneEmoji( - categoryEmoji, skinTonesEmoji[2], emojiSpace, emojiSize), - _buildSkinToneEmoji( - categoryEmoji, skinTonesEmoji[3], emojiSpace, emojiSize), - _buildSkinToneEmoji( - categoryEmoji, skinTonesEmoji[4], emojiSpace, emojiSize), - ], - ), - ), - ), - ), - ); - } - - // Build Emoji inside skin tone dialog - Widget _buildSkinToneEmoji( - CategoryEmoji categoryEmoji, - Emoji emoji, - double width, - double emojiSize, - ) { - return SizedBox( - width: width, - height: width, - child: _buildButtonWidget( - onPressed: () { - widget.state.onEmojiSelected(categoryEmoji.category, emoji); - _closeSkinToneDialog(); - }, - onLongPressed: () {}, - child: _buildEmoji(emojiSize, categoryEmoji, emoji, false), - ), - ); - } - - // Calucates the offset from the middle of selected emoji to the left side - // of the skin tone dialog - // Case 1: Selected Emoji is close to left border and offset needs to be - // reduced - // Case 2: Selected Emoji is close to right border and offset needs to be - // larger than half of the whole width - // Case 3: Enough space to left and right border and offset can be half - // of whole width - double _getLeftOffset(double emojiWidth, int column) { - final remainingColumns = - widget.config.columns - (column + 1 + (_skinToneCount ~/ 2)); - if (column >= 0 && column < 3) { - return -1 * column * emojiWidth; - } else if (remainingColumns < 0) { - return -1 * - ((_skinToneCount ~/ 2 - 1) + -1 * remainingColumns) * - emojiWidth; - } - return -1 * ((_skinToneCount ~/ 2) * emojiWidth) + emojiWidth / 2; - } -}