131 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
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';
 | 
						|
 | 
						|
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;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Bubble 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 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),
 | 
						|
                ),
 | 
						|
              ),
 | 
						|
            ),
 | 
						|
          ],
 | 
						|
        ),
 | 
						|
      ),
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  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;
 | 
						|
  }
 | 
						|
} |