diff --git a/lib/models/message_draft.dart b/lib/models/message_draft.dart index 0ffb98ab..23ffb6ff 100644 --- a/lib/models/message_draft.dart +++ b/lib/models/message_draft.dart @@ -6,7 +6,7 @@ import 'package:flutter/foundation.dart'; /// Only one draft is stored per conversation. class MessageDraft extends ChangeNotifier { QuotedReference? _quotedReference; - + int? _inviteHandle; TextEditingController ctrlCompose = TextEditingController(); static MessageDraft empty() { @@ -29,6 +29,15 @@ class MessageDraft extends ChangeNotifier { notifyListeners(); } + void attachInvite(int handle) { + this._inviteHandle = handle; + notifyListeners(); + } + + int? getInviteHandle() { + return this._inviteHandle; + } + QuotedReference? getQuotedMessage() { return this._quotedReference; } @@ -41,6 +50,7 @@ class MessageDraft extends ChangeNotifier { void clearDraft() { this._quotedReference = null; this.ctrlCompose.clear(); + this._inviteHandle = null; notifyListeners(); } @@ -49,6 +59,10 @@ class MessageDraft extends ChangeNotifier { ctrlCompose.dispose(); super.dispose(); } + + void clearInvite() { + this._inviteHandle = null; + } } /// A QuotedReference encapsulates the state of replied-to message. diff --git a/lib/views/messageview.dart b/lib/views/messageview.dart index add6e6ac..c5044d9c 100644 --- a/lib/views/messageview.dart +++ b/lib/views/messageview.dart @@ -12,10 +12,12 @@ import 'package:cwtch/models/contact.dart'; import 'package:cwtch/models/message.dart'; import 'package:cwtch/models/message_draft.dart'; import 'package:cwtch/models/messagecache.dart'; +import 'package:cwtch/models/messages/invitemessage.dart'; import 'package:cwtch/models/messages/quotedmessage.dart'; import 'package:cwtch/models/profile.dart'; import 'package:cwtch/themes/opaque.dart'; import 'package:cwtch/third_party/linkify/flutter_linkify.dart'; +import 'package:cwtch/widgets/invitationbubble.dart'; import 'package:cwtch/widgets/malformedbubble.dart'; import 'package:cwtch/widgets/messageloadingbubble.dart'; import 'package:cwtch/widgets/profileimage.dart'; @@ -345,6 +347,11 @@ class _MessageViewState extends State { return; } + var attachedInvite = Provider.of(context, listen: false).messageDraft.getInviteHandle(); + if (attachedInvite != null) { + this._sendInvitation(attachedInvite); + } + // Trim message var messageText = Provider.of(context, listen: false).messageDraft.messageText ?? ""; final messageWithoutNewLine = messageText.trimRight(); @@ -385,10 +392,10 @@ class _MessageViewState extends State { } } - void _sendInvitation([String? ignoredParam]) { + void _sendInvitation(int contact) { Provider.of(context, listen: false) .cwtch - .SendInvitation(Provider.of(context, listen: false).profileOnion, Provider.of(context, listen: false).identifier, this.selectedContact) + .SendInvitation(Provider.of(context, listen: false).profileOnion, Provider.of(context, listen: false).identifier, contact) .then(_sendMessageHandler); } @@ -434,6 +441,27 @@ class _MessageViewState extends State { focusNode.requestFocus(); } + Widget senderInviteChrome(String chrome, String targetName) { + var settings = Provider.of(context); + + return Wrap(children: [ + SelectableText( + chrome + '\u202F', + style: settings.scaleFonts(defaultMessageTextStyle.copyWith(color: Provider.of(context).theme.messageFromMeTextColor)), + textAlign: TextAlign.left, + maxLines: 2, + textWidthBasis: TextWidthBasis.longestLine, + ), + SelectableText( + targetName + '\u202F', + style: settings.scaleFonts(defaultMessageTextStyle.copyWith(color: Provider.of(context).theme.messageFromMeTextColor)), + textAlign: TextAlign.left, + maxLines: 2, + textWidthBasis: TextWidthBasis.longestLine, + ) + ]); + } + Widget _buildPreviewBox() { var showClickableLinks = Provider.of(context).isExperimentEnabled(ClickableLinksExperiment); @@ -686,6 +714,54 @@ class _MessageViewState extends State { Container(color: Provider.of(context).theme.backgroundMainColor, padding: EdgeInsets.all(2), margin: EdgeInsets.all(2), height: 164, child: Column(children: textEditChildren)); var children; + Widget invite = Container(); + if (Provider.of(context).messageDraft.getInviteHandle() != null) { + invite = FutureBuilder( + future: Future.value(Provider.of(context).messageDraft.getInviteHandle()), + builder: (context, snapshot) { + if (snapshot.hasData) { + var contactInvite = snapshot.data! as int; + var contact = Provider.of(context, listen: false).contactList.getContact(contactInvite); + return Container( + margin: EdgeInsets.all(5), + padding: EdgeInsets.all(5), + color: Provider.of(context).theme.messageFromMeBackgroundColor, + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Stack(children: [ + Container( + margin: EdgeInsets.all(5), + padding: EdgeInsets.all(5), + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration(color: Provider.of(context).theme.messageFromMeBackgroundColor), + height: 75, + child: Row(mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.start, children: [ + Padding(padding: EdgeInsets.symmetric(vertical: 5.0, horizontal: 10.0), child: Icon(CwtchIcons.send_invite, size: 32)), + Flexible( + child: DefaultTextStyle( + textWidthBasis: TextWidthBasis.parent, + child: senderInviteChrome("", contact!.nickname), + style: Provider.of(context).scaleFonts(defaultTextStyle), + overflow: TextOverflow.fade, + )) + ])), + Align( + alignment: Alignment.topRight, + child: IconButton( + icon: Icon(Icons.highlight_remove), + splashRadius: Material.defaultSplashRadius / 2, + tooltip: AppLocalizations.of(context)!.tooltipRemoveThisQuotedMessage, + onPressed: () { + Provider.of(context, listen: false).messageDraft.clearInvite(); + setState(() {}); + }, + )), + ]), + ])); + } + return Container(); + }); + } + if (Provider.of(context).selectedConversation != null && Provider.of(context).messageDraft.getQuotedMessage() != null) { var quoted = FutureBuilder( future: messageHandler(context, Provider.of(context).selectedProfile!, Provider.of(context).selectedConversation!, @@ -743,9 +819,9 @@ class _MessageViewState extends State { }, ); - children = [quoted, composeBox]; + children = [invite, quoted, composeBox]; } else { - children = [composeBox]; + children = [invite, composeBox]; } return Container(color: Provider.of(context).theme.backgroundMainColor, child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: children)); @@ -803,9 +879,10 @@ class _MessageViewState extends State { child: Text(AppLocalizations.of(bcontext)!.inviteBtn, semanticsLabel: AppLocalizations.of(bcontext)!.inviteBtn), onPressed: () { if (this.selectedContact != -1) { - this._sendInvitation(); + Provider.of(context, listen: false).messageDraft.attachInvite(this.selectedContact); } Navigator.pop(bcontext); + setState(() {}); }, ), ],