mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2024-12-25 23:59:32 -05:00
switch to smpl key
This commit is contained in:
parent
e68cbb26eb
commit
ee80dbf3a5
@ -1,6 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_chat_types/flutter_chat_types.dart' as types;
|
import 'package:flutter_chat_types/flutter_chat_types.dart' as types;
|
||||||
import 'package:flutter_chat_ui/flutter_chat_ui.dart';
|
import 'package:flutter_chat_ui/flutter_chat_ui.dart';
|
||||||
@ -61,13 +60,13 @@ class ChatComponentState extends ConsumerState<ChatComponent> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadMessages() async {
|
Future<void> _loadMessages() async {
|
||||||
final localConversationOwned = proto.OwnedDHTRecordPointerProto.fromProto(
|
final localConversationRecordKey = proto.TypedKeyProto.fromProto(
|
||||||
widget.activeChatContact.localConversation);
|
widget.activeChatContact.localConversationRecordKey);
|
||||||
final remoteIdentityPublicKey = proto.TypedKeyProto.fromProto(
|
final remoteIdentityPublicKey = proto.TypedKeyProto.fromProto(
|
||||||
widget.activeChatContact.identityPublicKey);
|
widget.activeChatContact.identityPublicKey);
|
||||||
final protoMessages = await getLocalConversationMessages(
|
final protoMessages = await getLocalConversationMessages(
|
||||||
activeAccountInfo: widget.activeAccountInfo,
|
activeAccountInfo: widget.activeAccountInfo,
|
||||||
localConversationOwned: localConversationOwned,
|
localConversationRecordKey: localConversationRecordKey,
|
||||||
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
||||||
if (protoMessages == null) {
|
if (protoMessages == null) {
|
||||||
return;
|
return;
|
||||||
@ -108,14 +107,14 @@ class ChatComponentState extends ConsumerState<ChatComponent> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Now add the message to the conversation messages
|
// Now add the message to the conversation messages
|
||||||
final localConversationOwned = proto.OwnedDHTRecordPointerProto.fromProto(
|
final localConversationRecordKey = proto.TypedKeyProto.fromProto(
|
||||||
widget.activeChatContact.localConversation);
|
widget.activeChatContact.localConversationRecordKey);
|
||||||
final remoteIdentityPublicKey = proto.TypedKeyProto.fromProto(
|
final remoteIdentityPublicKey = proto.TypedKeyProto.fromProto(
|
||||||
widget.activeChatContact.identityPublicKey);
|
widget.activeChatContact.identityPublicKey);
|
||||||
|
|
||||||
await addLocalConversationMessage(
|
await addLocalConversationMessage(
|
||||||
activeAccountInfo: widget.activeAccountInfo,
|
activeAccountInfo: widget.activeAccountInfo,
|
||||||
localConversationOwned: localConversationOwned,
|
localConversationRecordKey: localConversationRecordKey,
|
||||||
remoteIdentityPublicKey: remoteIdentityPublicKey,
|
remoteIdentityPublicKey: remoteIdentityPublicKey,
|
||||||
message: protoMessage);
|
message: protoMessage);
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,9 @@ class ChatSingleContactItemWidget extends ConsumerWidget {
|
|||||||
final scale = theme.extension<ScaleScheme>()!;
|
final scale = theme.extension<ScaleScheme>()!;
|
||||||
|
|
||||||
final activeChat = ref.watch(activeChatStateProvider).asData?.value;
|
final activeChat = ref.watch(activeChatStateProvider).asData?.value;
|
||||||
final selected = activeChat ==
|
final remoteConversationRecordKey =
|
||||||
proto.TypedKeyProto.fromProto(contact.remoteConversationKey);
|
proto.TypedKeyProto.fromProto(contact.remoteConversationRecordKey);
|
||||||
|
final selected = activeChat == remoteConversationRecordKey;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
margin: const EdgeInsets.fromLTRB(4, 4, 4, 0),
|
margin: const EdgeInsets.fromLTRB(4, 4, 4, 0),
|
||||||
@ -47,8 +48,7 @@ class ChatSingleContactItemWidget extends ConsumerWidget {
|
|||||||
await deleteChat(
|
await deleteChat(
|
||||||
activeAccountInfo: activeAccountInfo,
|
activeAccountInfo: activeAccountInfo,
|
||||||
remoteConversationRecordKey:
|
remoteConversationRecordKey:
|
||||||
proto.TypedKeyProto.fromProto(
|
remoteConversationRecordKey);
|
||||||
contact.remoteConversationKey));
|
|
||||||
ref.invalidate(fetchChatListProvider);
|
ref.invalidate(fetchChatListProvider);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -71,8 +71,7 @@ class ChatSingleContactItemWidget extends ConsumerWidget {
|
|||||||
// component is not dragged.
|
// component is not dragged.
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
activeChatState.add(proto.TypedKeyProto.fromProto(
|
activeChatState.add(remoteConversationRecordKey);
|
||||||
contact.remoteConversationKey));
|
|
||||||
ref.invalidate(fetchChatListProvider);
|
ref.invalidate(fetchChatListProvider);
|
||||||
},
|
},
|
||||||
title: Text(contact.editedProfile.name),
|
title: Text(contact.editedProfile.name),
|
||||||
|
@ -19,7 +19,8 @@ class ChatSingleContactListWidget extends ConsumerWidget {
|
|||||||
required this.chatList,
|
required this.chatList,
|
||||||
super.key})
|
super.key})
|
||||||
: contactMap = IMap.fromIterable(contactList,
|
: contactMap = IMap.fromIterable(contactList,
|
||||||
keyMapper: (c) => c.remoteConversationKey, valueMapper: (c) => c);
|
keyMapper: (c) => c.remoteConversationRecordKey,
|
||||||
|
valueMapper: (c) => c);
|
||||||
|
|
||||||
final IMap<proto.TypedKey, proto.Contact> contactMap;
|
final IMap<proto.TypedKey, proto.Contact> contactMap;
|
||||||
final IList<proto.Chat> chatList;
|
final IList<proto.Chat> chatList;
|
||||||
|
@ -24,7 +24,7 @@ class ContactItemWidget extends ConsumerWidget {
|
|||||||
final scale = theme.extension<ScaleScheme>()!;
|
final scale = theme.extension<ScaleScheme>()!;
|
||||||
|
|
||||||
final remoteConversationKey =
|
final remoteConversationKey =
|
||||||
proto.TypedKeyProto.fromProto(contact.remoteConversationKey);
|
proto.TypedKeyProto.fromProto(contact.remoteConversationRecordKey);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
margin: const EdgeInsets.fromLTRB(4, 4, 4, 0),
|
margin: const EdgeInsets.fromLTRB(4, 4, 4, 0),
|
||||||
@ -80,8 +80,12 @@ class ContactItemWidget extends ConsumerWidget {
|
|||||||
remoteConversationRecordKey: remoteConversationKey);
|
remoteConversationRecordKey: remoteConversationKey);
|
||||||
|
|
||||||
// Click over to chats
|
// Click over to chats
|
||||||
await MainPager.of(context)?.pageController.animateToPage(1,
|
if (context.mounted) {
|
||||||
duration: 250.ms, curve: Curves.easeInOut);
|
await MainPager.of(context)?.pageController.animateToPage(
|
||||||
|
1,
|
||||||
|
duration: 250.ms,
|
||||||
|
curve: Curves.easeInOut);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// // ignore: use_build_context_synchronously
|
// // ignore: use_build_context_synchronously
|
||||||
|
@ -116,8 +116,10 @@ class PasteInviteDialogState extends ConsumerState<PasteInviteDialog> {
|
|||||||
activeAccountInfo: activeAccountInfo,
|
activeAccountInfo: activeAccountInfo,
|
||||||
profile: acceptedContact.profile,
|
profile: acceptedContact.profile,
|
||||||
remoteIdentity: acceptedContact.remoteIdentity,
|
remoteIdentity: acceptedContact.remoteIdentity,
|
||||||
remoteConversationKey: acceptedContact.remoteConversationKey,
|
remoteConversationRecordKey:
|
||||||
localConversation: acceptedContact.localConversation,
|
acceptedContact.remoteConversationRecordKey,
|
||||||
|
localConversationRecordKey:
|
||||||
|
acceptedContact.localConversationRecordKey,
|
||||||
);
|
);
|
||||||
ref
|
ref
|
||||||
..invalidate(fetchContactInvitationRecordsProvider)
|
..invalidate(fetchContactInvitationRecordsProvider)
|
||||||
|
@ -1000,8 +1000,8 @@ class Contact extends $pb.GeneratedMessage {
|
|||||||
..aOM<Profile>(2, _omitFieldNames ? '' : 'remoteProfile', subBuilder: Profile.create)
|
..aOM<Profile>(2, _omitFieldNames ? '' : 'remoteProfile', subBuilder: Profile.create)
|
||||||
..aOS(3, _omitFieldNames ? '' : 'identityMasterJson')
|
..aOS(3, _omitFieldNames ? '' : 'identityMasterJson')
|
||||||
..aOM<TypedKey>(4, _omitFieldNames ? '' : 'identityPublicKey', subBuilder: TypedKey.create)
|
..aOM<TypedKey>(4, _omitFieldNames ? '' : 'identityPublicKey', subBuilder: TypedKey.create)
|
||||||
..aOM<TypedKey>(5, _omitFieldNames ? '' : 'remoteConversationKey', subBuilder: TypedKey.create)
|
..aOM<TypedKey>(5, _omitFieldNames ? '' : 'remoteConversationRecordKey', subBuilder: TypedKey.create)
|
||||||
..aOM<OwnedDHTRecordPointer>(6, _omitFieldNames ? '' : 'localConversation', subBuilder: OwnedDHTRecordPointer.create)
|
..aOM<TypedKey>(6, _omitFieldNames ? '' : 'localConversationRecordKey', subBuilder: TypedKey.create)
|
||||||
..aOB(7, _omitFieldNames ? '' : 'showAvailability')
|
..aOB(7, _omitFieldNames ? '' : 'showAvailability')
|
||||||
..hasRequiredFields = false
|
..hasRequiredFields = false
|
||||||
;
|
;
|
||||||
@ -1070,26 +1070,26 @@ class Contact extends $pb.GeneratedMessage {
|
|||||||
TypedKey ensureIdentityPublicKey() => $_ensure(3);
|
TypedKey ensureIdentityPublicKey() => $_ensure(3);
|
||||||
|
|
||||||
@$pb.TagNumber(5)
|
@$pb.TagNumber(5)
|
||||||
TypedKey get remoteConversationKey => $_getN(4);
|
TypedKey get remoteConversationRecordKey => $_getN(4);
|
||||||
@$pb.TagNumber(5)
|
@$pb.TagNumber(5)
|
||||||
set remoteConversationKey(TypedKey v) { setField(5, v); }
|
set remoteConversationRecordKey(TypedKey v) { setField(5, v); }
|
||||||
@$pb.TagNumber(5)
|
@$pb.TagNumber(5)
|
||||||
$core.bool hasRemoteConversationKey() => $_has(4);
|
$core.bool hasRemoteConversationRecordKey() => $_has(4);
|
||||||
@$pb.TagNumber(5)
|
@$pb.TagNumber(5)
|
||||||
void clearRemoteConversationKey() => clearField(5);
|
void clearRemoteConversationRecordKey() => clearField(5);
|
||||||
@$pb.TagNumber(5)
|
@$pb.TagNumber(5)
|
||||||
TypedKey ensureRemoteConversationKey() => $_ensure(4);
|
TypedKey ensureRemoteConversationRecordKey() => $_ensure(4);
|
||||||
|
|
||||||
@$pb.TagNumber(6)
|
@$pb.TagNumber(6)
|
||||||
OwnedDHTRecordPointer get localConversation => $_getN(5);
|
TypedKey get localConversationRecordKey => $_getN(5);
|
||||||
@$pb.TagNumber(6)
|
@$pb.TagNumber(6)
|
||||||
set localConversation(OwnedDHTRecordPointer v) { setField(6, v); }
|
set localConversationRecordKey(TypedKey v) { setField(6, v); }
|
||||||
@$pb.TagNumber(6)
|
@$pb.TagNumber(6)
|
||||||
$core.bool hasLocalConversation() => $_has(5);
|
$core.bool hasLocalConversationRecordKey() => $_has(5);
|
||||||
@$pb.TagNumber(6)
|
@$pb.TagNumber(6)
|
||||||
void clearLocalConversation() => clearField(6);
|
void clearLocalConversationRecordKey() => clearField(6);
|
||||||
@$pb.TagNumber(6)
|
@$pb.TagNumber(6)
|
||||||
OwnedDHTRecordPointer ensureLocalConversation() => $_ensure(5);
|
TypedKey ensureLocalConversationRecordKey() => $_ensure(5);
|
||||||
|
|
||||||
@$pb.TagNumber(7)
|
@$pb.TagNumber(7)
|
||||||
$core.bool get showAvailability => $_getBF(6);
|
$core.bool get showAvailability => $_getBF(6);
|
||||||
@ -1654,7 +1654,7 @@ class ContactResponse extends $pb.GeneratedMessage {
|
|||||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ContactResponse', createEmptyInstance: create)
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ContactResponse', createEmptyInstance: create)
|
||||||
..aOB(1, _omitFieldNames ? '' : 'accept')
|
..aOB(1, _omitFieldNames ? '' : 'accept')
|
||||||
..aOM<TypedKey>(2, _omitFieldNames ? '' : 'identityMasterRecordKey', subBuilder: TypedKey.create)
|
..aOM<TypedKey>(2, _omitFieldNames ? '' : 'identityMasterRecordKey', subBuilder: TypedKey.create)
|
||||||
..aOM<TypedKey>(3, _omitFieldNames ? '' : 'remoteConversationKey', subBuilder: TypedKey.create)
|
..aOM<TypedKey>(3, _omitFieldNames ? '' : 'remoteConversationRecordKey', subBuilder: TypedKey.create)
|
||||||
..hasRequiredFields = false
|
..hasRequiredFields = false
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -1700,15 +1700,15 @@ class ContactResponse extends $pb.GeneratedMessage {
|
|||||||
TypedKey ensureIdentityMasterRecordKey() => $_ensure(1);
|
TypedKey ensureIdentityMasterRecordKey() => $_ensure(1);
|
||||||
|
|
||||||
@$pb.TagNumber(3)
|
@$pb.TagNumber(3)
|
||||||
TypedKey get remoteConversationKey => $_getN(2);
|
TypedKey get remoteConversationRecordKey => $_getN(2);
|
||||||
@$pb.TagNumber(3)
|
@$pb.TagNumber(3)
|
||||||
set remoteConversationKey(TypedKey v) { setField(3, v); }
|
set remoteConversationRecordKey(TypedKey v) { setField(3, v); }
|
||||||
@$pb.TagNumber(3)
|
@$pb.TagNumber(3)
|
||||||
$core.bool hasRemoteConversationKey() => $_has(2);
|
$core.bool hasRemoteConversationRecordKey() => $_has(2);
|
||||||
@$pb.TagNumber(3)
|
@$pb.TagNumber(3)
|
||||||
void clearRemoteConversationKey() => clearField(3);
|
void clearRemoteConversationRecordKey() => clearField(3);
|
||||||
@$pb.TagNumber(3)
|
@$pb.TagNumber(3)
|
||||||
TypedKey ensureRemoteConversationKey() => $_ensure(2);
|
TypedKey ensureRemoteConversationRecordKey() => $_ensure(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
class SignedContactResponse extends $pb.GeneratedMessage {
|
class SignedContactResponse extends $pb.GeneratedMessage {
|
||||||
@ -1775,7 +1775,7 @@ class ContactInvitationRecord extends $pb.GeneratedMessage {
|
|||||||
..aOM<OwnedDHTRecordPointer>(1, _omitFieldNames ? '' : 'contactRequestInbox', subBuilder: OwnedDHTRecordPointer.create)
|
..aOM<OwnedDHTRecordPointer>(1, _omitFieldNames ? '' : 'contactRequestInbox', subBuilder: OwnedDHTRecordPointer.create)
|
||||||
..aOM<CryptoKey>(2, _omitFieldNames ? '' : 'writerKey', subBuilder: CryptoKey.create)
|
..aOM<CryptoKey>(2, _omitFieldNames ? '' : 'writerKey', subBuilder: CryptoKey.create)
|
||||||
..aOM<CryptoKey>(3, _omitFieldNames ? '' : 'writerSecret', subBuilder: CryptoKey.create)
|
..aOM<CryptoKey>(3, _omitFieldNames ? '' : 'writerSecret', subBuilder: CryptoKey.create)
|
||||||
..aOM<OwnedDHTRecordPointer>(4, _omitFieldNames ? '' : 'localConversation', subBuilder: OwnedDHTRecordPointer.create)
|
..aOM<TypedKey>(4, _omitFieldNames ? '' : 'localConversationRecordKey', subBuilder: TypedKey.create)
|
||||||
..a<$fixnum.Int64>(5, _omitFieldNames ? '' : 'expiration', $pb.PbFieldType.OU6, defaultOrMaker: $fixnum.Int64.ZERO)
|
..a<$fixnum.Int64>(5, _omitFieldNames ? '' : 'expiration', $pb.PbFieldType.OU6, defaultOrMaker: $fixnum.Int64.ZERO)
|
||||||
..a<$core.List<$core.int>>(6, _omitFieldNames ? '' : 'invitation', $pb.PbFieldType.OY)
|
..a<$core.List<$core.int>>(6, _omitFieldNames ? '' : 'invitation', $pb.PbFieldType.OY)
|
||||||
..aOS(7, _omitFieldNames ? '' : 'message')
|
..aOS(7, _omitFieldNames ? '' : 'message')
|
||||||
@ -1837,15 +1837,15 @@ class ContactInvitationRecord extends $pb.GeneratedMessage {
|
|||||||
CryptoKey ensureWriterSecret() => $_ensure(2);
|
CryptoKey ensureWriterSecret() => $_ensure(2);
|
||||||
|
|
||||||
@$pb.TagNumber(4)
|
@$pb.TagNumber(4)
|
||||||
OwnedDHTRecordPointer get localConversation => $_getN(3);
|
TypedKey get localConversationRecordKey => $_getN(3);
|
||||||
@$pb.TagNumber(4)
|
@$pb.TagNumber(4)
|
||||||
set localConversation(OwnedDHTRecordPointer v) { setField(4, v); }
|
set localConversationRecordKey(TypedKey v) { setField(4, v); }
|
||||||
@$pb.TagNumber(4)
|
@$pb.TagNumber(4)
|
||||||
$core.bool hasLocalConversation() => $_has(3);
|
$core.bool hasLocalConversationRecordKey() => $_has(3);
|
||||||
@$pb.TagNumber(4)
|
@$pb.TagNumber(4)
|
||||||
void clearLocalConversation() => clearField(4);
|
void clearLocalConversationRecordKey() => clearField(4);
|
||||||
@$pb.TagNumber(4)
|
@$pb.TagNumber(4)
|
||||||
OwnedDHTRecordPointer ensureLocalConversation() => $_ensure(3);
|
TypedKey ensureLocalConversationRecordKey() => $_ensure(3);
|
||||||
|
|
||||||
@$pb.TagNumber(5)
|
@$pb.TagNumber(5)
|
||||||
$fixnum.Int64 get expiration => $_getI64(4);
|
$fixnum.Int64 get expiration => $_getI64(4);
|
||||||
|
@ -303,8 +303,8 @@ const Contact$json = {
|
|||||||
{'1': 'remote_profile', '3': 2, '4': 1, '5': 11, '6': '.Profile', '10': 'remoteProfile'},
|
{'1': 'remote_profile', '3': 2, '4': 1, '5': 11, '6': '.Profile', '10': 'remoteProfile'},
|
||||||
{'1': 'identity_master_json', '3': 3, '4': 1, '5': 9, '10': 'identityMasterJson'},
|
{'1': 'identity_master_json', '3': 3, '4': 1, '5': 9, '10': 'identityMasterJson'},
|
||||||
{'1': 'identity_public_key', '3': 4, '4': 1, '5': 11, '6': '.TypedKey', '10': 'identityPublicKey'},
|
{'1': 'identity_public_key', '3': 4, '4': 1, '5': 11, '6': '.TypedKey', '10': 'identityPublicKey'},
|
||||||
{'1': 'remote_conversation_key', '3': 5, '4': 1, '5': 11, '6': '.TypedKey', '10': 'remoteConversationKey'},
|
{'1': 'remote_conversation_record_key', '3': 5, '4': 1, '5': 11, '6': '.TypedKey', '10': 'remoteConversationRecordKey'},
|
||||||
{'1': 'local_conversation', '3': 6, '4': 1, '5': 11, '6': '.OwnedDHTRecordPointer', '10': 'localConversation'},
|
{'1': 'local_conversation_record_key', '3': 6, '4': 1, '5': 11, '6': '.TypedKey', '10': 'localConversationRecordKey'},
|
||||||
{'1': 'show_availability', '3': 7, '4': 1, '5': 8, '10': 'showAvailability'},
|
{'1': 'show_availability', '3': 7, '4': 1, '5': 8, '10': 'showAvailability'},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@ -314,11 +314,11 @@ final $typed_data.Uint8List contactDescriptor = $convert.base64Decode(
|
|||||||
'CgdDb250YWN0Ei8KDmVkaXRlZF9wcm9maWxlGAEgASgLMgguUHJvZmlsZVINZWRpdGVkUHJvZm'
|
'CgdDb250YWN0Ei8KDmVkaXRlZF9wcm9maWxlGAEgASgLMgguUHJvZmlsZVINZWRpdGVkUHJvZm'
|
||||||
'lsZRIvCg5yZW1vdGVfcHJvZmlsZRgCIAEoCzIILlByb2ZpbGVSDXJlbW90ZVByb2ZpbGUSMAoU'
|
'lsZRIvCg5yZW1vdGVfcHJvZmlsZRgCIAEoCzIILlByb2ZpbGVSDXJlbW90ZVByb2ZpbGUSMAoU'
|
||||||
'aWRlbnRpdHlfbWFzdGVyX2pzb24YAyABKAlSEmlkZW50aXR5TWFzdGVySnNvbhI5ChNpZGVudG'
|
'aWRlbnRpdHlfbWFzdGVyX2pzb24YAyABKAlSEmlkZW50aXR5TWFzdGVySnNvbhI5ChNpZGVudG'
|
||||||
'l0eV9wdWJsaWNfa2V5GAQgASgLMgkuVHlwZWRLZXlSEWlkZW50aXR5UHVibGljS2V5EkEKF3Jl'
|
'l0eV9wdWJsaWNfa2V5GAQgASgLMgkuVHlwZWRLZXlSEWlkZW50aXR5UHVibGljS2V5Ek4KHnJl'
|
||||||
'bW90ZV9jb252ZXJzYXRpb25fa2V5GAUgASgLMgkuVHlwZWRLZXlSFXJlbW90ZUNvbnZlcnNhdG'
|
'bW90ZV9jb252ZXJzYXRpb25fcmVjb3JkX2tleRgFIAEoCzIJLlR5cGVkS2V5UhtyZW1vdGVDb2'
|
||||||
'lvbktleRJFChJsb2NhbF9jb252ZXJzYXRpb24YBiABKAsyFi5Pd25lZERIVFJlY29yZFBvaW50'
|
'52ZXJzYXRpb25SZWNvcmRLZXkSTAodbG9jYWxfY29udmVyc2F0aW9uX3JlY29yZF9rZXkYBiAB'
|
||||||
'ZXJSEWxvY2FsQ29udmVyc2F0aW9uEisKEXNob3dfYXZhaWxhYmlsaXR5GAcgASgIUhBzaG93QX'
|
'KAsyCS5UeXBlZEtleVIabG9jYWxDb252ZXJzYXRpb25SZWNvcmRLZXkSKwoRc2hvd19hdmFpbG'
|
||||||
'ZhaWxhYmlsaXR5');
|
'FiaWxpdHkYByABKAhSEHNob3dBdmFpbGFiaWxpdHk=');
|
||||||
|
|
||||||
@$core.Deprecated('Use profileDescriptor instead')
|
@$core.Deprecated('Use profileDescriptor instead')
|
||||||
const Profile$json = {
|
const Profile$json = {
|
||||||
@ -462,7 +462,7 @@ const ContactResponse$json = {
|
|||||||
'2': [
|
'2': [
|
||||||
{'1': 'accept', '3': 1, '4': 1, '5': 8, '10': 'accept'},
|
{'1': 'accept', '3': 1, '4': 1, '5': 8, '10': 'accept'},
|
||||||
{'1': 'identity_master_record_key', '3': 2, '4': 1, '5': 11, '6': '.TypedKey', '10': 'identityMasterRecordKey'},
|
{'1': 'identity_master_record_key', '3': 2, '4': 1, '5': 11, '6': '.TypedKey', '10': 'identityMasterRecordKey'},
|
||||||
{'1': 'remote_conversation_key', '3': 3, '4': 1, '5': 11, '6': '.TypedKey', '10': 'remoteConversationKey'},
|
{'1': 'remote_conversation_record_key', '3': 3, '4': 1, '5': 11, '6': '.TypedKey', '10': 'remoteConversationRecordKey'},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -470,8 +470,8 @@ const ContactResponse$json = {
|
|||||||
final $typed_data.Uint8List contactResponseDescriptor = $convert.base64Decode(
|
final $typed_data.Uint8List contactResponseDescriptor = $convert.base64Decode(
|
||||||
'Cg9Db250YWN0UmVzcG9uc2USFgoGYWNjZXB0GAEgASgIUgZhY2NlcHQSRgoaaWRlbnRpdHlfbW'
|
'Cg9Db250YWN0UmVzcG9uc2USFgoGYWNjZXB0GAEgASgIUgZhY2NlcHQSRgoaaWRlbnRpdHlfbW'
|
||||||
'FzdGVyX3JlY29yZF9rZXkYAiABKAsyCS5UeXBlZEtleVIXaWRlbnRpdHlNYXN0ZXJSZWNvcmRL'
|
'FzdGVyX3JlY29yZF9rZXkYAiABKAsyCS5UeXBlZEtleVIXaWRlbnRpdHlNYXN0ZXJSZWNvcmRL'
|
||||||
'ZXkSQQoXcmVtb3RlX2NvbnZlcnNhdGlvbl9rZXkYAyABKAsyCS5UeXBlZEtleVIVcmVtb3RlQ2'
|
'ZXkSTgoecmVtb3RlX2NvbnZlcnNhdGlvbl9yZWNvcmRfa2V5GAMgASgLMgkuVHlwZWRLZXlSG3'
|
||||||
'9udmVyc2F0aW9uS2V5');
|
'JlbW90ZUNvbnZlcnNhdGlvblJlY29yZEtleQ==');
|
||||||
|
|
||||||
@$core.Deprecated('Use signedContactResponseDescriptor instead')
|
@$core.Deprecated('Use signedContactResponseDescriptor instead')
|
||||||
const SignedContactResponse$json = {
|
const SignedContactResponse$json = {
|
||||||
@ -495,7 +495,7 @@ const ContactInvitationRecord$json = {
|
|||||||
{'1': 'contact_request_inbox', '3': 1, '4': 1, '5': 11, '6': '.OwnedDHTRecordPointer', '10': 'contactRequestInbox'},
|
{'1': 'contact_request_inbox', '3': 1, '4': 1, '5': 11, '6': '.OwnedDHTRecordPointer', '10': 'contactRequestInbox'},
|
||||||
{'1': 'writer_key', '3': 2, '4': 1, '5': 11, '6': '.CryptoKey', '10': 'writerKey'},
|
{'1': 'writer_key', '3': 2, '4': 1, '5': 11, '6': '.CryptoKey', '10': 'writerKey'},
|
||||||
{'1': 'writer_secret', '3': 3, '4': 1, '5': 11, '6': '.CryptoKey', '10': 'writerSecret'},
|
{'1': 'writer_secret', '3': 3, '4': 1, '5': 11, '6': '.CryptoKey', '10': 'writerSecret'},
|
||||||
{'1': 'local_conversation', '3': 4, '4': 1, '5': 11, '6': '.OwnedDHTRecordPointer', '10': 'localConversation'},
|
{'1': 'local_conversation_record_key', '3': 4, '4': 1, '5': 11, '6': '.TypedKey', '10': 'localConversationRecordKey'},
|
||||||
{'1': 'expiration', '3': 5, '4': 1, '5': 4, '10': 'expiration'},
|
{'1': 'expiration', '3': 5, '4': 1, '5': 4, '10': 'expiration'},
|
||||||
{'1': 'invitation', '3': 6, '4': 1, '5': 12, '10': 'invitation'},
|
{'1': 'invitation', '3': 6, '4': 1, '5': 12, '10': 'invitation'},
|
||||||
{'1': 'message', '3': 7, '4': 1, '5': 9, '10': 'message'},
|
{'1': 'message', '3': 7, '4': 1, '5': 9, '10': 'message'},
|
||||||
@ -507,8 +507,8 @@ final $typed_data.Uint8List contactInvitationRecordDescriptor = $convert.base64D
|
|||||||
'ChdDb250YWN0SW52aXRhdGlvblJlY29yZBJKChVjb250YWN0X3JlcXVlc3RfaW5ib3gYASABKA'
|
'ChdDb250YWN0SW52aXRhdGlvblJlY29yZBJKChVjb250YWN0X3JlcXVlc3RfaW5ib3gYASABKA'
|
||||||
'syFi5Pd25lZERIVFJlY29yZFBvaW50ZXJSE2NvbnRhY3RSZXF1ZXN0SW5ib3gSKQoKd3JpdGVy'
|
'syFi5Pd25lZERIVFJlY29yZFBvaW50ZXJSE2NvbnRhY3RSZXF1ZXN0SW5ib3gSKQoKd3JpdGVy'
|
||||||
'X2tleRgCIAEoCzIKLkNyeXB0b0tleVIJd3JpdGVyS2V5Ei8KDXdyaXRlcl9zZWNyZXQYAyABKA'
|
'X2tleRgCIAEoCzIKLkNyeXB0b0tleVIJd3JpdGVyS2V5Ei8KDXdyaXRlcl9zZWNyZXQYAyABKA'
|
||||||
'syCi5DcnlwdG9LZXlSDHdyaXRlclNlY3JldBJFChJsb2NhbF9jb252ZXJzYXRpb24YBCABKAsy'
|
'syCi5DcnlwdG9LZXlSDHdyaXRlclNlY3JldBJMCh1sb2NhbF9jb252ZXJzYXRpb25fcmVjb3Jk'
|
||||||
'Fi5Pd25lZERIVFJlY29yZFBvaW50ZXJSEWxvY2FsQ29udmVyc2F0aW9uEh4KCmV4cGlyYXRpb2'
|
'X2tleRgEIAEoCzIJLlR5cGVkS2V5Uhpsb2NhbENvbnZlcnNhdGlvblJlY29yZEtleRIeCgpleH'
|
||||||
'4YBSABKARSCmV4cGlyYXRpb24SHgoKaW52aXRhdGlvbhgGIAEoDFIKaW52aXRhdGlvbhIYCgdt'
|
'BpcmF0aW9uGAUgASgEUgpleHBpcmF0aW9uEh4KCmludml0YXRpb24YBiABKAxSCmludml0YXRp'
|
||||||
'ZXNzYWdlGAcgASgJUgdtZXNzYWdl');
|
'b24SGAoHbWVzc2FnZRgHIAEoCVIHbWVzc2FnZQ==');
|
||||||
|
|
||||||
|
@ -204,9 +204,9 @@ message Contact {
|
|||||||
// Copy of friend's most recent identity public key from their identityMaster
|
// Copy of friend's most recent identity public key from their identityMaster
|
||||||
TypedKey identity_public_key = 4;
|
TypedKey identity_public_key = 4;
|
||||||
// Remote conversation key to sync from friend
|
// Remote conversation key to sync from friend
|
||||||
TypedKey remote_conversation_key = 5;
|
TypedKey remote_conversation_record_key = 5;
|
||||||
// Our conversation key for friend to sync
|
// Our conversation key for friend to sync
|
||||||
OwnedDHTRecordPointer local_conversation = 6;
|
TypedKey local_conversation_record_key = 6;
|
||||||
// Show availability
|
// Show availability
|
||||||
bool show_availability = 7;
|
bool show_availability = 7;
|
||||||
}
|
}
|
||||||
@ -343,7 +343,7 @@ message ContactResponse {
|
|||||||
// Remote identity master DHT record key
|
// Remote identity master DHT record key
|
||||||
TypedKey identity_master_record_key = 2;
|
TypedKey identity_master_record_key = 2;
|
||||||
// Remote chat DHT record key if accepted
|
// Remote chat DHT record key if accepted
|
||||||
TypedKey remote_conversation_key = 3;
|
TypedKey remote_conversation_record_key = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signature of response with identity
|
// Signature of response with identity
|
||||||
@ -364,7 +364,7 @@ message ContactInvitationRecord {
|
|||||||
// Writer secret sent encrypted in the invitation
|
// Writer secret sent encrypted in the invitation
|
||||||
CryptoKey writer_secret = 3;
|
CryptoKey writer_secret = 3;
|
||||||
// Local chat DHT record key (parent is accountkey, will be moved to Contact if accepted)
|
// Local chat DHT record key (parent is accountkey, will be moved to Contact if accepted)
|
||||||
OwnedDHTRecordPointer local_conversation = 4;
|
TypedKey local_conversation_record_key = 4;
|
||||||
// Expiration timestamp
|
// Expiration timestamp
|
||||||
uint64 expiration = 5;
|
uint64 expiration = 5;
|
||||||
// A copy of the raw SignedContactInvitation invitation bytes post-encryption and signing
|
// A copy of the raw SignedContactInvitation invitation bytes post-encryption and signing
|
||||||
|
@ -14,6 +14,7 @@ import '../providers/account.dart';
|
|||||||
import '../providers/chat.dart';
|
import '../providers/chat.dart';
|
||||||
import '../providers/contact.dart';
|
import '../providers/contact.dart';
|
||||||
import '../providers/contact_invite.dart';
|
import '../providers/contact_invite.dart';
|
||||||
|
import '../providers/conversation.dart';
|
||||||
import '../providers/window_control.dart';
|
import '../providers/window_control.dart';
|
||||||
import '../tools/tools.dart';
|
import '../tools/tools.dart';
|
||||||
import 'main_pager/main_pager.dart';
|
import 'main_pager/main_pager.dart';
|
||||||
@ -113,8 +114,10 @@ class HomePageState extends ConsumerState<HomePage>
|
|||||||
activeAccountInfo: activeAccountInfo,
|
activeAccountInfo: activeAccountInfo,
|
||||||
profile: acceptedContact.profile,
|
profile: acceptedContact.profile,
|
||||||
remoteIdentity: acceptedContact.remoteIdentity,
|
remoteIdentity: acceptedContact.remoteIdentity,
|
||||||
remoteConversationKey: acceptedContact.remoteConversationKey,
|
remoteConversationRecordKey:
|
||||||
localConversation: acceptedContact.localConversation,
|
acceptedContact.remoteConversationRecordKey,
|
||||||
|
localConversationRecordKey:
|
||||||
|
acceptedContact.localConversationRecordKey,
|
||||||
);
|
);
|
||||||
ref
|
ref
|
||||||
..invalidate(fetchContactInvitationRecordsProvider)
|
..invalidate(fetchContactInvitationRecordsProvider)
|
||||||
@ -134,19 +137,34 @@ class HomePageState extends ConsumerState<HomePage>
|
|||||||
if (activeChat == null) {
|
if (activeChat == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final activeAccountInfo = await ref.read(fetchActiveAccountProvider.future);
|
||||||
|
if (activeAccountInfo == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final contactList = ref.read(fetchContactListProvider).asData?.value ??
|
final contactList = ref.read(fetchContactListProvider).asData?.value ??
|
||||||
const IListConst([]);
|
const IListConst([]);
|
||||||
|
|
||||||
final activeChatContactIdx = contactList.indexWhere(
|
final activeChatContactIdx = contactList.indexWhere(
|
||||||
(c) =>
|
(c) =>
|
||||||
proto.TypedKeyProto.fromProto(c.remoteConversationKey) == activeChat,
|
proto.TypedKeyProto.fromProto(c.remoteConversationRecordKey) ==
|
||||||
|
activeChat,
|
||||||
);
|
);
|
||||||
if (activeChatContactIdx == -1) {
|
if (activeChatContactIdx == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final activeChatContact = contactList[activeChatContactIdx];
|
final activeChatContact = contactList[activeChatContactIdx];
|
||||||
|
final remoteIdentityPublicKey =
|
||||||
|
proto.TypedKeyProto.fromProto(activeChatContact.identityPublicKey);
|
||||||
|
final remoteConversationRecordKey = proto.TypedKeyProto.fromProto(
|
||||||
|
activeChatContact.remoteConversationRecordKey);
|
||||||
|
|
||||||
//activeChatContact.rem
|
await getRemoteConversationMessages(
|
||||||
|
activeAccountInfo: activeAccountInfo,
|
||||||
|
remoteIdentityPublicKey: remoteIdentityPublicKey,
|
||||||
|
remoteConversationRecordKey: remoteConversationRecordKey);
|
||||||
|
|
||||||
|
// xxx add messages
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore: prefer_expression_function_bodies
|
// ignore: prefer_expression_function_bodies
|
||||||
@ -186,7 +204,8 @@ class HomePageState extends ConsumerState<HomePage>
|
|||||||
|
|
||||||
final activeChatContactIdx = contactList.indexWhere(
|
final activeChatContactIdx = contactList.indexWhere(
|
||||||
(c) =>
|
(c) =>
|
||||||
proto.TypedKeyProto.fromProto(c.remoteConversationKey) == activeChat,
|
proto.TypedKeyProto.fromProto(c.remoteConversationRecordKey) ==
|
||||||
|
activeChat,
|
||||||
);
|
);
|
||||||
if (activeChatContactIdx == -1) {
|
if (activeChatContactIdx == -1) {
|
||||||
activeChatState.add(null);
|
activeChatState.add(null);
|
||||||
|
@ -17,8 +17,8 @@ Future<void> createContact({
|
|||||||
required ActiveAccountInfo activeAccountInfo,
|
required ActiveAccountInfo activeAccountInfo,
|
||||||
required proto.Profile profile,
|
required proto.Profile profile,
|
||||||
required IdentityMaster remoteIdentity,
|
required IdentityMaster remoteIdentity,
|
||||||
required TypedKey remoteConversationKey,
|
required TypedKey remoteConversationRecordKey,
|
||||||
required OwnedDHTRecordPointer localConversation,
|
required TypedKey localConversationRecordKey,
|
||||||
}) async {
|
}) async {
|
||||||
final accountRecordKey =
|
final accountRecordKey =
|
||||||
activeAccountInfo.userLogin.accountRecordInfo.accountRecord.recordKey;
|
activeAccountInfo.userLogin.accountRecordInfo.accountRecord.recordKey;
|
||||||
@ -32,8 +32,8 @@ Future<void> createContact({
|
|||||||
kind: remoteIdentity.identityRecordKey.kind,
|
kind: remoteIdentity.identityRecordKey.kind,
|
||||||
value: remoteIdentity.identityPublicKey)
|
value: remoteIdentity.identityPublicKey)
|
||||||
.toProto()
|
.toProto()
|
||||||
..remoteConversationKey = remoteConversationKey.toProto()
|
..remoteConversationRecordKey = remoteConversationRecordKey.toProto()
|
||||||
..localConversation = localConversation.toProto()
|
..localConversationRecordKey = localConversationRecordKey.toProto()
|
||||||
..showAvailability = false;
|
..showAvailability = false;
|
||||||
|
|
||||||
// Add Contact to account's list
|
// Add Contact to account's list
|
||||||
@ -56,7 +56,7 @@ Future<void> deleteContact(
|
|||||||
final accountRecordKey =
|
final accountRecordKey =
|
||||||
activeAccountInfo.userLogin.accountRecordInfo.accountRecord.recordKey;
|
activeAccountInfo.userLogin.accountRecordInfo.accountRecord.recordKey;
|
||||||
final remoteConversationKey =
|
final remoteConversationKey =
|
||||||
proto.TypedKeyProto.fromProto(contact.remoteConversationKey);
|
proto.TypedKeyProto.fromProto(contact.remoteConversationRecordKey);
|
||||||
|
|
||||||
// Remove any chats for this contact
|
// Remove any chats for this contact
|
||||||
await deleteChat(
|
await deleteChat(
|
||||||
@ -75,14 +75,14 @@ Future<void> deleteContact(
|
|||||||
if (item == null) {
|
if (item == null) {
|
||||||
throw Exception('Failed to get contact');
|
throw Exception('Failed to get contact');
|
||||||
}
|
}
|
||||||
if (item.remoteConversationKey == contact.remoteConversationKey) {
|
if (item.remoteConversationRecordKey ==
|
||||||
|
contact.remoteConversationRecordKey) {
|
||||||
await contactList.tryRemoveItem(i);
|
await contactList.tryRemoveItem(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await (await pool.openOwned(
|
await (await pool.openRead(
|
||||||
proto.OwnedDHTRecordPointerProto.fromProto(
|
proto.TypedKeyProto.fromProto(contact.localConversationRecordKey),
|
||||||
contact.localConversation),
|
|
||||||
parent: accountRecordKey))
|
parent: accountRecordKey))
|
||||||
.delete();
|
.delete();
|
||||||
await (await pool.openRead(remoteConversationKey, parent: accountRecordKey))
|
await (await pool.openRead(remoteConversationKey, parent: accountRecordKey))
|
||||||
|
@ -28,14 +28,14 @@ class AcceptedContact {
|
|||||||
AcceptedContact({
|
AcceptedContact({
|
||||||
required this.profile,
|
required this.profile,
|
||||||
required this.remoteIdentity,
|
required this.remoteIdentity,
|
||||||
required this.remoteConversationKey,
|
required this.remoteConversationRecordKey,
|
||||||
required this.localConversation,
|
required this.localConversationRecordKey,
|
||||||
});
|
});
|
||||||
|
|
||||||
proto.Profile profile;
|
proto.Profile profile;
|
||||||
IdentityMaster remoteIdentity;
|
IdentityMaster remoteIdentity;
|
||||||
TypedKey remoteConversationKey;
|
TypedKey remoteConversationRecordKey;
|
||||||
OwnedDHTRecordPointer localConversation;
|
TypedKey localConversationRecordKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
class AcceptedOrRejectedContact {
|
class AcceptedOrRejectedContact {
|
||||||
@ -92,33 +92,33 @@ Future<AcceptedOrRejectedContact?> checkAcceptRejectContact(
|
|||||||
contactResponseBytes, signature);
|
contactResponseBytes, signature);
|
||||||
|
|
||||||
// Pull profile from remote conversation key
|
// Pull profile from remote conversation key
|
||||||
final remoteConversationKey =
|
final remoteConversationRecordKey = proto.TypedKeyProto.fromProto(
|
||||||
proto.TypedKeyProto.fromProto(contactResponse.remoteConversationKey);
|
contactResponse.remoteConversationRecordKey);
|
||||||
final remoteConversation = await readRemoteConversation(
|
final remoteConversation = await readRemoteConversation(
|
||||||
activeAccountInfo: activeAccountInfo,
|
activeAccountInfo: activeAccountInfo,
|
||||||
remoteIdentityPublicKey:
|
remoteIdentityPublicKey:
|
||||||
contactIdentityMaster.identityPublicTypedKey(),
|
contactIdentityMaster.identityPublicTypedKey(),
|
||||||
remoteConversationKey: remoteConversationKey);
|
remoteConversationRecordKey: remoteConversationRecordKey);
|
||||||
if (remoteConversation == null) {
|
if (remoteConversation == null) {
|
||||||
log.info('Remote conversation could not be read. Waiting...');
|
log.info('Remote conversation could not be read. Waiting...');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Complete the local conversation now that we have the remote profile
|
// Complete the local conversation now that we have the remote profile
|
||||||
final localConversationOwned = proto.OwnedDHTRecordPointerProto.fromProto(
|
final localConversationRecordKey = proto.TypedKeyProto.fromProto(
|
||||||
contactInvitationRecord.localConversation);
|
contactInvitationRecord.localConversationRecordKey);
|
||||||
return createConversation(
|
return createConversation(
|
||||||
activeAccountInfo: activeAccountInfo,
|
activeAccountInfo: activeAccountInfo,
|
||||||
remoteIdentityPublicKey:
|
remoteIdentityPublicKey:
|
||||||
contactIdentityMaster.identityPublicTypedKey(),
|
contactIdentityMaster.identityPublicTypedKey(),
|
||||||
existingConversationOwned: localConversationOwned,
|
existingConversationRecordKey: localConversationRecordKey,
|
||||||
// ignore: prefer_expression_function_bodies
|
// ignore: prefer_expression_function_bodies
|
||||||
callback: (localConversation) async {
|
callback: (localConversation) async {
|
||||||
return AcceptedOrRejectedContact(
|
return AcceptedOrRejectedContact(
|
||||||
acceptedContact: AcceptedContact(
|
acceptedContact: AcceptedContact(
|
||||||
profile: remoteConversation.profile,
|
profile: remoteConversation.profile,
|
||||||
remoteIdentity: contactIdentityMaster,
|
remoteIdentity: contactIdentityMaster,
|
||||||
remoteConversationKey: remoteConversationKey,
|
remoteConversationRecordKey: remoteConversationRecordKey,
|
||||||
localConversation: localConversationOwned));
|
localConversationRecordKey: localConversationRecordKey));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -182,9 +182,9 @@ Future<void> deleteContactInvitation(
|
|||||||
await contactRequestInbox.delete();
|
await contactRequestInbox.delete();
|
||||||
});
|
});
|
||||||
if (!accepted) {
|
if (!accepted) {
|
||||||
await (await pool.openOwned(
|
await (await pool.openRead(
|
||||||
proto.OwnedDHTRecordPointerProto.fromProto(
|
proto.TypedKeyProto.fromProto(
|
||||||
contactInvitationRecord.localConversation),
|
contactInvitationRecord.localConversationRecordKey),
|
||||||
parent: accountRecordKey))
|
parent: accountRecordKey))
|
||||||
.delete();
|
.delete();
|
||||||
}
|
}
|
||||||
@ -206,11 +206,13 @@ Future<Uint8List> createContactInvitation(
|
|||||||
|
|
||||||
// Generate writer keypair to share with new contact
|
// Generate writer keypair to share with new contact
|
||||||
final cs = await pool.veilid.bestCryptoSystem();
|
final cs = await pool.veilid.bestCryptoSystem();
|
||||||
final writer = await cs.generateKeyPair();
|
final contactRequestWriter = await cs.generateKeyPair();
|
||||||
|
final conversationWriter =
|
||||||
|
getConversationWriter(activeAccountInfo: activeAccountInfo);
|
||||||
|
|
||||||
// Encrypt the writer secret with the encryption key
|
// Encrypt the writer secret with the encryption key
|
||||||
final encryptedSecret = await encryptSecretToBytes(
|
final encryptedSecret = await encryptSecretToBytes(
|
||||||
secret: writer.secret,
|
secret: contactRequestWriter.secret,
|
||||||
cryptoKind: cs.kind(),
|
cryptoKind: cs.kind(),
|
||||||
encryptionKey: encryptionKey,
|
encryptionKey: encryptionKey,
|
||||||
encryptionKeyType: encryptionKeyType);
|
encryptionKeyType: encryptionKeyType);
|
||||||
@ -220,19 +222,24 @@ Future<Uint8List> createContactInvitation(
|
|||||||
// to and it will be eventually encrypted with the DH of the contact's
|
// to and it will be eventually encrypted with the DH of the contact's
|
||||||
// identity key
|
// identity key
|
||||||
late final Uint8List signedContactInvitationBytes;
|
late final Uint8List signedContactInvitationBytes;
|
||||||
await (await pool.create(parent: accountRecordKey))
|
await (await pool.create(
|
||||||
|
parent: accountRecordKey,
|
||||||
|
schema: DHTSchema.smpl(oCnt: 0, members: [
|
||||||
|
DHTSchemaMember(mKey: conversationWriter.key, mCnt: 1)
|
||||||
|
])))
|
||||||
.deleteScope((localConversation) async {
|
.deleteScope((localConversation) async {
|
||||||
|
// dont bother reopening localConversation with writer
|
||||||
// Make ContactRequestPrivate and encrypt with the writer secret
|
// Make ContactRequestPrivate and encrypt with the writer secret
|
||||||
final crpriv = ContactRequestPrivate()
|
final crpriv = ContactRequestPrivate()
|
||||||
..writerKey = writer.key.toProto()
|
..writerKey = contactRequestWriter.key.toProto()
|
||||||
..profile = activeAccountInfo.account.profile
|
..profile = activeAccountInfo.account.profile
|
||||||
..identityMasterRecordKey =
|
..identityMasterRecordKey =
|
||||||
activeAccountInfo.userLogin.accountMasterRecordKey.toProto()
|
activeAccountInfo.userLogin.accountMasterRecordKey.toProto()
|
||||||
..chatRecordKey = localConversation.key.toProto()
|
..chatRecordKey = localConversation.key.toProto()
|
||||||
..expiration = expiration?.toInt64() ?? Int64.ZERO;
|
..expiration = expiration?.toInt64() ?? Int64.ZERO;
|
||||||
final crprivbytes = crpriv.writeToBuffer();
|
final crprivbytes = crpriv.writeToBuffer();
|
||||||
final encryptedContactRequestPrivate =
|
final encryptedContactRequestPrivate = await cs.encryptNoAuthWithNonce(
|
||||||
await cs.encryptNoAuthWithNonce(crprivbytes, writer.secret);
|
crprivbytes, contactRequestWriter.secret);
|
||||||
|
|
||||||
// Create ContactRequest and embed contactrequestprivate
|
// Create ContactRequest and embed contactrequestprivate
|
||||||
final creq = ContactRequest()
|
final creq = ContactRequest()
|
||||||
@ -242,8 +249,9 @@ Future<Uint8List> createContactInvitation(
|
|||||||
// Create DHT unicast inbox for ContactRequest
|
// Create DHT unicast inbox for ContactRequest
|
||||||
await (await pool.create(
|
await (await pool.create(
|
||||||
parent: accountRecordKey,
|
parent: accountRecordKey,
|
||||||
schema: DHTSchema.smpl(
|
schema: DHTSchema.smpl(oCnt: 1, members: [
|
||||||
oCnt: 1, members: [DHTSchemaMember(mCnt: 1, mKey: writer.key)]),
|
DHTSchemaMember(mCnt: 1, mKey: contactRequestWriter.key)
|
||||||
|
]),
|
||||||
crypto: const DHTRecordCryptoPublic()))
|
crypto: const DHTRecordCryptoPublic()))
|
||||||
.deleteScope((contactRequestInbox) async {
|
.deleteScope((contactRequestInbox) async {
|
||||||
// Store ContactRequest in owner subkey
|
// Store ContactRequest in owner subkey
|
||||||
@ -264,9 +272,9 @@ Future<Uint8List> createContactInvitation(
|
|||||||
final cinvrec = ContactInvitationRecord()
|
final cinvrec = ContactInvitationRecord()
|
||||||
..contactRequestInbox =
|
..contactRequestInbox =
|
||||||
contactRequestInbox.ownedDHTRecordPointer.toProto()
|
contactRequestInbox.ownedDHTRecordPointer.toProto()
|
||||||
..writerKey = writer.key.toProto()
|
..writerKey = contactRequestWriter.key.toProto()
|
||||||
..writerSecret = writer.secret.toProto()
|
..writerSecret = contactRequestWriter.secret.toProto()
|
||||||
..localConversation = localConversation.ownedDHTRecordPointer.toProto()
|
..localConversationRecordKey = localConversation.key.toProto()
|
||||||
..expiration = expiration?.toInt64() ?? Int64.ZERO
|
..expiration = expiration?.toInt64() ?? Int64.ZERO
|
||||||
..invitation = signedContactInvitationBytes
|
..invitation = signedContactInvitationBytes
|
||||||
..message = message;
|
..message = message;
|
||||||
@ -390,7 +398,7 @@ Future<AcceptedContact?> acceptContactInvitation(
|
|||||||
callback: (localConversation) async {
|
callback: (localConversation) async {
|
||||||
final contactResponse = ContactResponse()
|
final contactResponse = ContactResponse()
|
||||||
..accept = true
|
..accept = true
|
||||||
..remoteConversationKey = localConversation.key.toProto()
|
..remoteConversationRecordKey = localConversation.key.toProto()
|
||||||
..identityMasterRecordKey = activeAccountInfo
|
..identityMasterRecordKey = activeAccountInfo
|
||||||
.localAccount.identityMaster.masterRecordKey
|
.localAccount.identityMaster.masterRecordKey
|
||||||
.toProto();
|
.toProto();
|
||||||
@ -418,9 +426,9 @@ Future<AcceptedContact?> acceptContactInvitation(
|
|||||||
return AcceptedContact(
|
return AcceptedContact(
|
||||||
profile: validContactInvitation.contactRequestPrivate.profile,
|
profile: validContactInvitation.contactRequestPrivate.profile,
|
||||||
remoteIdentity: validContactInvitation.contactIdentityMaster,
|
remoteIdentity: validContactInvitation.contactIdentityMaster,
|
||||||
remoteConversationKey: proto.TypedKeyProto.fromProto(
|
remoteConversationRecordKey: proto.TypedKeyProto.fromProto(
|
||||||
validContactInvitation.contactRequestPrivate.chatRecordKey),
|
validContactInvitation.contactRequestPrivate.chatRecordKey),
|
||||||
localConversation: localConversation.ownedDHTRecordPointer,
|
localConversationRecordKey: localConversation.key,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -24,6 +24,15 @@ Future<DHTRecordCrypto> getConversationCrypto({
|
|||||||
return DHTRecordCryptoPrivate.fromSecret(identitySecret.kind, sharedSecret);
|
return DHTRecordCryptoPrivate.fromSecret(identitySecret.kind, sharedSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyPair getConversationWriter({
|
||||||
|
required ActiveAccountInfo activeAccountInfo,
|
||||||
|
}) {
|
||||||
|
final identityKey =
|
||||||
|
activeAccountInfo.localAccount.identityMaster.identityPublicKey;
|
||||||
|
final identitySecret = activeAccountInfo.userLogin.identitySecret;
|
||||||
|
return KeyPair(key: identityKey, secret: identitySecret.value);
|
||||||
|
}
|
||||||
|
|
||||||
// Create a conversation
|
// Create a conversation
|
||||||
// If we were the initator of the conversation there may be an
|
// If we were the initator of the conversation there may be an
|
||||||
// incomplete 'existingConversationRecord' that we need to fill
|
// incomplete 'existingConversationRecord' that we need to fill
|
||||||
@ -32,7 +41,7 @@ Future<T> createConversation<T>(
|
|||||||
{required ActiveAccountInfo activeAccountInfo,
|
{required ActiveAccountInfo activeAccountInfo,
|
||||||
required TypedKey remoteIdentityPublicKey,
|
required TypedKey remoteIdentityPublicKey,
|
||||||
required FutureOr<T> Function(DHTRecord) callback,
|
required FutureOr<T> Function(DHTRecord) callback,
|
||||||
OwnedDHTRecordPointer? existingConversationOwned}) async {
|
TypedKey? existingConversationRecordKey}) async {
|
||||||
final pool = await DHTRecordPool.instance();
|
final pool = await DHTRecordPool.instance();
|
||||||
final accountRecordKey =
|
final accountRecordKey =
|
||||||
activeAccountInfo.userLogin.accountRecordInfo.accountRecord.recordKey;
|
activeAccountInfo.userLogin.accountRecordInfo.accountRecord.recordKey;
|
||||||
@ -40,28 +49,38 @@ Future<T> createConversation<T>(
|
|||||||
final crypto = await getConversationCrypto(
|
final crypto = await getConversationCrypto(
|
||||||
activeAccountInfo: activeAccountInfo,
|
activeAccountInfo: activeAccountInfo,
|
||||||
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
||||||
|
final writer = getConversationWriter(activeAccountInfo: activeAccountInfo);
|
||||||
|
|
||||||
|
// Open with SMPL scheme for identity writer
|
||||||
late final DHTRecord localConversationRecord;
|
late final DHTRecord localConversationRecord;
|
||||||
if (existingConversationOwned != null) {
|
if (existingConversationRecordKey != null) {
|
||||||
localConversationRecord = await pool.openOwned(existingConversationOwned,
|
localConversationRecord = await pool.openWrite(
|
||||||
|
existingConversationRecordKey, writer,
|
||||||
parent: accountRecordKey, crypto: crypto);
|
parent: accountRecordKey, crypto: crypto);
|
||||||
} else {
|
} else {
|
||||||
localConversationRecord =
|
final localConversationRecordCreate = await pool.create(
|
||||||
await pool.create(parent: accountRecordKey, crypto: crypto);
|
parent: accountRecordKey,
|
||||||
|
crypto: crypto,
|
||||||
|
schema: DHTSchema.smpl(
|
||||||
|
oCnt: 0, members: [DHTSchemaMember(mKey: writer.key, mCnt: 1)]));
|
||||||
|
await localConversationRecordCreate.close();
|
||||||
|
localConversationRecord = await pool.openWrite(
|
||||||
|
localConversationRecordCreate.key, writer,
|
||||||
|
parent: accountRecordKey, crypto: crypto);
|
||||||
}
|
}
|
||||||
return localConversationRecord
|
return localConversationRecord
|
||||||
// ignore: prefer_expression_function_bodies
|
// ignore: prefer_expression_function_bodies
|
||||||
.deleteScope((localConversation) async {
|
.deleteScope((localConversation) async {
|
||||||
// Make messages log
|
// Make messages log
|
||||||
return (await DHTShortArray.create(
|
return (await DHTShortArray.create(
|
||||||
parent: localConversation.key, crypto: crypto))
|
parent: localConversation.key, crypto: crypto, smplWriter: writer))
|
||||||
.deleteScope((messages) async {
|
.deleteScope((messages) async {
|
||||||
// Write local conversation key
|
// Write local conversation key
|
||||||
final conversation = Conversation()
|
final conversation = Conversation()
|
||||||
..profile = activeAccountInfo.account.profile
|
..profile = activeAccountInfo.account.profile
|
||||||
..identityMasterJson =
|
..identityMasterJson =
|
||||||
jsonEncode(activeAccountInfo.localAccount.identityMaster.toJson())
|
jsonEncode(activeAccountInfo.localAccount.identityMaster.toJson())
|
||||||
..messages = messages.record.ownedDHTRecordPointer.toProto();
|
..messages = messages.record.key.toProto();
|
||||||
|
|
||||||
//
|
//
|
||||||
final update = await localConversation.tryWriteProtobuf(
|
final update = await localConversation.tryWriteProtobuf(
|
||||||
@ -76,8 +95,8 @@ Future<T> createConversation<T>(
|
|||||||
|
|
||||||
Future<Conversation?> readRemoteConversation({
|
Future<Conversation?> readRemoteConversation({
|
||||||
required ActiveAccountInfo activeAccountInfo,
|
required ActiveAccountInfo activeAccountInfo,
|
||||||
|
required TypedKey remoteConversationRecordKey,
|
||||||
required TypedKey remoteIdentityPublicKey,
|
required TypedKey remoteIdentityPublicKey,
|
||||||
required TypedKey remoteConversationKey,
|
|
||||||
}) async {
|
}) async {
|
||||||
final accountRecordKey =
|
final accountRecordKey =
|
||||||
activeAccountInfo.userLogin.accountRecordInfo.accountRecord.recordKey;
|
activeAccountInfo.userLogin.accountRecordInfo.accountRecord.recordKey;
|
||||||
@ -86,7 +105,7 @@ Future<Conversation?> readRemoteConversation({
|
|||||||
final crypto = await getConversationCrypto(
|
final crypto = await getConversationCrypto(
|
||||||
activeAccountInfo: activeAccountInfo,
|
activeAccountInfo: activeAccountInfo,
|
||||||
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
||||||
return (await pool.openRead(remoteConversationKey,
|
return (await pool.openRead(remoteConversationRecordKey,
|
||||||
parent: accountRecordKey, crypto: crypto))
|
parent: accountRecordKey, crypto: crypto))
|
||||||
.scope((remoteConversation) async {
|
.scope((remoteConversation) async {
|
||||||
//
|
//
|
||||||
@ -98,7 +117,7 @@ Future<Conversation?> readRemoteConversation({
|
|||||||
|
|
||||||
Future<Conversation?> writeLocalConversation({
|
Future<Conversation?> writeLocalConversation({
|
||||||
required ActiveAccountInfo activeAccountInfo,
|
required ActiveAccountInfo activeAccountInfo,
|
||||||
required OwnedDHTRecordPointer localConversationOwned,
|
required TypedKey localConversationRecordKey,
|
||||||
required TypedKey remoteIdentityPublicKey,
|
required TypedKey remoteIdentityPublicKey,
|
||||||
required Conversation conversation,
|
required Conversation conversation,
|
||||||
}) async {
|
}) async {
|
||||||
@ -109,8 +128,9 @@ Future<Conversation?> writeLocalConversation({
|
|||||||
final crypto = await getConversationCrypto(
|
final crypto = await getConversationCrypto(
|
||||||
activeAccountInfo: activeAccountInfo,
|
activeAccountInfo: activeAccountInfo,
|
||||||
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
||||||
|
final writer = getConversationWriter(activeAccountInfo: activeAccountInfo);
|
||||||
|
|
||||||
return (await pool.openOwned(localConversationOwned,
|
return (await pool.openWrite(localConversationRecordKey, writer,
|
||||||
parent: accountRecordKey, crypto: crypto))
|
parent: accountRecordKey, crypto: crypto))
|
||||||
.scope((localConversation) async {
|
.scope((localConversation) async {
|
||||||
//
|
//
|
||||||
@ -125,7 +145,7 @@ Future<Conversation?> writeLocalConversation({
|
|||||||
|
|
||||||
Future<Conversation?> readLocalConversation({
|
Future<Conversation?> readLocalConversation({
|
||||||
required ActiveAccountInfo activeAccountInfo,
|
required ActiveAccountInfo activeAccountInfo,
|
||||||
required OwnedDHTRecordPointer localConversationOwned,
|
required TypedKey localConversationRecordKey,
|
||||||
required TypedKey remoteIdentityPublicKey,
|
required TypedKey remoteIdentityPublicKey,
|
||||||
}) async {
|
}) async {
|
||||||
final accountRecordKey =
|
final accountRecordKey =
|
||||||
@ -136,7 +156,7 @@ Future<Conversation?> readLocalConversation({
|
|||||||
activeAccountInfo: activeAccountInfo,
|
activeAccountInfo: activeAccountInfo,
|
||||||
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
||||||
|
|
||||||
return (await pool.openOwned(localConversationOwned,
|
return (await pool.openRead(localConversationRecordKey,
|
||||||
parent: accountRecordKey, crypto: crypto))
|
parent: accountRecordKey, crypto: crypto))
|
||||||
.scope((localConversation) async {
|
.scope((localConversation) async {
|
||||||
//
|
//
|
||||||
@ -150,24 +170,25 @@ Future<Conversation?> readLocalConversation({
|
|||||||
|
|
||||||
Future<void> addLocalConversationMessage(
|
Future<void> addLocalConversationMessage(
|
||||||
{required ActiveAccountInfo activeAccountInfo,
|
{required ActiveAccountInfo activeAccountInfo,
|
||||||
required OwnedDHTRecordPointer localConversationOwned,
|
required TypedKey localConversationRecordKey,
|
||||||
required TypedKey remoteIdentityPublicKey,
|
required TypedKey remoteIdentityPublicKey,
|
||||||
required proto.Message message}) async {
|
required proto.Message message}) async {
|
||||||
final conversation = await readLocalConversation(
|
final conversation = await readLocalConversation(
|
||||||
activeAccountInfo: activeAccountInfo,
|
activeAccountInfo: activeAccountInfo,
|
||||||
localConversationOwned: localConversationOwned,
|
localConversationRecordKey: localConversationRecordKey,
|
||||||
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
||||||
if (conversation == null) {
|
if (conversation == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final messagesOwned =
|
final messagesRecordKey =
|
||||||
proto.OwnedDHTRecordPointerProto.fromProto(conversation.messages);
|
proto.TypedKeyProto.fromProto(conversation.messages);
|
||||||
final crypto = await getConversationCrypto(
|
final crypto = await getConversationCrypto(
|
||||||
activeAccountInfo: activeAccountInfo,
|
activeAccountInfo: activeAccountInfo,
|
||||||
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
||||||
|
final writer = getConversationWriter(activeAccountInfo: activeAccountInfo);
|
||||||
|
|
||||||
await (await DHTShortArray.openOwned(messagesOwned,
|
await (await DHTShortArray.openWrite(messagesRecordKey, writer,
|
||||||
parent: localConversationOwned.recordKey, crypto: crypto))
|
parent: localConversationRecordKey, crypto: crypto))
|
||||||
.scope((messages) async {
|
.scope((messages) async {
|
||||||
await messages.tryAddItem(message.writeToBuffer());
|
await messages.tryAddItem(message.writeToBuffer());
|
||||||
});
|
});
|
||||||
@ -175,24 +196,24 @@ Future<void> addLocalConversationMessage(
|
|||||||
|
|
||||||
Future<IList<proto.Message>?> getLocalConversationMessages({
|
Future<IList<proto.Message>?> getLocalConversationMessages({
|
||||||
required ActiveAccountInfo activeAccountInfo,
|
required ActiveAccountInfo activeAccountInfo,
|
||||||
required OwnedDHTRecordPointer localConversationOwned,
|
required TypedKey localConversationRecordKey,
|
||||||
required TypedKey remoteIdentityPublicKey,
|
required TypedKey remoteIdentityPublicKey,
|
||||||
}) async {
|
}) async {
|
||||||
final conversation = await readLocalConversation(
|
final conversation = await readLocalConversation(
|
||||||
activeAccountInfo: activeAccountInfo,
|
activeAccountInfo: activeAccountInfo,
|
||||||
localConversationOwned: localConversationOwned,
|
localConversationRecordKey: localConversationRecordKey,
|
||||||
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
||||||
if (conversation == null) {
|
if (conversation == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final messagesOwned =
|
final messagesRecordKey =
|
||||||
proto.OwnedDHTRecordPointerProto.fromProto(conversation.messages);
|
proto.TypedKeyProto.fromProto(conversation.messages);
|
||||||
final crypto = await getConversationCrypto(
|
final crypto = await getConversationCrypto(
|
||||||
activeAccountInfo: activeAccountInfo,
|
activeAccountInfo: activeAccountInfo,
|
||||||
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
||||||
|
|
||||||
return (await DHTShortArray.openOwned(messagesOwned,
|
return (await DHTShortArray.openRead(messagesRecordKey,
|
||||||
parent: localConversationOwned.recordKey, crypto: crypto))
|
parent: localConversationRecordKey, crypto: crypto))
|
||||||
.scope((messages) async {
|
.scope((messages) async {
|
||||||
var out = IList<proto.Message>();
|
var out = IList<proto.Message>();
|
||||||
for (var i = 0; i < messages.length; i++) {
|
for (var i = 0; i < messages.length; i++) {
|
||||||
@ -208,24 +229,24 @@ Future<IList<proto.Message>?> getLocalConversationMessages({
|
|||||||
|
|
||||||
Future<IList<proto.Message>?> getRemoteConversationMessages({
|
Future<IList<proto.Message>?> getRemoteConversationMessages({
|
||||||
required ActiveAccountInfo activeAccountInfo,
|
required ActiveAccountInfo activeAccountInfo,
|
||||||
required TypedKey remoteConversationKey,
|
required TypedKey remoteConversationRecordKey,
|
||||||
required TypedKey remoteIdentityPublicKey,
|
required TypedKey remoteIdentityPublicKey,
|
||||||
}) async {
|
}) async {
|
||||||
final conversation = await readRemoteConversation(
|
final conversation = await readRemoteConversation(
|
||||||
activeAccountInfo: activeAccountInfo,
|
activeAccountInfo: activeAccountInfo,
|
||||||
remoteConversationKey: remoteConversationKey,
|
remoteConversationRecordKey: remoteConversationRecordKey,
|
||||||
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
||||||
if (conversation == null) {
|
if (conversation == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final messagesOwned =
|
final messagesRecordKey =
|
||||||
proto.OwnedDHTRecordPointerProto.fromProto(conversation.messages);
|
proto.TypedKeyProto.fromProto(conversation.messages);
|
||||||
final crypto = await getConversationCrypto(
|
final crypto = await getConversationCrypto(
|
||||||
activeAccountInfo: activeAccountInfo,
|
activeAccountInfo: activeAccountInfo,
|
||||||
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
remoteIdentityPublicKey: remoteIdentityPublicKey);
|
||||||
|
|
||||||
return (await DHTShortArray.openOwned(messagesOwned,
|
return (await DHTShortArray.openRead(messagesRecordKey,
|
||||||
parent: localConversationOwned.recordKey, crypto: crypto))
|
parent: remoteConversationRecordKey, crypto: crypto))
|
||||||
.scope((messages) async {
|
.scope((messages) async {
|
||||||
var out = IList<proto.Message>();
|
var out = IList<proto.Message>();
|
||||||
for (var i = 0; i < messages.length; i++) {
|
for (var i = 0; i < messages.length; i++) {
|
||||||
|
@ -60,6 +60,9 @@ class DHTShortArray {
|
|||||||
// Cached representation refreshed from head record
|
// Cached representation refreshed from head record
|
||||||
_DHTShortArrayCache _head;
|
_DHTShortArrayCache _head;
|
||||||
|
|
||||||
|
// Create a DHTShortArray
|
||||||
|
// if smplWriter is specified, uses a SMPL schema with a single writer
|
||||||
|
// rather than the key owner
|
||||||
static Future<DHTShortArray> create(
|
static Future<DHTShortArray> create(
|
||||||
{int stride = maxElements,
|
{int stride = maxElements,
|
||||||
VeilidRoutingContext? routingContext,
|
VeilidRoutingContext? routingContext,
|
||||||
|
Loading…
Reference in New Issue
Block a user