checkpoint

This commit is contained in:
Christien Rioux 2024-06-18 21:20:06 -04:00
parent 3edf2ebb46
commit c40f835ec5
25 changed files with 378 additions and 312 deletions

View file

@ -2,7 +2,6 @@ import 'package:async_tools/async_tools.dart';
import 'package:bloc_advanced_tools/bloc_advanced_tools.dart';
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';
import 'package:provider/provider.dart';
import 'package:veilid_support/veilid_support.dart';
import '../../account_manager/account_manager.dart';
@ -45,10 +44,15 @@ class ActiveConversationsBlocMapCubit extends BlocMapCubit<TypedKey,
AsyncValue<ActiveConversationState>, ActiveConversationCubit>
with StateMapFollower<ChatListCubitState, TypedKey, proto.Chat> {
ActiveConversationsBlocMapCubit({
required Locator locator,
}) : _locator = locator {
required AccountInfo accountInfo,
required AccountRecordCubit accountRecordCubit,
required ChatListCubit chatListCubit,
required ContactListCubit contactListCubit,
}) : _accountInfo = accountInfo,
_accountRecordCubit = accountRecordCubit,
_contactListCubit = contactListCubit {
// Follow the chat list cubit
follow(locator<ChatListCubit>());
follow(chatListCubit);
}
////////////////////////////////////////////////////////////////////////////
@ -69,20 +73,15 @@ class ActiveConversationsBlocMapCubit extends BlocMapCubit<TypedKey,
// Conversation cubit the tracks the state between the local
// and remote halves of a contact's relationship with this account
final conversationCubit = ConversationCubit(
locator: _locator,
accountInfo: _accountInfo,
remoteIdentityPublicKey: remoteIdentityPublicKey,
localConversationRecordKey: localConversationRecordKey,
remoteConversationRecordKey: remoteConversationRecordKey,
);
// When our local account profile changes, send it to the conversation
final accountRecordCubit = _locator<AccountRecordCubit>();
conversationCubit.watchAccountChanges(
accountRecordCubit.stream, accountRecordCubit.state);
// When remote conversation changes its profile,
// update our local contact
_locator<ContactListCubit>().followContactProfileChanges(
_contactListCubit.followContactProfileChanges(
localConversationRecordKey,
conversationCubit.stream.map((x) => x.map(
data: (d) => d.value.remoteConversation?.profile,
@ -90,6 +89,10 @@ class ActiveConversationsBlocMapCubit extends BlocMapCubit<TypedKey,
error: (_) => null)),
conversationCubit.state.asData?.value.remoteConversation?.profile);
// When our local account profile changes, send it to the conversation
conversationCubit.watchAccountChanges(
_accountRecordCubit.stream, _accountRecordCubit.state);
// Transformer that only passes through completed/active conversations
// along with the contact that corresponds to the completed
// conversation
@ -119,7 +122,7 @@ class ActiveConversationsBlocMapCubit extends BlocMapCubit<TypedKey,
@override
Future<void> updateState(TypedKey key, proto.Chat value) async {
final contactList = _locator<ContactListCubit>().state.state.asData?.value;
final contactList = _contactListCubit.state.state.asData?.value;
if (contactList == null) {
await addState(key, const AsyncValue.loading());
return;
@ -136,5 +139,7 @@ class ActiveConversationsBlocMapCubit extends BlocMapCubit<TypedKey,
////
final Locator _locator;
final AccountInfo _accountInfo;
final AccountRecordCubit _accountRecordCubit;
final ContactListCubit _contactListCubit;
}

View file

@ -2,13 +2,14 @@ import 'dart:async';
import 'package:async_tools/async_tools.dart';
import 'package:bloc_advanced_tools/bloc_advanced_tools.dart';
import 'package:provider/provider.dart';
import 'package:veilid_support/veilid_support.dart';
import '../../account_manager/account_manager.dart';
import '../../chat/chat.dart';
import '../../chat_list/cubits/chat_list_cubit.dart';
import '../../contacts/contacts.dart';
import '../../proto/proto.dart' as proto;
import '../conversation.dart';
import 'active_conversations_bloc_map_cubit.dart';
// Map of localConversationRecordKey to MessagesCubit
@ -19,10 +20,16 @@ class ActiveSingleContactChatBlocMapCubit extends BlocMapCubit<TypedKey,
with
StateMapFollower<ActiveConversationsBlocMapState, TypedKey,
AsyncValue<ActiveConversationState>> {
ActiveSingleContactChatBlocMapCubit({required Locator locator})
: _locator = locator {
ActiveSingleContactChatBlocMapCubit(
{required AccountInfo accountInfo,
required ActiveConversationsBlocMapCubit activeConversationsBlocMapCubit,
required ContactListCubit contactListCubit,
required ChatListCubit chatListCubit})
: _accountInfo = accountInfo,
_contactListCubit = contactListCubit,
_chatListCubit = chatListCubit {
// Follow the active conversations bloc map cubit
follow(locator<ActiveConversationsBlocMapCubit>());
follow(activeConversationsBlocMapCubit);
}
Future<void> _addConversationMessages(
@ -33,7 +40,7 @@ class ActiveSingleContactChatBlocMapCubit extends BlocMapCubit<TypedKey,
add(() => MapEntry(
contact.localConversationRecordKey.toVeilid(),
SingleContactMessagesCubit(
locator: _locator,
accountInfo: _accountInfo,
remoteIdentityPublicKey: contact.identityPublicKey.toVeilid(),
localConversationRecordKey:
contact.localConversationRecordKey.toVeilid(),
@ -52,7 +59,7 @@ class ActiveSingleContactChatBlocMapCubit extends BlocMapCubit<TypedKey,
Future<void> updateState(
TypedKey key, AsyncValue<ActiveConversationState> value) async {
// Get the contact object for this single contact chat
final contactList = _locator<ContactListCubit>().state.state.asData?.value;
final contactList = _contactListCubit.state.state.asData?.value;
if (contactList == null) {
await addState(key, const AsyncValue.loading());
return;
@ -67,7 +74,7 @@ class ActiveSingleContactChatBlocMapCubit extends BlocMapCubit<TypedKey,
final contact = contactList[contactIndex].value;
// Get the chat object for this single contact chat
final chatList = _locator<ChatListCubit>().state.state.asData?.value;
final chatList = _chatListCubit.state.state.asData?.value;
if (chatList == null) {
await addState(key, const AsyncValue.loading());
return;
@ -92,6 +99,7 @@ class ActiveSingleContactChatBlocMapCubit extends BlocMapCubit<TypedKey,
}
////
final Locator _locator;
final AccountInfo _accountInfo;
final ContactListCubit _contactListCubit;
final ChatListCubit _chatListCubit;
}

View file

@ -10,7 +10,6 @@ import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:meta/meta.dart';
import 'package:protobuf/protobuf.dart';
import 'package:provider/provider.dart';
import 'package:veilid_support/veilid_support.dart';
import '../../account_manager/account_manager.dart';
@ -36,19 +35,16 @@ class ConversationState extends Equatable {
/// 1-1 chats
class ConversationCubit extends Cubit<AsyncValue<ConversationState>> {
ConversationCubit(
{required Locator locator,
{required AccountInfo accountInfo,
required TypedKey remoteIdentityPublicKey,
TypedKey? localConversationRecordKey,
TypedKey? remoteConversationRecordKey})
: _locator = locator,
: _accountInfo = accountInfo,
_localConversationRecordKey = localConversationRecordKey,
_remoteIdentityPublicKey = remoteIdentityPublicKey,
_remoteConversationRecordKey = remoteConversationRecordKey,
super(const AsyncValue.loading()) {
final unlockedAccountInfo =
_locator<AccountInfoCubit>().state.unlockedAccountInfo!;
_accountRecordKey = unlockedAccountInfo.accountRecordKey;
_identityWriter = unlockedAccountInfo.identityWriter;
_identityWriter = _accountInfo.identityWriter;
if (_localConversationRecordKey != null) {
_initWait.add(() async {
@ -60,7 +56,7 @@ class ConversationCubit extends Cubit<AsyncValue<ConversationState>> {
final record = await pool.openRecordWrite(
_localConversationRecordKey!, writer,
debugName: 'ConversationCubit::LocalConversation',
parent: _accountRecordKey,
parent: accountInfo.accountRecordKey,
crypto: crypto);
return record;
@ -77,7 +73,7 @@ class ConversationCubit extends Cubit<AsyncValue<ConversationState>> {
final record = await pool.openRecordRead(_remoteConversationRecordKey,
debugName: 'ConversationCubit::RemoteConversation',
parent: pool.getParentRecordKey(_remoteConversationRecordKey) ??
_accountRecordKey,
accountInfo.accountRecordKey,
crypto: crypto);
return record;
});
@ -108,7 +104,8 @@ class ConversationCubit extends Cubit<AsyncValue<ConversationState>> {
/// The callback allows for more initialization to occur and for
/// cleanup to delete records upon failure of the callback
Future<T> initLocalConversation<T>(
{required FutureOr<T> Function(DHTRecord) callback,
{required proto.Profile profile,
required FutureOr<T> Function(DHTRecord) callback,
TypedKey? existingConversationRecordKey}) async {
assert(_localConversationRecordKey == null,
'must not have a local conversation yet');
@ -116,11 +113,8 @@ class ConversationCubit extends Cubit<AsyncValue<ConversationState>> {
final pool = DHTRecordPool.instance;
final crypto = await _cachedConversationCrypto();
final account = _locator<AccountRecordCubit>().state.asData!.value;
final unlockedAccountInfo =
_locator<AccountInfoCubit>().state.unlockedAccountInfo!;
final accountRecordKey = unlockedAccountInfo.accountRecordKey;
final writer = unlockedAccountInfo.identityWriter;
final accountRecordKey = _accountInfo.accountRecordKey;
final writer = _accountInfo.identityWriter;
// Open with SMPL scheme for identity writer
late final DHTRecord localConversationRecord;
@ -150,9 +144,9 @@ class ConversationCubit extends Cubit<AsyncValue<ConversationState>> {
callback: (messages) async {
// Create initial local conversation key contents
final conversation = proto.Conversation()
..profile = account.profile
..superIdentityJson = jsonEncode(
unlockedAccountInfo.localAccount.superIdentity.toJson())
..profile = profile
..superIdentityJson =
jsonEncode(_accountInfo.localAccount.superIdentity.toJson())
..messages = messages.recordKey.toProto();
// Write initial conversation to record
@ -359,10 +353,8 @@ class ConversationCubit extends Cubit<AsyncValue<ConversationState>> {
if (conversationCrypto != null) {
return conversationCrypto;
}
final unlockedAccountInfo =
_locator<AccountInfoCubit>().state.unlockedAccountInfo!;
conversationCrypto = await unlockedAccountInfo
.makeConversationCrypto(_remoteIdentityPublicKey);
conversationCrypto =
await _accountInfo.makeConversationCrypto(_remoteIdentityPublicKey);
_conversationCrypto = conversationCrypto;
return conversationCrypto;
}
@ -371,8 +363,7 @@ class ConversationCubit extends Cubit<AsyncValue<ConversationState>> {
// Fields
TypedKey get remoteIdentityPublicKey => _remoteIdentityPublicKey;
final Locator _locator;
late final TypedKey _accountRecordKey;
final AccountInfo _accountInfo;
late final KeyPair _identityWriter;
final TypedKey _remoteIdentityPublicKey;
TypedKey? _localConversationRecordKey;