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

@ -8,7 +8,8 @@ import '../repository/account_repository.dart';
class AccountInfoCubit extends Cubit<AccountInfo> {
AccountInfoCubit(
AccountRepository accountRepository, TypedKey superIdentityRecordKey)
{required AccountRepository accountRepository,
required TypedKey superIdentityRecordKey})
: _accountRepository = accountRepository,
super(accountRepository.getAccountInfo(superIdentityRecordKey)!) {
// Subscribe to streams

View file

@ -1,6 +1,7 @@
export 'account_info_cubit.dart';
export 'account_record_cubit.dart';
export 'account_records_bloc_map_cubit.dart';
export 'active_local_account_cubit.dart';
export 'local_accounts_cubit.dart';
export 'per_account_collection_bloc_map_cubit.dart';
export 'per_account_collection_cubit.dart';
export 'user_logins_cubit.dart';

View file

@ -8,26 +8,30 @@ import '../../account_manager/account_manager.dart';
typedef AccountRecordsBlocMapState
= BlocMapState<TypedKey, AsyncValue<AccountRecordState>>;
/// Map of the logged in user accounts to their AccountRecordCubit
/// Map of the logged in user accounts to their PerAccountCollectionCubit
/// Ensures there is an single account record cubit for each logged in account
class AccountRecordsBlocMapCubit extends BlocMapCubit<TypedKey,
AsyncValue<AccountRecordState>, AccountRecordCubit>
class PerAccountCollectionBlocMapCubit extends BlocMapCubit<TypedKey,
PerAccountCollectionState, PerAccountCollectionCubit>
with StateMapFollower<LocalAccountsState, TypedKey, LocalAccount> {
AccountRecordsBlocMapCubit(
AccountRepository accountRepository, Locator locator)
: _accountRepository = accountRepository {
PerAccountCollectionBlocMapCubit({
required Locator locator,
required AccountRepository accountRepository,
}) : _locator = locator,
_accountRepository = accountRepository {
// Follow the local accounts cubit
follow(locator<LocalAccountsCubit>());
}
// Add account record cubit
Future<void> _addAccountRecordCubit(
Future<void> _addPerAccountCollectionCubit(
{required TypedKey superIdentityRecordKey}) async =>
add(() => MapEntry(
superIdentityRecordKey,
AccountRecordCubit(
accountRepository: _accountRepository,
superIdentityRecordKey: superIdentityRecordKey)));
PerAccountCollectionCubit(
locator: _locator,
accountInfoCubit: AccountInfoCubit(
accountRepository: _accountRepository,
superIdentityRecordKey: superIdentityRecordKey))));
/// StateFollower /////////////////////////
@ -36,10 +40,11 @@ class AccountRecordsBlocMapCubit extends BlocMapCubit<TypedKey,
@override
Future<void> updateState(TypedKey key, LocalAccount value) async {
await _addAccountRecordCubit(
await _addPerAccountCollectionCubit(
superIdentityRecordKey: value.superIdentity.recordKey);
}
////////////////////////////////////////////////////////////////////////////
final AccountRepository _accountRepository;
final Locator _locator;
}

View file

@ -10,6 +10,7 @@ import '../../chat/chat.dart';
import '../../chat_list/chat_list.dart';
import '../../contact_invitation/contact_invitation.dart';
import '../../contacts/contacts.dart';
import '../../conversation/conversation.dart';
import '../../proto/proto.dart' as proto;
import '../account_manager.dart';
@ -30,6 +31,14 @@ class PerAccountCollectionCubit extends Cubit<PerAccountCollectionState> {
await _accountRecordSubscription?.cancel();
await accountRecordCubit?.close();
await activeSingleContactChatBlocMapCubitUpdater.close();
await activeConversationsBlocMapCubitUpdater.close();
await activeChatCubitUpdater.close();
await waitingInvitationsBlocMapCubitUpdater.close();
await chatListCubitUpdater.close();
await contactListCubitUpdater.close();
await contactInvitationListCubitUpdater.close();
await super.close();
}
@ -95,48 +104,72 @@ class PerAccountCollectionCubit extends Cubit<PerAccountCollectionState> {
state.copyWith(avAccountRecordState: accountRecordCubit!.state);
// Get bloc parameters
final accountRecordKey = nextState.accountInfo.accountRecordKey;
final accountInfo = nextState.accountInfo;
// ContactInvitationListCubit
final contactInvitationListRecordPointer = nextState
.avAccountRecordState.asData?.value.contactInvitationRecords
.toVeilid();
contactInvitationListCubitUpdater.update(
final contactInvitationListCubit = contactInvitationListCubitUpdater.update(
contactInvitationListRecordPointer == null
? null
: (
collectionLocator,
accountRecordKey,
contactInvitationListRecordPointer
));
: (accountInfo, contactInvitationListRecordPointer));
// ContactListCubit
final contactListRecordPointer =
nextState.avAccountRecordState.asData?.value.contactList.toVeilid();
contactListCubitUpdater.update(contactListRecordPointer == null
? null
: (collectionLocator, accountRecordKey, contactListRecordPointer));
final contactListCubit = contactListCubitUpdater.update(
contactListRecordPointer == null
? null
: (accountInfo, contactListRecordPointer));
// WaitingInvitationsBlocMapCubit
waitingInvitationsBlocMapCubitUpdater.update(
nextState.avAccountRecordState.isData ? collectionLocator : null);
contactInvitationListCubit == null
? null
: (accountInfo, accountRecordCubit!, contactInvitationListCubit));
// ActiveChatCubit
activeChatCubitUpdater
final activeChatCubit = activeChatCubitUpdater
.update(nextState.avAccountRecordState.isData ? true : null);
// ChatListCubit
final chatListRecordPointer =
nextState.avAccountRecordState.asData?.value.chatList.toVeilid();
chatListCubitUpdater.update(chatListRecordPointer == null
? null
: (collectionLocator, accountRecordKey, chatListRecordPointer));
final chatListCubit = chatListCubitUpdater.update(
chatListRecordPointer == null || activeChatCubit == null
? null
: (accountInfo, chatListRecordPointer, activeChatCubit));
// ActiveConversationsBlocMapCubit
// xxx
final activeConversationsBlocMapCubit =
activeConversationsBlocMapCubitUpdater.update(
accountRecordCubit == null ||
chatListCubit == null ||
contactListCubit == null
? null
: (
accountInfo,
accountRecordCubit!,
chatListCubit,
contactListCubit
));
// ActiveSingleContactChatBlocMapCubit
activeSingleContactChatBlocMapCubitUpdater.update(
activeConversationsBlocMapCubit == null ||
chatListCubit == null ||
contactListCubit == null
? null
: (
accountInfo,
activeConversationsBlocMapCubit,
chatListCubit,
contactListCubit
));
return nextState;
}
@ -163,6 +196,12 @@ class PerAccountCollectionCubit extends Cubit<PerAccountCollectionState> {
if (T is ChatListCubit) {
return chatListCubitUpdater.bloc! as T;
}
if (T is ActiveConversationsBlocMapCubit) {
return activeConversationsBlocMapCubitUpdater.bloc! as T;
}
if (T is ActiveSingleContactChatBlocMapCubit) {
return activeSingleContactChatBlocMapCubitUpdater.bloc! as T;
}
return _locator<T>();
}
@ -178,32 +217,52 @@ class PerAccountCollectionCubit extends Cubit<PerAccountCollectionState> {
StreamSubscription<AsyncValue<AccountRecordState>>?
_accountRecordSubscription;
final contactInvitationListCubitUpdater = BlocUpdater<
ContactInvitationListCubit,
(Locator, TypedKey, OwnedDHTRecordPointer)>(
ContactInvitationListCubit, (AccountInfo, OwnedDHTRecordPointer)>(
create: (params) => ContactInvitationListCubit(
locator: params.$1,
accountRecordKey: params.$2,
contactInvitationListRecordPointer: params.$3,
accountInfo: params.$1,
contactInvitationListRecordPointer: params.$2,
));
final contactListCubitUpdater =
BlocUpdater<ContactListCubit, (Locator, TypedKey, OwnedDHTRecordPointer)>(
BlocUpdater<ContactListCubit, (AccountInfo, OwnedDHTRecordPointer)>(
create: (params) => ContactListCubit(
locator: params.$1,
accountRecordKey: params.$2,
contactListRecordPointer: params.$3,
));
final waitingInvitationsBlocMapCubitUpdater =
BlocUpdater<WaitingInvitationsBlocMapCubit, Locator>(
create: (params) => WaitingInvitationsBlocMapCubit(
locator: params,
accountInfo: params.$1,
contactListRecordPointer: params.$2,
));
final waitingInvitationsBlocMapCubitUpdater = BlocUpdater<
WaitingInvitationsBlocMapCubit,
(AccountInfo, AccountRecordCubit, ContactInvitationListCubit)>(
create: (params) => WaitingInvitationsBlocMapCubit(
accountInfo: params.$1,
accountRecordCubit: params.$2,
contactInvitationListCubit: params.$3));
final activeChatCubitUpdater =
BlocUpdater<ActiveChatCubit, bool>(create: (_) => ActiveChatCubit(null));
final chatListCubitUpdater =
BlocUpdater<ChatListCubit, (Locator, TypedKey, OwnedDHTRecordPointer)>(
create: (params) => ChatListCubit(
locator: params.$1,
accountRecordKey: params.$2,
chatListRecordPointer: params.$3,
));
final chatListCubitUpdater = BlocUpdater<ChatListCubit,
(AccountInfo, OwnedDHTRecordPointer, ActiveChatCubit)>(
create: (params) => ChatListCubit(
accountInfo: params.$1,
chatListRecordPointer: params.$2,
activeChatCubit: params.$3));
final activeConversationsBlocMapCubitUpdater = BlocUpdater<
ActiveConversationsBlocMapCubit,
(AccountInfo, AccountRecordCubit, ChatListCubit, ContactListCubit)>(
create: (params) => ActiveConversationsBlocMapCubit(
accountInfo: params.$1,
accountRecordCubit: params.$2,
chatListCubit: params.$3,
contactListCubit: params.$4));
final activeSingleContactChatBlocMapCubitUpdater = BlocUpdater<
ActiveSingleContactChatBlocMapCubit,
(
AccountInfo,
ActiveConversationsBlocMapCubit,
ChatListCubit,
ContactListCubit
)>(
create: (params) => ActiveSingleContactChatBlocMapCubit(
accountInfo: params.$1,
activeConversationsBlocMapCubit: params.$2,
chatListCubit: params.$3,
contactListCubit: params.$4,
));
}

View file

@ -16,20 +16,17 @@ enum AccountInfoStatus {
class AccountInfo extends Equatable {
const AccountInfo({
required this.status,
required this.active,
required this.localAccount,
required this.userLogin,
});
final AccountInfoStatus status;
final bool active;
final LocalAccount localAccount;
final UserLogin? userLogin;
@override
List<Object?> get props => [
status,
active,
localAccount,
userLogin,
];

View file

@ -93,10 +93,6 @@ class AccountRepository {
}
AccountInfo? getAccountInfo(TypedKey superIdentityRecordKey) {
// Get active account if we have one
final activeLocalAccount = getActiveLocalAccount();
final active = superIdentityRecordKey == activeLocalAccount;
// Get which local account we want to fetch the profile for
final localAccount = fetchLocalAccount(superIdentityRecordKey);
if (localAccount == null) {
@ -109,7 +105,6 @@ class AccountRepository {
// Account was locked
return AccountInfo(
status: AccountInfoStatus.accountLocked,
active: active,
localAccount: localAccount,
userLogin: null,
);
@ -118,7 +113,6 @@ class AccountRepository {
// Got account, decrypted and decoded
return AccountInfo(
status: AccountInfoStatus.accountUnlocked,
active: active,
localAccount: localAccount,
userLogin: userLogin,
);

View file

@ -116,13 +116,13 @@ class _EditAccountPageState extends State<EditAccountPage> {
});
try {
// Look up account cubit for this specific account
final accountRecordsCubit =
context.read<AccountRecordsBlocMapCubit>();
await accountRecordsCubit.operateAsync(
final perAccountCollectionCubit =
context.read<PerAccountCollectionBlocMapCubit>();
await perAccountCollectionCubit.operateAsync(
widget.superIdentityRecordKey, closure: (c) async {
// Update account profile DHT record
// This triggers ConversationCubits to update
await c.updateProfile(newProfile);
await c.accountRecordCubit!.updateProfile(newProfile);
});
// Update local account profile