import 'package:cwtch/models/contact.dart'; import 'package:cwtch/models/message.dart'; import 'package:cwtch/models/redaction.dart'; import 'package:cwtch/models/profile.dart'; import 'package:cwtch/widgets/malformedbubble.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../settings.dart'; import 'messageBubbleWidgetHelpers.dart'; import 'messagebubbledecorations.dart'; class MessageBubble extends StatefulWidget { final String content; MessageBubble(this.content); @override MessageBubbleState createState() => MessageBubbleState(); } class MessageBubbleState extends State { FocusNode _focus = FocusNode(); @override Widget build(BuildContext context) { var fromMe = Provider.of(context).senderHandle == Provider.of(context).onion; var borderRadiousEh = 15.0; var showClickableLinks = Provider.of(context).isExperimentEnabled(ClickableLinksExperiment); var formatMessages = Provider.of(context).isExperimentEnabled(FormattingExperiment); DateTime messageDate = Provider.of(context).timestamp; // If the sender is not us, then we want to give them a nickname... var senderDisplayStr = ""; if (!fromMe) { ContactInfoState? contact = Provider.of(context).contactList.findContact(Provider.of(context).senderHandle); if (contact != null) { senderDisplayStr = redactedNick(context, contact.onion, contact.nickname); } else { senderDisplayStr = Provider.of(context).senderHandle; } } Size size = MediaQuery.sizeOf(context); var wdgSender = compileSenderWidget(context, null, fromMe, senderDisplayStr); var wdgMessage = compileMessageContentWidget(context, BoxConstraints.loose(size), fromMe, widget.content, _focus, formatMessages, showClickableLinks); var wdgDecorations = MessageBubbleDecoration(ackd: Provider.of(context).ackd, errored: Provider.of(context).error, fromMe: fromMe, messageDate: messageDate); var error = Provider.of(context).error; return Container( decoration: BoxDecoration( color: error ? malformedColor : (fromMe ? Provider.of(context).theme.messageFromMeBackgroundColor : Provider.of(context).theme.messageFromOtherBackgroundColor), border: Border.all( color: error ? malformedColor : (fromMe ? Provider.of(context).theme.messageFromMeBackgroundColor : Provider.of(context).theme.messageFromOtherBackgroundColor), width: 1), borderRadius: BorderRadius.only( topLeft: Radius.circular(borderRadiousEh), topRight: Radius.circular(borderRadiousEh), bottomLeft: fromMe ? Radius.circular(borderRadiousEh) : Radius.zero, bottomRight: fromMe ? Radius.zero : Radius.circular(borderRadiousEh), ), ), child: Padding( padding: EdgeInsets.all(9.0), child: Theme( data: Theme.of(context).copyWith( textSelectionTheme: TextSelectionThemeData( cursorColor: Provider.of(context).theme.messageSelectionColor, selectionColor: Provider.of(context).theme.messageSelectionColor, selectionHandleColor: Provider.of(context).theme.messageSelectionColor), // Horrifying Hack: Flutter doesn't give us direct control over system menus but instead picks BG color from TextButtonThemeData ¯\_(ツ)_/¯ textButtonTheme: TextButtonThemeData( style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Provider.of(context).theme.menuBackgroundColor)), ), ), child: Column( crossAxisAlignment: fromMe ? CrossAxisAlignment.end : CrossAxisAlignment.start, mainAxisAlignment: fromMe ? MainAxisAlignment.end : MainAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: fromMe ? [wdgMessage, wdgDecorations] : [wdgSender, wdgMessage, wdgDecorations])))); } }