clean up context locators

This commit is contained in:
Christien Rioux 2024-06-15 23:29:15 -04:00
parent 751022e743
commit 2ccad50f9a
31 changed files with 603 additions and 542 deletions

View file

@ -2,6 +2,7 @@ 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';
@ -44,12 +45,11 @@ class ActiveConversationsBlocMapCubit extends BlocMapCubit<TypedKey,
AsyncValue<ActiveConversationState>, ActiveConversationCubit>
with StateMapFollower<ChatListCubitState, TypedKey, proto.Chat> {
ActiveConversationsBlocMapCubit({
required UnlockedAccountInfo unlockedAccountInfo,
required ContactListCubit contactListCubit,
required AccountRecordCubit accountRecordCubit,
}) : _activeAccountInfo = unlockedAccountInfo,
_contactListCubit = contactListCubit,
_accountRecordCubit = accountRecordCubit;
required Locator locator,
}) : _locator = locator {
// Follow the chat list cubit
follow(locator<ChatListCubit>());
}
////////////////////////////////////////////////////////////////////////////
// Public Interface
@ -69,13 +69,20 @@ 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(
activeAccountInfo: _activeAccountInfo,
locator: _locator,
remoteIdentityPublicKey: remoteIdentityPublicKey,
localConversationRecordKey: localConversationRecordKey,
remoteConversationRecordKey: remoteConversationRecordKey,
)..watchAccountChanges(
_accountRecordCubit.stream, _accountRecordCubit.state);
_contactListCubit.followContactProfileChanges(
);
// 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(
localConversationRecordKey,
conversationCubit.stream.map((x) => x.map(
data: (d) => d.value.remoteConversation?.profile,
@ -112,7 +119,7 @@ class ActiveConversationsBlocMapCubit extends BlocMapCubit<TypedKey,
@override
Future<void> updateState(TypedKey key, proto.Chat value) async {
final contactList = _contactListCubit.state.state.asData?.value;
final contactList = _locator<ContactListCubit>().state.state.asData?.value;
if (contactList == null) {
await addState(key, const AsyncValue.loading());
return;
@ -129,7 +136,5 @@ class ActiveConversationsBlocMapCubit extends BlocMapCubit<TypedKey,
////
final UnlockedAccountInfo _activeAccountInfo;
final ContactListCubit _contactListCubit;
final AccountRecordCubit _accountRecordCubit;
final Locator _locator;
}

View file

@ -2,14 +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 'active_conversations_bloc_map_cubit.dart';
import '../../chat_list/cubits/chat_list_cubit.dart';
// Map of localConversationRecordKey to MessagesCubit
// Wraps a MessagesCubit to stream the latest messages to the state
@ -19,13 +19,11 @@ class ActiveSingleContactChatBlocMapCubit extends BlocMapCubit<TypedKey,
with
StateMapFollower<ActiveConversationsBlocMapState, TypedKey,
AsyncValue<ActiveConversationState>> {
ActiveSingleContactChatBlocMapCubit(
{required UnlockedAccountInfo unlockedAccountInfo,
required ContactListCubit contactListCubit,
required ChatListCubit chatListCubit})
: _activeAccountInfo = unlockedAccountInfo,
_contactListCubit = contactListCubit,
_chatListCubit = chatListCubit;
ActiveSingleContactChatBlocMapCubit({required Locator locator})
: _locator = locator {
// Follow the active conversations bloc map cubit
follow(locator<ActiveConversationsBlocMapCubit>());
}
Future<void> _addConversationMessages(
{required proto.Contact contact,
@ -35,7 +33,7 @@ class ActiveSingleContactChatBlocMapCubit extends BlocMapCubit<TypedKey,
add(() => MapEntry(
contact.localConversationRecordKey.toVeilid(),
SingleContactMessagesCubit(
activeAccountInfo: _activeAccountInfo,
locator: _locator,
remoteIdentityPublicKey: contact.identityPublicKey.toVeilid(),
localConversationRecordKey:
contact.localConversationRecordKey.toVeilid(),
@ -54,7 +52,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 = _contactListCubit.state.state.asData?.value;
final contactList = _locator<ContactListCubit>().state.state.asData?.value;
if (contactList == null) {
await addState(key, const AsyncValue.loading());
return;
@ -69,7 +67,7 @@ class ActiveSingleContactChatBlocMapCubit extends BlocMapCubit<TypedKey,
final contact = contactList[contactIndex].value;
// Get the chat object for this single contact chat
final chatList = _chatListCubit.state.state.asData?.value;
final chatList = _locator<ChatListCubit>().state.state.asData?.value;
if (chatList == null) {
await addState(key, const AsyncValue.loading());
return;
@ -95,7 +93,5 @@ class ActiveSingleContactChatBlocMapCubit extends BlocMapCubit<TypedKey,
////
final UnlockedAccountInfo _activeAccountInfo;
final ContactListCubit _contactListCubit;
final ChatListCubit _chatListCubit;
final Locator _locator;
}

View file

@ -10,6 +10,7 @@ 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';
@ -35,29 +36,31 @@ class ConversationState extends Equatable {
/// 1-1 chats
class ConversationCubit extends Cubit<AsyncValue<ConversationState>> {
ConversationCubit(
{required UnlockedAccountInfo activeAccountInfo,
{required Locator locator,
required TypedKey remoteIdentityPublicKey,
TypedKey? localConversationRecordKey,
TypedKey? remoteConversationRecordKey})
: _unlockedAccountInfo = activeAccountInfo,
: _locator = locator,
_localConversationRecordKey = localConversationRecordKey,
_remoteIdentityPublicKey = remoteIdentityPublicKey,
_remoteConversationRecordKey = remoteConversationRecordKey,
super(const AsyncValue.loading()) {
final unlockedAccountInfo =
_locator<ActiveAccountInfoCubit>().state.unlockedAccountInfo!;
_accountRecordKey = unlockedAccountInfo.accountRecordKey;
_identityWriter = unlockedAccountInfo.identityWriter;
if (_localConversationRecordKey != null) {
_initWait.add(() async {
await _setLocalConversation(() async {
final accountRecordKey = _unlockedAccountInfo
.userLogin.accountRecordInfo.accountRecord.recordKey;
// Open local record key if it is specified
final pool = DHTRecordPool.instance;
final crypto = await _cachedConversationCrypto();
final writer = _unlockedAccountInfo.identityWriter;
final writer = _identityWriter;
final record = await pool.openRecordWrite(
_localConversationRecordKey!, writer,
debugName: 'ConversationCubit::LocalConversation',
parent: accountRecordKey,
parent: _accountRecordKey,
crypto: crypto);
return record;
@ -68,15 +71,12 @@ class ConversationCubit extends Cubit<AsyncValue<ConversationState>> {
if (_remoteConversationRecordKey != null) {
_initWait.add(() async {
await _setRemoteConversation(() async {
final accountRecordKey = _unlockedAccountInfo
.userLogin.accountRecordInfo.accountRecord.recordKey;
// Open remote record key if it is specified
final pool = DHTRecordPool.instance;
final crypto = await _cachedConversationCrypto();
final record = await pool.openRecordRead(_remoteConversationRecordKey,
debugName: 'ConversationCubit::RemoteConversation',
parent: accountRecordKey,
parent: _accountRecordKey,
crypto: crypto);
return record;
});
@ -107,18 +107,19 @@ 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 proto.Profile profile,
required FutureOr<T> Function(DHTRecord) callback,
{required FutureOr<T> Function(DHTRecord) callback,
TypedKey? existingConversationRecordKey}) async {
assert(_localConversationRecordKey == null,
'must not have a local conversation yet');
final pool = DHTRecordPool.instance;
final accountRecordKey = _unlockedAccountInfo
.userLogin.accountRecordInfo.accountRecord.recordKey;
final crypto = await _cachedConversationCrypto();
final writer = _unlockedAccountInfo.identityWriter;
final account = _locator<AccountRecordCubit>().state.asData!.value;
final unlockedAccountInfo =
_locator<ActiveAccountInfoCubit>().state.unlockedAccountInfo!;
final accountRecordKey = unlockedAccountInfo.accountRecordKey;
final writer = unlockedAccountInfo.identityWriter;
// Open with SMPL scheme for identity writer
late final DHTRecord localConversationRecord;
@ -144,15 +145,13 @@ class ConversationCubit extends Cubit<AsyncValue<ConversationState>> {
.deleteScope((localConversation) async {
// Make messages log
return _initLocalMessages(
activeAccountInfo: _unlockedAccountInfo,
remoteIdentityPublicKey: _remoteIdentityPublicKey,
localConversationKey: localConversation.key,
callback: (messages) async {
// Create initial local conversation key contents
final conversation = proto.Conversation()
..profile = profile
..profile = account.profile
..superIdentityJson = jsonEncode(
_unlockedAccountInfo.localAccount.superIdentity.toJson())
unlockedAccountInfo.localAccount.superIdentity.toJson())
..messages = messages.recordKey.toProto();
// Write initial conversation to record
@ -340,14 +339,11 @@ class ConversationCubit extends Cubit<AsyncValue<ConversationState>> {
// Initialize local messages
Future<T> _initLocalMessages<T>({
required UnlockedAccountInfo activeAccountInfo,
required TypedKey remoteIdentityPublicKey,
required TypedKey localConversationKey,
required FutureOr<T> Function(DHTLog) callback,
}) async {
final crypto =
await activeAccountInfo.makeConversationCrypto(remoteIdentityPublicKey);
final writer = activeAccountInfo.identityWriter;
final crypto = await _cachedConversationCrypto();
final writer = _identityWriter;
return (await DHTLog.create(
debugName: 'ConversationCubit::initLocalMessages::LocalMessages',
@ -362,17 +358,19 @@ class ConversationCubit extends Cubit<AsyncValue<ConversationState>> {
if (conversationCrypto != null) {
return conversationCrypto;
}
conversationCrypto = await _unlockedAccountInfo
final unlockedAccountInfo =
_locator<ActiveAccountInfoCubit>().state.unlockedAccountInfo!;
conversationCrypto = await unlockedAccountInfo
.makeConversationCrypto(_remoteIdentityPublicKey);
_conversationCrypto = conversationCrypto;
return conversationCrypto;
}
////////////////////////////////////////////////////////////////////////////
// Fields
final UnlockedAccountInfo _unlockedAccountInfo;
final Locator _locator;
late final TypedKey _accountRecordKey;
late final KeyPair _identityWriter;
final TypedKey _remoteIdentityPublicKey;
TypedKey? _localConversationRecordKey;
final TypedKey? _remoteConversationRecordKey;