Merge pull request 'Support New Groups' (#68) from groups into trunk
continuous-integration/drone/push Build was killed
Details
continuous-integration/drone/push Build was killed
Details
Reviewed-on: #68
This commit is contained in:
commit
2c9cd7f111
|
@ -62,20 +62,42 @@ class CwtchNotifier {
|
|||
profileCN.getProfile(data["ProfileOnion"]).contactList.getContact(data["RemotePeer"]).totalMessages++;
|
||||
profileCN.getProfile(data["ProfileOnion"]).contactList.updateLastMessageTime(data["RemotePeer"], DateTime.now());
|
||||
break;
|
||||
case "PeerAcknowledgement":
|
||||
// We don't use these anymore, IndexedAcknowledgement is more suited to the UI front end...
|
||||
break;
|
||||
case "IndexedAcknowledgement":
|
||||
var idx = int.parse(data["Index"]);
|
||||
if (idx < 0) break;
|
||||
var idx = data["Index"];
|
||||
// We return -1 for protocol message acks if there is no message
|
||||
if (idx == "-1") break;
|
||||
var key = profileCN.getProfile(data["ProfileOnion"]).contactList.getContact(data["RemotePeer"]).getMessageKey(idx);
|
||||
if (key == null) break;
|
||||
Provider.of<MessageState>(key.currentContext, listen: false).ackd = true;
|
||||
try {
|
||||
var message = Provider.of<MessageState>(key.currentContext, listen: false);
|
||||
if (message == null) break;
|
||||
message.ackd = true;
|
||||
} catch (e) {
|
||||
// ignore, we received an ack for a message that hasn't loaded onto the screen yet...
|
||||
// the protocol was faster than the ui....yay?
|
||||
}
|
||||
break;
|
||||
case "NewMessageFromGroup":
|
||||
if (data["ProfileOnion"] != data["RemotePeer"]) {//not from me
|
||||
if (data["ProfileOnion"] != data["RemotePeer"]) {
|
||||
//not from me
|
||||
profileCN.getProfile(data["ProfileOnion"]).contactList.getContact(data["GroupID"]).unreadMessages++;
|
||||
profileCN.getProfile(data["ProfileOnion"]).contactList.getContact(data["GroupID"]).totalMessages++;
|
||||
profileCN.getProfile(data["ProfileOnion"]).contactList.updateLastMessageTime(data["GroupID"], DateTime.now());
|
||||
} else {// from me (already displayed - do not update counter)
|
||||
//todo: update ack - once group messages
|
||||
} else {
|
||||
// from me (already displayed - do not update counter)
|
||||
var idx = data["Signature"];
|
||||
var key = profileCN.getProfile(data["ProfileOnion"]).contactList.getContact(data["GroupID"]).getMessageKey(idx);
|
||||
if (key == null) break;
|
||||
try {
|
||||
var message = Provider.of<MessageState>(key.currentContext, listen: false);
|
||||
if (message == null) break;
|
||||
message.ackd = true;
|
||||
} catch (e) {
|
||||
// ignore, we likely have an old key that has been replaced with an actual signature
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "AppError":
|
||||
|
@ -103,12 +125,19 @@ class CwtchNotifier {
|
|||
case "UpdateServerInfo":
|
||||
profileCN.getProfile(data["ProfileOnion"]).replaceServers(data["ServerList"]);
|
||||
break;
|
||||
case "NewGroupInvite":
|
||||
case "NewGroup":
|
||||
print("new group invite: $data");
|
||||
dynamic groupInvite = jsonDecode(data["GroupInvite"]);
|
||||
profileCN.getProfile(data["ProfileOnion"]).contactList.add(ContactInfoState(data["ProfileOnion"], groupInvite["GroupID"],
|
||||
isInvitation: true, imagePath: data["PicturePath"], nickname: groupInvite["GroupName"], server: groupInvite["ServerHost"], isGroup: true, lastMessageTime: DateTime.now()));
|
||||
profileCN.getProfile(data["ProfileOnion"]).contactList.updateLastMessageTime(groupInvite["GroupID"], DateTime.now());
|
||||
String invite = data["GroupInvite"].toString();
|
||||
if (invite.startsWith("torv3")) {
|
||||
String inviteJson = new String.fromCharCodes(base64Decode(invite.substring(5)));
|
||||
dynamic groupInvite = jsonDecode(inviteJson);
|
||||
print("new group invite: $groupInvite");
|
||||
if (profileCN.getProfile(data["ProfileOnion"]).contactList.getContact(groupInvite["GroupID"]) == null) {
|
||||
profileCN.getProfile(data["ProfileOnion"]).contactList.add(ContactInfoState(data["ProfileOnion"], groupInvite["GroupID"],
|
||||
isInvitation: true, imagePath: data["PicturePath"], nickname: groupInvite["GroupName"], server: groupInvite["ServerHost"], isGroup: true, lastMessageTime: DateTime.now()));
|
||||
profileCN.getProfile(data["ProfileOnion"]).contactList.updateLastMessageTime(groupInvite["GroupID"], DateTime.now());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "AcceptGroupInvite":
|
||||
print("accept group invite: $data");
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -41,7 +40,7 @@ class DiskAssetBundle extends CachingAssetBundle {
|
|||
for (final pattern in globs) {
|
||||
await for (final path in Glob(pattern).list(root: from)) {
|
||||
if (path is File) {
|
||||
final bytes = await (path as File).readAsBytes()/* as Uint8List*/;
|
||||
final bytes = await (path as File).readAsBytes() /* as Uint8List*/;
|
||||
cache[path.path] = ByteData.view(bytes.buffer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -233,7 +233,7 @@ class ContactInfoState extends ChangeNotifier {
|
|||
int _unreadMessages = 0;
|
||||
int _totalMessages = 0;
|
||||
DateTime _lastMessageTime;
|
||||
Map<int, GlobalKey> keys;
|
||||
Map<String, GlobalKey> keys;
|
||||
|
||||
// todo: a nicer way to model contacts, groups and other "entities"
|
||||
bool _isGroup;
|
||||
|
@ -265,7 +265,7 @@ class ContactInfoState extends ChangeNotifier {
|
|||
this._savePeerHistory = savePeerHistory;
|
||||
this._lastMessageTime = lastMessageTime;
|
||||
this._server = server;
|
||||
keys = Map<int, GlobalKey>();
|
||||
keys = Map<String, GlobalKey>();
|
||||
}
|
||||
|
||||
get nickname => this._nickname;
|
||||
|
@ -340,7 +340,7 @@ class ContactInfoState extends ChangeNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
GlobalKey<MessageBubbleState> getMessageKey(int index) {
|
||||
GlobalKey<MessageBubbleState> getMessageKey(String index) {
|
||||
if (keys[index] == null) {
|
||||
keys[index] = GlobalKey<MessageBubbleState>();
|
||||
}
|
||||
|
@ -356,6 +356,7 @@ class MessageState extends ChangeNotifier {
|
|||
DateTime _timestamp;
|
||||
String _senderOnion;
|
||||
String _senderImage;
|
||||
String _signature = "";
|
||||
bool _ackd = false;
|
||||
bool _loaded = false;
|
||||
|
||||
|
@ -374,6 +375,7 @@ class MessageState extends ChangeNotifier {
|
|||
get senderOnion => this._senderOnion;
|
||||
get senderImage => this._senderImage;
|
||||
get loaded => this._loaded;
|
||||
get signature => this._signature;
|
||||
|
||||
set ackd(bool newVal) {
|
||||
this._ackd = newVal;
|
||||
|
@ -397,6 +399,12 @@ class MessageState extends ChangeNotifier {
|
|||
this._timestamp = DateTime.tryParse(messageWrapper['Timestamp']);
|
||||
this._senderOnion = messageWrapper['PeerID'];
|
||||
this._senderImage = messageWrapper['ContactImage'];
|
||||
|
||||
// If this is a group, store the signature
|
||||
if (contactHandle.length == 32) {
|
||||
this._signature = messageWrapper['Signature'];
|
||||
}
|
||||
|
||||
this._loaded = true;
|
||||
//update ackd last as it's changenotified
|
||||
this._ackd = messageWrapper['Acknowledged'];
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/widgets/contactrow.dart';
|
||||
import 'package:flutter_app/widgets/profileimage.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../settings.dart';
|
||||
import 'addcontactview.dart';
|
||||
import '../model.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
@ -17,7 +19,21 @@ class _ContactsViewState extends State<ContactsView> {
|
|||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text("%1's contacts".replaceAll("%1", Provider.of<ProfileInfoState>(context).nickname ?? Provider.of<ProfileInfoState>(context).onion ?? '')), //todo
|
||||
title: Row(children: [
|
||||
ProfileImage(
|
||||
imagePath: Provider.of<ProfileInfoState>(context).imagePath,
|
||||
diameter: 42,
|
||||
border: Provider.of<Settings>(context).theme.portraitOnlineBorderColor(),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"%1 » %2".replaceAll("%1", Provider.of<ProfileInfoState>(context).nickname ?? Provider.of<ProfileInfoState>(context).onion ?? '').replaceAll("%2", "Contacts"),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
)), //todo
|
||||
]),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: Icon(Icons.copy),
|
||||
|
|
|
@ -51,10 +51,10 @@ class MessageBubbleState extends State<MessageBubble> {
|
|||
),
|
||||
textAlign: fromMe ? TextAlign.right : TextAlign.left),
|
||||
!fromMe
|
||||
? SizedBox(width:1,height:1)
|
||||
? SizedBox(width: 1, height: 1)
|
||||
: Provider.of<MessageState>(context).ackd
|
||||
? 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.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)
|
||||
],
|
||||
));
|
||||
|
||||
|
|
|
@ -49,7 +49,9 @@ class _MessageListState extends State<MessageList> {
|
|||
child: Container(
|
||||
// Only show broken heart is the contact is offline...
|
||||
decoration: BoxDecoration(
|
||||
image: Provider.of<ContactInfoState>(outerContext).isOnline() ? null : DecorationImage(
|
||||
image: Provider.of<ContactInfoState>(outerContext).isOnline()
|
||||
? null
|
||||
: DecorationImage(
|
||||
fit: BoxFit.contain,
|
||||
image: AssetImage("assets/core/negative_heart_512px.png"),
|
||||
colorFilter: ColorFilter.mode(Provider.of<Settings>(context).theme.mainTextColor(), BlendMode.srcIn))),
|
||||
|
@ -64,7 +66,12 @@ class _MessageListState extends State<MessageList> {
|
|||
contactHandle: Provider.of<ContactInfoState>(outerContext).onion,
|
||||
messageIndex: index,
|
||||
),
|
||||
child: MessageRow(key: Provider.of<ContactInfoState>(outerContext).getMessageKey(index)));
|
||||
builder: (bcontext, child) {
|
||||
String idx = Provider.of<ContactInfoState>(outerContext).isGroup == true && Provider.of<MessageState>(bcontext).signature.isEmpty == false
|
||||
? Provider.of<MessageState>(bcontext).signature
|
||||
: index.toString();
|
||||
return MessageRow(key: Provider.of<ContactInfoState>(bcontext).getMessageKey(idx));
|
||||
});
|
||||
},
|
||||
),
|
||||
)));
|
||||
|
|
|
@ -7,7 +7,7 @@ import '../settings.dart';
|
|||
import 'messagebubble.dart';
|
||||
|
||||
class MessageRow extends StatefulWidget {
|
||||
MessageRow({Key key}): super(key: key);
|
||||
MessageRow({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_MessageRowState createState() => _MessageRowState();
|
||||
|
|
Loading…
Reference in New Issue