import 'package:bubble/bubble.dart'; import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; import 'package:marianum_mobile/api/marianumcloud/talk/chat/getChatResponse.dart'; import 'package:marianum_mobile/screen/pages/talk/chatMessage.dart'; import '../../../api/marianumcloud/talk/room/getRoomResponse.dart'; import '../../settings/debug/jsonViewer.dart'; class ChatBubble { static const styleSystem = BubbleStyle( color: Color(0xffd4eaf4), borderWidth: 1, elevation: 2, margin: BubbleEdges.only(bottom: 15), alignment: Alignment.center, ); static BubbleStyle getStyleOther(bool seamless) { return BubbleStyle( nip: BubbleNip.leftTop, color: seamless ? Colors.transparent : Colors.white, borderWidth: seamless ? 0 : 1, elevation: seamless ? 0 : 1, margin: const BubbleEdges.only(bottom: 15, left: 10, right: 50), alignment: Alignment.topLeft, ); } static BubbleStyle getStyleSelf(bool seamless) { return BubbleStyle( nip: BubbleNip.rightBottom, color: seamless ? Colors.transparent : const Color(0xffd9fdd3), borderWidth: seamless ? 0 : 1, elevation: seamless ? 0 : 1, margin: const BubbleEdges.only(bottom: 15, right: 10, left: 50), alignment: Alignment.topRight, ); } BuildContext context; bool isSender; GetChatResponseObject bubbleData; GetRoomResponseObject chatData; late ChatMessage message; ChatBubble({ required this.context, required this.isSender, required this.bubbleData, required this.chatData, }) { message = ChatMessage(originalMessage: bubbleData.message, originalData: bubbleData.messageParameters); } BubbleStyle getStyle() { if(bubbleData.messageType == GetRoomResponseObjectMessageType.comment) { if(isSender) { return getStyleSelf(message.containsFile); } else { return getStyleOther(message.containsFile); } } else { return styleSystem; } } Widget generateBubble() { bool showActorDisplayName = bubbleData.messageType == GetRoomResponseObjectMessageType.comment && chatData.type != GetRoomResponseObjectConversationType.oneToOne; bool showBubbleTime = bubbleData.messageType != GetRoomResponseObjectMessageType.system; var actorTextStyle = TextStyle(color: Theme.of(context).primaryColor, fontWeight: FontWeight.bold); return GestureDetector( child: Bubble( style: getStyle(), child: Container( constraints: BoxConstraints( maxWidth: MediaQuery.of(context).size.width * 0.9, minWidth: showActorDisplayName ? _textSize(bubbleData.actorDisplayName, actorTextStyle).width : 30, ), child: Stack( children: [ Padding( padding: EdgeInsets.only(bottom: showBubbleTime ? 18 : 0, top: showActorDisplayName ? 18 : 0), child: FutureBuilder( future: message.getWidget(), builder: (context, snapshot) { if(!snapshot.hasData) return const CircularProgressIndicator(); return snapshot.data ?? const Icon(Icons.error); }, ) ), Visibility( visible: showActorDisplayName, child: Positioned( top: 0, left: 0, child: Text( bubbleData.actorDisplayName, textAlign: TextAlign.start, style: actorTextStyle, ), ), ), Visibility( visible: showBubbleTime, child: Positioned( bottom: 0, right: 0, child: Text( Jiffy.unixFromSecondsSinceEpoch(bubbleData.timestamp).format("HH:mm"), textAlign: TextAlign.end, style: const TextStyle(color: Colors.grey, fontSize: 12), ), ), ), ], ), ), ), onLongPress: () { showDialog(context: context, builder: (context) { return SimpleDialog( children: [ ListTile( leading: Icon(Icons.copy), title: Text("Nachricht kopieren"), ), ListTile( leading: Icon(Icons.person), title: Text("Zu '${bubbleData.actorDisplayName}' wechseln"), ), ListTile( leading: Icon(Icons.bug_report_outlined), title: Text("Debugdaten anzeigen"), onTap: () => JsonViewer.asDialog(context, bubbleData.toJson()), ) ], ); }); }, ); } Size _textSize(String text, TextStyle style) { final TextPainter textPainter = TextPainter( text: TextSpan(text: text, style: style), maxLines: 1, textDirection: TextDirection.ltr) ..layout(minWidth: 0, maxWidth: double.infinity); return textPainter.size; } }