diff --git a/lib/view/pages/talk/components/chatBubble.dart b/lib/view/pages/talk/components/chatBubble.dart index 6e56dc7..6c589c5 100644 --- a/lib/view/pages/talk/components/chatBubble.dart +++ b/lib/view/pages/talk/components/chatBubble.dart @@ -99,6 +99,167 @@ class _ChatBubbleState extends State { } } + void showOptionsDialog() { + showDialog(context: context, builder: (context) { + var commonReactions = ['👍', '👎', '😆', '❤️', '👀']; + var canReact = widget.bubbleData.messageType == GetRoomResponseObjectMessageType.comment; + return SimpleDialog( + children: [ + Visibility( + visible: canReact, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Wrap( + alignment: WrapAlignment.center, + children: [ + ...commonReactions.map((e) => TextButton( + style: TextButton.styleFrom( + padding: EdgeInsets.zero, + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + minimumSize: const Size(40, 40) + ), + onPressed: () { + Navigator.of(context).pop(); + ReactMessage( + chatToken: widget.chatData.token, + messageId: widget.bubbleData.id, + params: ReactMessageParams(e), + ).run().then((value) => widget.refetch(renew: true)); + }, + child: Text(e), + ), + ), + IconButton( + onPressed: () { + showDialog(context: context, builder: (context) => AlertDialog( + contentPadding: const EdgeInsets.all(15), + titlePadding: const EdgeInsets.only(left: 6, top: 15), + title: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + IconButton( + onPressed: () { + Navigator.of(context).pop(); + }, + icon: const Icon(Icons.arrow_back), + ), + const SizedBox(width: 10), + const Text('Reagieren'), + ], + ), + content: SizedBox( + width: 256, + height: 270, + child: Column( + children: [ + emojis.EmojiPicker( + config: emojis.Config( + height: 256, + swapCategoryAndBottomBar: true, + emojiViewConfig: emojis.EmojiViewConfig( + backgroundColor: Theme.of(context).canvasColor, + recentsLimit: 67, + emojiSizeMax: 25, + noRecents: const Text('Keine zuletzt verwendeten Emojis'), + columns: 7, + ), + bottomActionBarConfig: const emojis.BottomActionBarConfig( + enabled: false, + ), + categoryViewConfig: emojis.CategoryViewConfig( + backgroundColor: Theme.of(context).hoverColor, + iconColorSelected: Theme.of(context).primaryColor, + indicatorColor: Theme.of(context).primaryColor, + ), + searchViewConfig: emojis.SearchViewConfig( + backgroundColor: Theme.of(context).dividerColor, + buttonColor: Theme.of(context).dividerColor, + hintText: 'Suchen', + buttonIconColor: Colors.white, + ), + ), + onEmojiSelected: (emojis.Category? category, emojis.Emoji emoji) { + Navigator.of(context).pop(); + Navigator.of(context).pop(); + ReactMessage( + chatToken: widget.chatData.token, + messageId: widget.bubbleData.id, + params: ReactMessageParams(emoji.emoji), + ).run().then((value) => widget.refetch(renew: true)); + }, + ), + ], + ), + ), + )); + }, + style: IconButton.styleFrom( + padding: EdgeInsets.zero, + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + minimumSize: const Size(40, 40), + ), + icon: const Icon(Icons.add_circle_outline_outlined), + ), + ], + ), + const Divider(), + ], + ), + ), + Visibility( + visible: canReact, + child: ListTile( + leading: const Icon(Icons.emoji_emotions_outlined), + title: const Text('Reaktionen'), + onTap: () { + Navigator.of(context).push(MaterialPageRoute(builder: (context) => MessageReactions( + token: widget.chatData.token, + messageId: widget.bubbleData.id, + ))); + }, + ), + ), + Visibility( + visible: !message.containsFile, + child: ListTile( + leading: const Icon(Icons.copy), + title: const Text('Nachricht kopieren'), + onTap: () => { + Clipboard.setData(ClipboardData(text: widget.bubbleData.message)), + Navigator.of(context).pop(), + }, + ), + ), + Visibility( + visible: !kReleaseMode && !widget.isSender && widget.chatData.type != GetRoomResponseObjectConversationType.oneToOne, + child: ListTile( + leading: const Icon(Icons.sms_outlined), + title: Text("Private Nachricht an '${widget.bubbleData.actorDisplayName}'"), + onTap: () => { + Navigator.of(context).pop() + }, + ), + ), + Visibility( + visible: widget.isSender && DateTime.fromMillisecondsSinceEpoch(widget.bubbleData.timestamp * 1000).add(const Duration(hours: 6)).isAfter(DateTime.now()), + child: ListTile( + leading: const Icon(Icons.delete_outline), + title: const Text('Nachricht löschen'), + onTap: () { + DeleteMessage(widget.chatData.token, widget.bubbleData.id).run().then((value) { + Provider.of(context, listen: false).run(); + Navigator.of(context).pop(); + }); + }, + ), + ), + DebugTile(context).jsonData(widget.bubbleData.toJson()), + ], + ); + }); + } + @override Widget build(BuildContext context) { @@ -127,6 +288,54 @@ class _ChatBubbleState extends State { children: [ GestureDetector( + onLongPress: showOptionsDialog, + onDoubleTap: showOptionsDialog, + onTap: () { + if(message.file == null) return; + + if(downloadProgress > 0) { + showDialog(context: context, builder: (context) => AlertDialog( + title: const Text('Download abbrechen?'), + content: const Text('Möchtest du den Download abbrechen?'), + actions: [ + TextButton(onPressed: () { + Navigator.of(context).pop(); + }, child: const Text('Nein')), + TextButton(onPressed: () { + downloadCore?.then((value) { + if(!value.isCancelled) value.cancel(); + Navigator.of(context).pop(); + }); + setState(() { + downloadProgress = 0; + downloadCore = null; + }); + }, child: const Text('Ja, Abbrechen')) + ], + )); + + return; + } + + downloadProgress = 1; + downloadCore = FileElement.download(context, message.file!.path!, message.file!.name, (progress) { + if(progress > 1) { + setState(() { + downloadProgress = progress; + }); + } + }, (result) { + setState(() { + downloadProgress = 0; + }); + + if(result.type != ResultType.done) { + showDialog(context: context, builder: (context) => AlertDialog( + content: Text(result.message), + )); + } + }); + }, child: Bubble( style: getStyle(), child: Container( @@ -182,212 +391,6 @@ class _ChatBubbleState extends State { ), ), ), - onLongPress: () { - showDialog(context: context, builder: (context) { - var commonReactions = ['👍', '👎', '😆', '❤️', '👀']; - var canReact = widget.bubbleData.messageType == GetRoomResponseObjectMessageType.comment; - return SimpleDialog( - children: [ - Visibility( - visible: canReact, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Wrap( - alignment: WrapAlignment.center, - children: [ - ...commonReactions.map((e) => TextButton( - style: TextButton.styleFrom( - padding: EdgeInsets.zero, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - minimumSize: const Size(40, 40) - ), - onPressed: () { - Navigator.of(context).pop(); - ReactMessage( - chatToken: widget.chatData.token, - messageId: widget.bubbleData.id, - params: ReactMessageParams(e), - ).run().then((value) => widget.refetch(renew: true)); - }, - child: Text(e), - ), - ), - IconButton( - onPressed: () { - showDialog(context: context, builder: (context) => AlertDialog( - contentPadding: const EdgeInsets.all(15), - titlePadding: const EdgeInsets.only(left: 6, top: 15), - title: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - IconButton( - onPressed: () { - Navigator.of(context).pop(); - }, - icon: const Icon(Icons.arrow_back), - ), - const SizedBox(width: 10), - const Text('Reagieren'), - ], - ), - content: SizedBox( - width: 256, - height: 270, - child: Column( - children: [ - emojis.EmojiPicker( - config: emojis.Config( - height: 256, - swapCategoryAndBottomBar: true, - emojiViewConfig: emojis.EmojiViewConfig( - backgroundColor: Theme.of(context).canvasColor, - recentsLimit: 67, - emojiSizeMax: 25, - noRecents: const Text('Keine zuletzt verwendeten Emojis'), - columns: 7, - ), - bottomActionBarConfig: const emojis.BottomActionBarConfig( - enabled: false, - ), - categoryViewConfig: emojis.CategoryViewConfig( - backgroundColor: Theme.of(context).hoverColor, - iconColorSelected: Theme.of(context).primaryColor, - indicatorColor: Theme.of(context).primaryColor, - ), - searchViewConfig: emojis.SearchViewConfig( - backgroundColor: Theme.of(context).dividerColor, - buttonColor: Theme.of(context).dividerColor, - hintText: 'Suchen', - buttonIconColor: Colors.white, - ), - ), - onEmojiSelected: (emojis.Category? category, emojis.Emoji emoji) { - Navigator.of(context).pop(); - Navigator.of(context).pop(); - ReactMessage( - chatToken: widget.chatData.token, - messageId: widget.bubbleData.id, - params: ReactMessageParams(emoji.emoji), - ).run().then((value) => widget.refetch(renew: true)); - }, - ), - ], - ), - ), - )); - }, - style: IconButton.styleFrom( - padding: EdgeInsets.zero, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - minimumSize: const Size(40, 40), - ), - icon: const Icon(Icons.add_circle_outline_outlined), - ), - ], - ), - const Divider(), - ], - ), - ), - Visibility( - visible: canReact, - child: ListTile( - leading: const Icon(Icons.emoji_emotions_outlined), - title: const Text('Reaktionen'), - onTap: () { - Navigator.of(context).push(MaterialPageRoute(builder: (context) => MessageReactions( - token: widget.chatData.token, - messageId: widget.bubbleData.id, - ))); - }, - ), - ), - Visibility( - visible: !message.containsFile, - child: ListTile( - leading: const Icon(Icons.copy), - title: const Text('Nachricht kopieren'), - onTap: () => { - Clipboard.setData(ClipboardData(text: widget.bubbleData.message)), - Navigator.of(context).pop(), - }, - ), - ), - Visibility( - visible: !kReleaseMode && !widget.isSender && widget.chatData.type != GetRoomResponseObjectConversationType.oneToOne, - child: ListTile( - leading: const Icon(Icons.sms_outlined), - title: Text("Private Nachricht an '${widget.bubbleData.actorDisplayName}'"), - onTap: () => { - Navigator.of(context).pop() - }, - ), - ), - Visibility( - visible: widget.isSender && DateTime.fromMillisecondsSinceEpoch(widget.bubbleData.timestamp * 1000).add(const Duration(hours: 6)).isAfter(DateTime.now()), - child: ListTile( - leading: const Icon(Icons.delete_outline), - title: const Text('Nachricht löschen'), - onTap: () { - DeleteMessage(widget.chatData.token, widget.bubbleData.id).run().then((value) { - Provider.of(context, listen: false).run(); - Navigator.of(context).pop(); - }); - }, - ), - ), - DebugTile(context).jsonData(widget.bubbleData.toJson()), - ], - ); - }); - }, - onTap: () { - if(message.file == null) return; - - if(downloadProgress > 0) { - showDialog(context: context, builder: (context) => AlertDialog( - title: const Text('Download abbrechen?'), - content: const Text('Möchtest du den Download abbrechen?'), - actions: [ - TextButton(onPressed: () { - Navigator.of(context).pop(); - }, child: const Text('Nein')), - TextButton(onPressed: () { - downloadCore?.then((value) { - if(!value.isCancelled) value.cancel(); - Navigator.of(context).pop(); - }); - setState(() { - downloadProgress = 0; - downloadCore = null; - }); - }, child: const Text('Ja, Abbrechen')) - ], - )); - - return; - } - - downloadProgress = 1; - downloadCore = FileElement.download(context, message.file!.path!, message.file!.name, (progress) { - if(progress > 1) { - setState(() { - downloadProgress = progress; - }); - } - }, (result) { - setState(() { - downloadProgress = 0; - }); - - if(result.type != ResultType.done) { - showDialog(context: context, builder: (context) => AlertDialog( - content: Text(result.message), - )); - } - }); - }, ), Visibility( visible: widget.bubbleData.reactions != null,