2022-06-10 21:21:40 +00:00
|
|
|
import 'package:cwtch/controllers/open_link_modal.dart';
|
2022-01-18 21:26:52 +00:00
|
|
|
import 'package:cwtch/models/contact.dart';
|
2021-07-06 19:46:39 +00:00
|
|
|
import 'package:cwtch/models/message.dart';
|
2022-01-18 21:26:52 +00:00
|
|
|
import 'package:cwtch/models/profile.dart';
|
2022-06-10 21:21:40 +00:00
|
|
|
import 'package:cwtch/third_party/linkify/flutter_linkify.dart';
|
2021-07-05 19:30:26 +00:00
|
|
|
import 'package:cwtch/widgets/malformedbubble.dart';
|
2021-07-06 19:46:39 +00:00
|
|
|
import 'package:cwtch/widgets/messageloadingbubble.dart';
|
2022-06-13 17:06:06 +00:00
|
|
|
import 'package:flutter/cupertino.dart';
|
2021-07-05 19:30:26 +00:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:provider/provider.dart';
|
2022-11-24 21:28:25 +00:00
|
|
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
2021-07-05 19:30:26 +00:00
|
|
|
import '../settings.dart';
|
|
|
|
import 'messagebubbledecorations.dart';
|
|
|
|
|
2021-07-06 19:46:39 +00:00
|
|
|
class QuotedMessageBubble extends StatefulWidget {
|
|
|
|
final Future<Message> quotedMessage;
|
|
|
|
final String body;
|
2021-07-05 19:31:16 +00:00
|
|
|
|
2021-07-06 19:46:39 +00:00
|
|
|
QuotedMessageBubble(this.body, this.quotedMessage);
|
2021-07-05 19:31:16 +00:00
|
|
|
|
2021-07-05 19:30:26 +00:00
|
|
|
@override
|
|
|
|
QuotedMessageBubbleState createState() => QuotedMessageBubbleState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class QuotedMessageBubbleState extends State<QuotedMessageBubble> {
|
|
|
|
FocusNode _focus = FocusNode();
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2021-07-06 19:46:39 +00:00
|
|
|
var fromMe = Provider.of<MessageMetadata>(context).senderHandle == Provider.of<ProfileInfoState>(context).onion;
|
2021-07-05 19:30:26 +00:00
|
|
|
var borderRadiousEh = 15.0;
|
2021-07-05 19:31:16 +00:00
|
|
|
|
2021-07-06 19:46:39 +00:00
|
|
|
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) {
|
2021-11-18 23:44:54 +00:00
|
|
|
ContactInfoState? contact = Provider.of<ProfileInfoState>(context).contactList.findContact(Provider.of<MessageMetadata>(context).senderHandle);
|
2021-07-06 19:46:39 +00:00
|
|
|
if (contact != null) {
|
|
|
|
senderDisplayStr = contact.nickname;
|
|
|
|
} else {
|
|
|
|
senderDisplayStr = Provider.of<MessageMetadata>(context).senderHandle;
|
2021-07-05 19:30:26 +00:00
|
|
|
}
|
2021-07-06 19:46:39 +00:00
|
|
|
}
|
2022-11-24 21:28:25 +00:00
|
|
|
|
2023-02-16 21:46:48 +00:00
|
|
|
var wdgSender = Container(
|
2023-05-15 19:05:28 +00:00
|
|
|
height: 14 * Provider.of<Settings>(context).fontScaling,
|
2023-02-16 21:46:48 +00:00
|
|
|
clipBehavior: Clip.hardEdge,
|
|
|
|
decoration: BoxDecoration(),
|
|
|
|
child: SelectableText(senderDisplayStr,
|
2023-05-15 19:05:28 +00:00
|
|
|
style: TextStyle(
|
|
|
|
fontSize: 9.0 * Provider.of<Settings>(context).fontScaling,
|
|
|
|
fontWeight: FontWeight.bold,
|
|
|
|
fontFamily: "Inter",
|
|
|
|
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor)));
|
2021-07-06 19:46:39 +00:00
|
|
|
|
2022-06-10 21:21:40 +00:00
|
|
|
var showClickableLinks = Provider.of<Settings>(context).isExperimentEnabled(ClickableLinksExperiment);
|
|
|
|
var formatMessages = Provider.of<Settings>(context).isExperimentEnabled(FormattingExperiment);
|
|
|
|
|
|
|
|
var wdgMessage = SelectableLinkify(
|
|
|
|
text: widget.body + '\u202F',
|
|
|
|
// TODO: onOpen breaks the "selectable" functionality. Maybe something to do with gesture handler?
|
|
|
|
options: LinkifyOptions(messageFormatting: formatMessages, parseLinks: showClickableLinks, looseUrl: true, defaultToHttps: true),
|
|
|
|
linkifiers: [UrlLinkifier()],
|
|
|
|
onOpen: showClickableLinks
|
|
|
|
? (link) {
|
|
|
|
modalOpenLink(context, link);
|
|
|
|
}
|
|
|
|
: null,
|
|
|
|
//key: Key(myKey),
|
2021-07-06 19:46:39 +00:00
|
|
|
focusNode: _focus,
|
|
|
|
style: TextStyle(
|
2023-05-15 19:05:28 +00:00
|
|
|
fontSize: 12.0 * Provider.of<Settings>(context).fontScaling,
|
|
|
|
fontWeight: FontWeight.normal,
|
|
|
|
fontFamily: "Inter",
|
2021-12-10 04:22:55 +00:00
|
|
|
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor,
|
2021-07-06 19:46:39 +00:00
|
|
|
),
|
2023-05-15 19:05:28 +00:00
|
|
|
linkStyle: TextStyle(
|
|
|
|
fontSize: 12.0 * Provider.of<Settings>(context).fontScaling,
|
|
|
|
fontWeight: FontWeight.normal,
|
|
|
|
fontFamily: "Inter",
|
|
|
|
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor),
|
2022-06-10 21:21:40 +00:00
|
|
|
codeStyle: TextStyle(
|
2023-05-15 19:05:28 +00:00
|
|
|
fontSize: 12.0 * Provider.of<Settings>(context).fontScaling,
|
|
|
|
fontWeight: FontWeight.normal,
|
|
|
|
fontFamily: "RobotoMono",
|
2022-06-10 21:21:40 +00:00
|
|
|
// note: these colors are flipped
|
|
|
|
color: fromMe ? Provider.of<Settings>(context).theme.messageFromOtherTextColor : Provider.of<Settings>(context).theme.messageFromMeTextColor,
|
|
|
|
backgroundColor: fromMe ? Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor : Provider.of<Settings>(context).theme.messageFromMeBackgroundColor),
|
2021-07-06 19:46:39 +00:00
|
|
|
textAlign: TextAlign.left,
|
|
|
|
textWidthBasis: TextWidthBasis.longestLine,
|
|
|
|
);
|
|
|
|
|
|
|
|
var wdgQuote = FutureBuilder(
|
|
|
|
future: widget.quotedMessage,
|
|
|
|
builder: (context, snapshot) {
|
|
|
|
if (snapshot.hasData) {
|
2021-07-07 17:05:25 +00:00
|
|
|
try {
|
|
|
|
var qMessage = (snapshot.data! as Message);
|
2022-11-24 21:28:25 +00:00
|
|
|
|
|
|
|
// If the sender is not us, then we want to give them a nickname...
|
|
|
|
String qMessageSender;
|
|
|
|
|
2022-11-24 21:51:26 +00:00
|
|
|
// if we sent the quoted message then display our nickname
|
2022-11-24 21:28:25 +00:00
|
|
|
if (qMessage.getMetadata().senderHandle == Provider.of<ProfileInfoState>(context).onion) {
|
|
|
|
qMessageSender = Provider.of<ProfileInfoState>(context).nickname;
|
|
|
|
} else {
|
2022-11-24 21:51:26 +00:00
|
|
|
// 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);
|
2022-11-24 21:28:25 +00:00
|
|
|
if (contact != null) {
|
|
|
|
qMessageSender = contact.nickname;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-10 04:22:55 +00:00
|
|
|
var qTextColor = fromMe ? Provider.of<Settings>(context).theme.messageFromOtherTextColor : Provider.of<Settings>(context).theme.messageFromMeTextColor;
|
2022-11-24 21:28:25 +00:00
|
|
|
|
|
|
|
var wdgReplyingTo = SelectableText(
|
|
|
|
AppLocalizations.of(context)!.replyingTo.replaceAll("%1", qMessageSender),
|
|
|
|
style: TextStyle(fontSize: 10, color: qTextColor.withOpacity(0.8)),
|
|
|
|
);
|
|
|
|
// Swap the background color for quoted tweets..
|
2022-06-10 19:10:17 +00:00
|
|
|
return MouseRegion(
|
|
|
|
cursor: SystemMouseCursors.click,
|
|
|
|
child: GestureDetector(
|
|
|
|
onTap: () {
|
2022-06-23 18:25:26 +00:00
|
|
|
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);
|
|
|
|
if (index != null) {
|
|
|
|
Provider.of<ContactInfoState>(context, listen: false).messageScrollController.scrollTo(index: index, duration: Duration(milliseconds: 100));
|
|
|
|
}
|
|
|
|
}
|
2022-06-10 19:10:17 +00:00
|
|
|
},
|
|
|
|
child: Container(
|
|
|
|
margin: EdgeInsets.all(5),
|
|
|
|
padding: EdgeInsets.all(5),
|
2022-06-13 17:06:06 +00:00
|
|
|
clipBehavior: Clip.antiAlias,
|
2022-06-20 17:54:06 +00:00
|
|
|
decoration: BoxDecoration(
|
|
|
|
color: fromMe ? Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor : Provider.of<Settings>(context).theme.messageFromMeBackgroundColor,
|
|
|
|
),
|
2022-06-13 17:06:06 +00:00
|
|
|
height: 75,
|
2022-11-24 21:28:25 +00:00
|
|
|
child: Column(children: [
|
|
|
|
Align(alignment: Alignment.centerLeft, child: wdgReplyingTo),
|
2022-12-30 04:27:25 +00:00
|
|
|
Flexible(
|
|
|
|
child: Row(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [
|
2022-11-24 21:28:25 +00:00
|
|
|
Padding(padding: EdgeInsets.symmetric(vertical: 5.0, horizontal: 10.0), child: Icon(Icons.reply, size: 32, color: qTextColor)),
|
2022-12-30 04:27:25 +00:00
|
|
|
Flexible(child: qMessage.getPreviewWidget(context)),
|
|
|
|
]))
|
2022-06-10 19:10:17 +00:00
|
|
|
]))));
|
2021-07-07 17:05:25 +00:00
|
|
|
} catch (e) {
|
|
|
|
return MalformedBubble();
|
|
|
|
}
|
2021-07-05 19:31:16 +00:00
|
|
|
} else {
|
2021-07-06 19:46:39 +00:00
|
|
|
// This should be almost instantly resolved, any failure likely means an issue in decoding...
|
|
|
|
return MessageLoadingBubble();
|
2021-07-05 19:31:16 +00:00
|
|
|
}
|
2021-07-06 19:46:39 +00:00
|
|
|
},
|
|
|
|
);
|
|
|
|
|
2022-03-01 06:35:09 +00:00
|
|
|
var wdgDecorations = MessageBubbleDecoration(ackd: Provider.of<MessageMetadata>(context).ackd, errored: Provider.of<MessageMetadata>(context).error, fromMe: fromMe, messageDate: messageDate);
|
2021-07-06 19:46:39 +00:00
|
|
|
|
|
|
|
var error = Provider.of<MessageMetadata>(context).error;
|
|
|
|
|
|
|
|
return LayoutBuilder(builder: (context, constraints) {
|
|
|
|
return RepaintBoundary(
|
|
|
|
child: Container(
|
|
|
|
child: Container(
|
|
|
|
decoration: BoxDecoration(
|
2021-12-15 22:29:27 +00:00
|
|
|
color: error ? malformedColor : (fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor),
|
2021-07-06 19:46:39 +00:00
|
|
|
border: Border.all(
|
|
|
|
color: error
|
|
|
|
? malformedColor
|
2021-12-10 04:22:55 +00:00
|
|
|
: (fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor),
|
2021-07-06 19:46:39 +00:00
|
|
|
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),
|
2021-07-05 19:30:26 +00:00
|
|
|
),
|
2021-07-06 19:46:39 +00:00
|
|
|
),
|
|
|
|
child: Padding(
|
|
|
|
padding: EdgeInsets.all(9.0),
|
|
|
|
child: Column(
|
|
|
|
crossAxisAlignment: fromMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
|
|
|
mainAxisAlignment: fromMe ? MainAxisAlignment.end : MainAxisAlignment.start,
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
children: fromMe ? [wdgQuote, wdgMessage, wdgDecorations] : [wdgSender, wdgQuote, wdgMessage, wdgDecorations])))));
|
|
|
|
});
|
2021-07-05 19:30:26 +00:00
|
|
|
}
|
|
|
|
}
|