veilidchat/lib/contacts/cubits/contact_list_cubit.dart
2024-06-07 14:42:04 -04:00

106 lines
3.6 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'package:veilid_support/veilid_support.dart';
import '../../account_manager/account_manager.dart';
import '../../proto/proto.dart' as proto;
import '../../tools/tools.dart';
import 'conversation_cubit.dart';
//////////////////////////////////////////////////
// Mutable state for per-account contacts
class ContactListCubit extends DHTShortArrayCubit<proto.Contact> {
ContactListCubit({
required ActiveAccountInfo activeAccountInfo,
required proto.Account account,
}) : _activeAccountInfo = activeAccountInfo,
super(
open: () => _open(activeAccountInfo, account),
decodeElement: proto.Contact.fromBuffer);
static Future<DHTShortArray> _open(
ActiveAccountInfo activeAccountInfo, proto.Account account) async {
final accountRecordKey =
activeAccountInfo.userLogin.accountRecordInfo.accountRecord.recordKey;
final contactListRecordKey = account.contactList.toVeilid();
final dhtRecord = await DHTShortArray.openOwned(contactListRecordKey,
debugName: 'ContactListCubit::_open::ContactList',
parent: accountRecordKey);
return dhtRecord;
}
Future<void> createContact({
required proto.Profile remoteProfile,
required SuperIdentity remoteSuperIdentity,
required TypedKey remoteConversationRecordKey,
required TypedKey localConversationRecordKey,
}) async {
// Create Contact
final contact = proto.Contact()
..editedProfile = remoteProfile
..remoteProfile = remoteProfile
..superIdentityJson = jsonEncode(remoteSuperIdentity.toJson())
..identityPublicKey =
remoteSuperIdentity.currentInstance.typedPublicKey.toProto()
..remoteConversationRecordKey = remoteConversationRecordKey.toProto()
..localConversationRecordKey = localConversationRecordKey.toProto()
..showAvailability = false;
// Add Contact to account's list
// if this fails, don't keep retrying, user can try again later
await operateWrite((writer) async {
if (!await writer.tryAdd(contact.writeToBuffer())) {
throw Exception('Failed to add contact record');
}
});
}
Future<void> deleteContact({required proto.Contact contact}) async {
final remoteIdentityPublicKey = contact.identityPublicKey.toVeilid();
final localConversationRecordKey =
contact.localConversationRecordKey.toVeilid();
final remoteConversationRecordKey =
contact.remoteConversationRecordKey.toVeilid();
// Remove Contact from account's list
final deletedItem = await operateWrite((writer) async {
for (var i = 0; i < writer.length; i++) {
final item = await writer.getProtobuf(proto.Contact.fromBuffer, i);
if (item == null) {
throw Exception('Failed to get contact');
}
if (item.localConversationRecordKey ==
contact.localConversationRecordKey) {
await writer.remove(i);
return item;
}
}
return null;
});
if (deletedItem != null) {
try {
// Make a conversation cubit to manipulate the conversation
final conversationCubit = ConversationCubit(
activeAccountInfo: _activeAccountInfo,
remoteIdentityPublicKey: remoteIdentityPublicKey,
localConversationRecordKey: localConversationRecordKey,
remoteConversationRecordKey: remoteConversationRecordKey,
);
// Delete the local and remote conversation records
await conversationCubit.delete();
} on Exception catch (e) {
log.debug('error deleting conversation records: $e', e);
}
}
}
final ActiveAccountInfo _activeAccountInfo;
}