cwtch-ui/lib/widgets/quotedmessage.dart

158 lines
8.3 KiB
Dart

import 'package:cwtch/models/contact.dart';
import 'package:cwtch/models/message.dart';
import 'package:cwtch/models/profile.dart';
import 'package:cwtch/widgets/malformedbubble.dart';
import 'package:cwtch/widgets/messageloadingbubble.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import '../models/redaction.dart';
import '../settings.dart';
import 'messageBubbleWidgetHelpers.dart';
import 'messagebubbledecorations.dart';
class QuotedMessageBubble extends StatefulWidget {
final Future<Message> quotedMessage;
final String body;
QuotedMessageBubble(this.body, this.quotedMessage);
@override
QuotedMessageBubbleState createState() => QuotedMessageBubbleState();
}
class QuotedMessageBubbleState extends State<QuotedMessageBubble> {
FocusNode _focus = FocusNode();
@override
Widget build(BuildContext context) {
var fromMe = Provider.of<MessageMetadata>(context).senderHandle == Provider.of<ProfileInfoState>(context).onion;
var borderRadiousEh = 15.0;
DateTime messageDate = Provider.of<MessageMetadata>(context).timestamp;
// If the sender is not us, then we want to give them a nickname...
var senderDisplayStr = "";
if (!fromMe) {
ContactInfoState? contact = Provider.of<ProfileInfoState>(context).contactList.findContact(Provider.of<MessageMetadata>(context).senderHandle);
if (contact != null) {
senderDisplayStr = redactedNick(context, contact.onion, contact.nickname);
} else {
senderDisplayStr = Provider.of<MessageMetadata>(context).senderHandle;
}
}
var showClickableLinks = Provider.of<Settings>(context).isExperimentEnabled(ClickableLinksExperiment);
var formatMessages = Provider.of<Settings>(context).isExperimentEnabled(FormattingExperiment);
Size size = MediaQuery.of(context).size;
BoxConstraints constraints = BoxConstraints.loose(size);
Widget wdgMessage = compileMessageContentWidget(context, constraints, fromMe, widget.body, _focus, formatMessages, showClickableLinks);
var wdgQuote = FutureBuilder(
future: widget.quotedMessage,
builder: (context, snapshot) {
if (snapshot.hasData) {
try {
var qMessage = (snapshot.data! as Message);
// If the sender is not us, then we want to give them a nickname...
String qMessageSender;
// if we sent the quoted message then display our nickname
if (qMessage.getMetadata().senderHandle == Provider.of<ProfileInfoState>(context).onion) {
qMessageSender = Provider.of<ProfileInfoState>(context).nickname;
} else {
// default to handle
qMessageSender = qMessage.getMetadata().senderHandle;
// if we have the handle as a contact then replace with the nickname...
ContactInfoState? contact = Provider.of<ProfileInfoState>(context).contactList.findContact(qMessageSender);
if (contact != null) {
qMessageSender = contact.nickname;
}
}
var qTextColor = fromMe ? Provider.of<Settings>(context).theme.messageFromOtherTextColor : Provider.of<Settings>(context).theme.messageFromMeTextColor;
var wdgReplyingTo = SelectableText(
AppLocalizations.of(context)!.replyingTo.replaceAll("%1", qMessageSender),
style: Provider.of<Settings>(context).scaleFonts(TextStyle(fontSize: 10, color: qTextColor.withOpacity(0.8))),
);
// Swap the background color for quoted tweets..
return MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: () {
var messageInfo = Provider.of<ContactInfoState>(context, listen: false).messageCache.getByContentHash(qMessage.getMetadata().contenthash);
if (messageInfo != null) {
var index = Provider.of<ContactInfoState>(context, listen: false).messageCache.findIndex(messageInfo.metadata.messageID);
Provider.of<ContactInfoState>(context, listen: false).messageScrollController.scrollTo(index: index, duration: Duration(milliseconds: 100));
}
},
child: Container(
margin: EdgeInsets.all(5),
padding: EdgeInsets.all(5),
clipBehavior: Clip.antiAliasWithSaveLayer,
decoration: BoxDecoration(
color: fromMe ? Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor : Provider.of<Settings>(context).theme.messageFromMeBackgroundColor,
),
height: 75,
child: Column(crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [
Align(alignment: Alignment.centerLeft, child: wdgReplyingTo),
Flexible(
child: Row(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [
Padding(padding: EdgeInsets.symmetric(vertical: 5.0, horizontal: 10.0), child: Icon(Icons.reply, size: 32, color: qTextColor)),
Flexible(child: IntrinsicWidth(child: qMessage.getPreviewWidget(context))),
]))
])),
),
);
} catch (e) {
return MalformedBubble();
}
} else {
// This should be almost instantly resolved, any failure likely means an issue in decoding...
return MessageLoadingBubble();
}
},
);
var wdgDecorations = MessageBubbleDecoration(ackd: Provider.of<MessageMetadata>(context).ackd, errored: Provider.of<MessageMetadata>(context).error, fromMe: fromMe, messageDate: messageDate);
var error = Provider.of<MessageMetadata>(context).error;
var wdgSender = compileSenderWidget(context, constraints, fromMe, senderDisplayStr);
return Container(
decoration: BoxDecoration(
color: error ? malformedColor : (fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor),
border: Border.all(
color: error ? malformedColor : (fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor : Provider.of<Settings>(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<Settings>(context).theme.messageSelectionColor,
selectionColor: Provider.of<Settings>(context).theme.messageSelectionColor,
selectionHandleColor: Provider.of<Settings>(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<Settings>(context).theme.menuBackgroundColor)),
),
),
child: IntrinsicWidth(
child: Column(
crossAxisAlignment: fromMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
mainAxisAlignment: fromMe ? MainAxisAlignment.end : MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
verticalDirection: VerticalDirection.up,
children: fromMe ? [wdgDecorations, wdgMessage, wdgQuote] : [wdgDecorations, wdgMessage, wdgQuote, wdgSender])))));
}
}