This commit is contained in:
erinn 2021-05-12 16:45:22 -07:00
parent 4cf3b4f6d5
commit 760458931a
6 changed files with 111 additions and 85 deletions

View File

@ -429,7 +429,7 @@ class MessageState extends ChangeNotifier {
} else { } else {
var parts = message['d'].toString().split("||"); var parts = message['d'].toString().split("||");
if (parts.length == 2) { if (parts.length == 2) {
print("jsondecoding: "+utf8.fuse(base64).decode(parts[1].substring(5))); print("jsondecoding: " + utf8.fuse(base64).decode(parts[1].substring(5)));
var jsonObj = jsonDecode(utf8.fuse(base64).decode(parts[1].substring(5))); var jsonObj = jsonDecode(utf8.fuse(base64).decode(parts[1].substring(5)));
this._inviteTarget = jsonObj['GroupID']; this._inviteTarget = jsonObj['GroupID'];
this._inviteNick = jsonObj['GroupName']; this._inviteNick = jsonObj['GroupName'];

View File

@ -81,18 +81,16 @@ class _MessageViewState extends State<MessageView> {
void _sendMessage([String ignoredParam]) { void _sendMessage([String ignoredParam]) {
ChatMessage cm = new ChatMessage(o: 1, d: ctrlrCompose.value.text); ChatMessage cm = new ChatMessage(o: 1, d: ctrlrCompose.value.text);
Provider.of<FlwtchState>(context, listen: false).cwtch.SendMessage( Provider.of<FlwtchState>(context, listen: false)
Provider.of<ContactInfoState>(context, listen: false).profileOnion, .cwtch
Provider.of<ContactInfoState>(context, listen: false).onion, .SendMessage(Provider.of<ContactInfoState>(context, listen: false).profileOnion, Provider.of<ContactInfoState>(context, listen: false).onion, jsonEncode(cm));
jsonEncode(cm));
_sendMessageHelper(); _sendMessageHelper();
} }
void _sendInvitation([String ignoredParam]) { void _sendInvitation([String ignoredParam]) {
Provider.of<FlwtchState>(context, listen: false).cwtch.SendInvitation( Provider.of<FlwtchState>(context, listen: false)
Provider.of<ContactInfoState>(context, listen: false).profileOnion, .cwtch
Provider.of<ContactInfoState>(context, listen: false).onion, .SendInvitation(Provider.of<ContactInfoState>(context, listen: false).profileOnion, Provider.of<ContactInfoState>(context, listen: false).onion, this.selectedContact);
this.selectedContact);
_sendMessageHelper(); _sendMessageHelper();
} }
@ -121,23 +119,25 @@ class _MessageViewState extends State<MessageView> {
textInputAction: TextInputAction.send, textInputAction: TextInputAction.send,
onSubmitted: _sendMessage, onSubmitted: _sendMessage,
)), )),
Column(children:[SizedBox( Column(children: [
width: 100, SizedBox(
height: 50, width: 100,
child: Padding( height: 50,
padding: EdgeInsets.fromLTRB(2, 2, 2, 2), child: Padding(
child: ElevatedButton( padding: EdgeInsets.fromLTRB(2, 2, 2, 2),
child: Icon(Icons.send, size: 24, color: Provider.of<Settings>(context).theme.mainTextColor()), child: ElevatedButton(
style: ButtonStyle( child: Icon(Icons.send, size: 24, color: Provider.of<Settings>(context).theme.mainTextColor()),
fixedSize: MaterialStateProperty.all(Size(86, 50)), style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Provider.of<Settings>(context).theme.defaultButtonColor()), fixedSize: MaterialStateProperty.all(Size(86, 50)),
), backgroundColor: MaterialStateProperty.all(Provider.of<Settings>(context).theme.defaultButtonColor()),
onPressed: _sendMessage, ),
))), onPressed: _sendMessage,
SizedBox( ))),
width: 86, height: 40, SizedBox(
child: IconButton(icon: Icon(Icons.insert_invitation, size: 12, color: Provider.of<Settings>(context).theme.mainTextColor()), onPressed: () => _modalSendInvitation(context)) width: 86,
),]) height: 40,
child: IconButton(icon: Icon(Icons.insert_invitation, size: 12, color: Provider.of<Settings>(context).theme.mainTextColor()), onPressed: () => _modalSendInvitation(context))),
])
], ],
), ),
); );
@ -165,10 +165,16 @@ class _MessageViewState extends State<MessageView> {
SizedBox( SizedBox(
height: 20, height: 20,
), ),
ChangeNotifierProvider.value(value: Provider.of<ProfileInfoState>(ctx, listen: false), child: DropdownContacts(onChanged: (newVal) { ChangeNotifierProvider.value(
setState((){ this.selectedContact = newVal; }); value: Provider.of<ProfileInfoState>(ctx, listen: false),
})), child: DropdownContacts(onChanged: (newVal) {
SizedBox(height: 20,), setState(() {
this.selectedContact = newVal;
});
})),
SizedBox(
height: 20,
),
ElevatedButton( ElevatedButton(
child: Text(AppLocalizations.of(bcontext).inviteBtn, semanticsLabel: AppLocalizations.of(bcontext).inviteBtn), child: Text(AppLocalizations.of(bcontext).inviteBtn, semanticsLabel: AppLocalizations.of(bcontext).inviteBtn),
onPressed: () { onPressed: () {

View File

@ -8,7 +8,9 @@ import '../model.dart';
// Displays nicknames to UI but uses handles as values // Displays nicknames to UI but uses handles as values
// Pass an onChanged handler to access value // Pass an onChanged handler to access value
class DropdownContacts extends StatefulWidget { class DropdownContacts extends StatefulWidget {
DropdownContacts({this.onChanged,}); DropdownContacts({
this.onChanged,
});
final Function(dynamic) onChanged; final Function(dynamic) onChanged;
@override @override
@ -20,15 +22,18 @@ class _DropdownContactsState extends State<DropdownContacts> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DropdownButton(value: this.selected, items: Provider.of<ProfileInfoState>(context, listen: false).contactList.contacts.map<DropdownMenuItem<String>>((ContactInfoState contact) { return DropdownButton(
return DropdownMenuItem<String>(value: contact.onion, child: Text(contact.nickname??contact.onion)); value: this.selected,
}).toList(), onChanged: (newVal) { items: Provider.of<ProfileInfoState>(context, listen: false).contactList.contacts.map<DropdownMenuItem<String>>((ContactInfoState contact) {
setState(() { return DropdownMenuItem<String>(value: contact.onion, child: Text(contact.nickname ?? contact.onion));
this.selected = newVal; }).toList(),
}); onChanged: (newVal) {
if (widget.onChanged != null) { setState(() {
widget.onChanged(newVal); this.selected = newVal;
} });
}); if (widget.onChanged != null) {
widget.onChanged(newVal);
}
});
} }
} }

View File

@ -43,27 +43,33 @@ class InvitationBubbleState extends State<InvitationBubble> {
senderDisplayStr = contact.nickname ?? contact.onion; senderDisplayStr = contact.nickname ?? contact.onion;
} }
} }
var wdgSender = Center(widthFactor:1, child: SelectableText(senderDisplayStr + '\u202F', var wdgSender = Center(
style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor() : Provider.of<Settings>(context).theme.messageFromOtherTextColor()))); widthFactor: 1,
child: SelectableText(senderDisplayStr + '\u202F',
style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor() : Provider.of<Settings>(context).theme.messageFromOtherTextColor())));
// todo: translations // todo: translations
var messageStr = ""; var messageStr = "";
if (fromMe) { if (fromMe) {
//todo: get group name? //todo: get group name?
messageStr = "You sent an invitation for "+(isGroup ? "a group" : Provider.of<MessageState>(context).message ?? ""); messageStr = "You sent an invitation for " + (isGroup ? "a group" : Provider.of<MessageState>(context).message ?? "");
} else { } else {
messageStr = (isGroup ? "You have been invited to join "+(Provider.of<MessageState>(context).inviteNick??"") : "This is a contact suggestion for:") + "\n" + (Provider.of<MessageState>(context).inviteTarget ?? ""); messageStr = (isGroup ? "You have been invited to join " + (Provider.of<MessageState>(context).inviteNick ?? "") : "This is a contact suggestion for:") +
"\n" +
(Provider.of<MessageState>(context).inviteTarget ?? "");
} }
var wdgMessage = Center(widthFactor:1, child: SelectableText( var wdgMessage = Center(
messageStr + '\u202F', widthFactor: 1,
key: Key(myKey), child: SelectableText(
focusNode: _focus, messageStr + '\u202F',
style: TextStyle( key: Key(myKey),
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor() : Provider.of<Settings>(context).theme.messageFromOtherTextColor(), focusNode: _focus,
), style: TextStyle(
textAlign: TextAlign.left, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor() : Provider.of<Settings>(context).theme.messageFromOtherTextColor(),
textWidthBasis: TextWidthBasis.longestLine, ),
)); textAlign: TextAlign.left,
textWidthBasis: TextWidthBasis.longestLine,
));
Widget wdgDecorations; Widget wdgDecorations;
if (fromMe) { if (fromMe) {
@ -72,15 +78,14 @@ class InvitationBubbleState extends State<InvitationBubble> {
child: Row( child: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text(prettyDate, style: TextStyle( Text(prettyDate,
fontSize: 9.0, style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor() : Provider.of<Settings>(context).theme.messageFromOtherTextColor()),
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor() : Provider.of<Settings>(context).theme.messageFromOtherTextColor() textAlign: fromMe ? TextAlign.right : TextAlign.left),
), textAlign: fromMe ? TextAlign.right : TextAlign.left),
!fromMe !fromMe
? SizedBox(width: 1, height: 1) ? SizedBox(width: 1, height: 1)
: Provider.of<MessageState>(context).ackd : Provider.of<MessageState>(context).ackd
? Icon(Icons.check_circle_outline, color: Provider.of<Settings>(context).theme.messageFromMeTextColor(), size: 12) ? Icon(Icons.check_circle_outline, color: Provider.of<Settings>(context).theme.messageFromMeTextColor(), size: 12)
: Icon(Icons.hourglass_bottom_outlined, color: Provider.of<Settings>(context).theme.messageFromMeTextColor(), size: 12) : Icon(Icons.hourglass_bottom_outlined, color: Provider.of<Settings>(context).theme.messageFromMeTextColor(), size: 12)
], ],
)); ));
} else if (isAccepted) { } else if (isAccepted) {
@ -88,10 +93,12 @@ class InvitationBubbleState extends State<InvitationBubble> {
} else if (this.rejected) { } else if (this.rejected) {
wdgDecorations = Text("Rejected."); wdgDecorations = Text("Rejected.");
} else { } else {
wdgDecorations = Center(widthFactor:1,child:Row(children: [ wdgDecorations = Center(
Padding(padding: EdgeInsets.all(5), child: TextButton(child: Text("Reject"), onPressed: _btnReject)), widthFactor: 1,
Padding(padding: EdgeInsets.all(5), child: TextButton(child: Text("Accept"), onPressed: _btnAccept)), child: Row(children: [
])); Padding(padding: EdgeInsets.all(5), child: TextButton(child: Text("Reject"), onPressed: _btnReject)),
Padding(padding: EdgeInsets.all(5), child: TextButton(child: Text("Accept"), onPressed: _btnAccept)),
]));
} }
return LayoutBuilder(builder: (context, constraints) { return LayoutBuilder(builder: (context, constraints) {
@ -110,21 +117,26 @@ class InvitationBubbleState extends State<InvitationBubble> {
bottomRight: fromMe ? Radius.zero : Radius.circular(borderRadiousEh), bottomRight: fromMe ? Radius.zero : Radius.circular(borderRadiousEh),
), ),
), ),
child: Center(widthFactor: 1.0,child:Padding( child: Center(
padding: EdgeInsets.all(9.0), widthFactor: 1.0,
child: Row(mainAxisSize: MainAxisSize.min, children: [Center(widthFactor: 1,child: Padding(padding:EdgeInsets.all(4), child:Icon(Icons.group_add, size: 32))), child: Padding(
Center(widthFactor: 1.0,child: Column( padding: EdgeInsets.all(9.0),
crossAxisAlignment: fromMe ? CrossAxisAlignment.end : CrossAxisAlignment.start, child: Row(mainAxisSize: MainAxisSize.min, children: [
mainAxisAlignment: fromMe ? MainAxisAlignment.end : MainAxisAlignment.start, Center(widthFactor: 1, child: Padding(padding: EdgeInsets.all(4), child: Icon(Icons.group_add, size: 32))),
mainAxisSize: MainAxisSize.min, Center(
children: fromMe ? [wdgMessage, wdgDecorations] : [wdgSender, wdgMessage, wdgDecorations])), widthFactor: 1.0,
]))))); child: Column(
crossAxisAlignment: fromMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
mainAxisAlignment: fromMe ? MainAxisAlignment.end : MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: fromMe ? [wdgMessage, wdgDecorations] : [wdgSender, wdgMessage, wdgDecorations])),
])))));
}); });
} }
void _btnReject() { void _btnReject() {
//todo: how should we track inline invite rejections? //todo: how should we track inline invite rejections?
setState(()=>this.rejected = true); setState(() => this.rejected = true);
} }
void _btnAccept() { void _btnAccept() {

View File

@ -13,6 +13,6 @@ class MessageLoadingBubble extends StatefulWidget {
class MessageLoadingBubbleState extends State<MessageLoadingBubble> { class MessageLoadingBubbleState extends State<MessageLoadingBubble> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Center(child:Row(children:[SizedBox(width:40, height:100, child: Text(""))])); return Center(child: Row(children: [SizedBox(width: 40, height: 100, child: Text(""))]));
} }
} }

View File

@ -24,7 +24,8 @@ class _MessageRowState extends State<MessageRow> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
var fromMe = Provider.of<MessageState>(context).senderOnion == Provider.of<ProfileInfoState>(context).onion; var fromMe = Provider.of<MessageState>(context).senderOnion == Provider.of<ProfileInfoState>(context).onion;
Widget wdgBubble = Flexible(flex: 3, fit: FlexFit.loose, child: Provider.of<MessageState>(context).loaded == true ? widgetForOverlay(Provider.of<MessageState>(context).overlay) : MessageLoadingBubble()); Widget wdgBubble =
Flexible(flex: 3, fit: FlexFit.loose, child: Provider.of<MessageState>(context).loaded == true ? widgetForOverlay(Provider.of<MessageState>(context).overlay) : MessageLoadingBubble());
Widget wdgIcons = Icon(Icons.delete_forever_outlined, color: Provider.of<Settings>(context).theme.dropShadowColor()); Widget wdgIcons = Icon(Icons.delete_forever_outlined, color: Provider.of<Settings>(context).theme.dropShadowColor());
Widget wdgSpacer = Expanded(child: SizedBox(width: 60, height: 10)); Widget wdgSpacer = Expanded(child: SizedBox(width: 60, height: 10));
var widgetRow = <Widget>[]; var widgetRow = <Widget>[];
@ -38,12 +39,12 @@ class _MessageRowState extends State<MessageRow> {
} else { } else {
var contact = Provider.of<ContactInfoState>(context); var contact = Provider.of<ContactInfoState>(context);
Widget wdgPortrait = GestureDetector( Widget wdgPortrait = GestureDetector(
onTap: _btnAdd, onTap: _btnAdd,
child: ProfileImage( child: ProfileImage(
diameter: 48.0, diameter: 48.0,
imagePath: Provider.of<MessageState>(context).senderImage ?? contact.imagePath, imagePath: Provider.of<MessageState>(context).senderImage ?? contact.imagePath,
//maskOut: contact.status != "Authenticated", //maskOut: contact.status != "Authenticated",
border: contact.status == "Authenticated" ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor())); border: contact.status == "Authenticated" ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor()));
widgetRow = <Widget>[ widgetRow = <Widget>[
wdgPortrait, wdgPortrait,
@ -58,9 +59,11 @@ class _MessageRowState extends State<MessageRow> {
Widget widgetForOverlay(int o) { Widget widgetForOverlay(int o) {
switch (o) { switch (o) {
case 1: return MessageBubble(); case 1:
return MessageBubble();
case 100: case 100:
case 101: return InvitationBubble(); case 101:
return InvitationBubble();
} }
return null; return null;
} }