diff --git a/lib/account_manager/cubits/per_account_collection_bloc_map_cubit.dart b/lib/account_manager/cubits/per_account_collection_bloc_map_cubit.dart index 8810376..f1df6e6 100644 --- a/lib/account_manager/cubits/per_account_collection_bloc_map_cubit.dart +++ b/lib/account_manager/cubits/per_account_collection_bloc_map_cubit.dart @@ -1,12 +1,11 @@ -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'; -typedef AccountRecordsBlocMapState - = BlocMapState>; +typedef PerAccountCollectionBlocMapState + = BlocMapState; /// Map of the logged in user accounts to their PerAccountCollectionCubit /// Ensures there is an single account record cubit for each logged in account diff --git a/lib/account_manager/cubits/per_account_collection_cubit.dart b/lib/account_manager/cubits/per_account_collection_cubit.dart index b67e234..0678f4b 100644 --- a/lib/account_manager/cubits/per_account_collection_cubit.dart +++ b/lib/account_manager/cubits/per_account_collection_cubit.dart @@ -55,11 +55,26 @@ class PerAccountCollectionCubit extends Cubit { PerAccountCollectionState( accountInfo: accountInfoCubit.state, avAccountRecordState: const AsyncValue.loading(), - contactInvitationListCubit: null); + contactInvitationListCubit: null, + accountInfoCubit: null, + accountRecordCubit: null, + contactListCubit: null, + waitingInvitationsBlocMapCubit: null, + activeChatCubit: null, + chatListCubit: null, + activeConversationsBlocMapCubit: null, + activeSingleContactChatBlocMapCubit: null); Future _followAccountInfoState(AccountInfo accountInfo) async { + // If state hasn't changed just return + if (state.accountInfo == accountInfo) { + return; + } + + // Get the next state var nextState = state.copyWith(accountInfo: accountInfo); + // Update AccountRecordCubit if (accountInfo.userLogin == null) { /////////////// Not logged in ///////////////// @@ -67,7 +82,7 @@ class PerAccountCollectionCubit extends Cubit { await _accountRecordSubscription?.cancel(); _accountRecordSubscription = null; - // Update state + // Update state to 'loading' nextState = _updateAccountRecordState(nextState, const AsyncValue.loading()); emit(nextState); @@ -78,12 +93,12 @@ class PerAccountCollectionCubit extends Cubit { } else { ///////////////// Logged in /////////////////// - // AccountRecordCubit + // Create AccountRecordCubit accountRecordCubit ??= AccountRecordCubit( localAccount: accountInfo.localAccount, userLogin: accountInfo.userLogin!); - // Update State + // Update state to value nextState = _updateAccountRecordState(nextState, accountRecordCubit!.state); emit(nextState); @@ -98,17 +113,17 @@ class PerAccountCollectionCubit extends Cubit { PerAccountCollectionState _updateAccountRecordState( PerAccountCollectionState prevState, - AsyncValue avAccountRecordState) { + AsyncValue? avAccountRecordState) { // Get next state final nextState = - state.copyWith(avAccountRecordState: accountRecordCubit!.state); + state.copyWith(avAccountRecordState: avAccountRecordState); // Get bloc parameters final accountInfo = nextState.accountInfo; // ContactInvitationListCubit final contactInvitationListRecordPointer = nextState - .avAccountRecordState.asData?.value.contactInvitationRecords + .avAccountRecordState?.asData?.value.contactInvitationRecords .toVeilid(); final contactInvitationListCubit = contactInvitationListCubitUpdater.update( @@ -118,7 +133,7 @@ class PerAccountCollectionCubit extends Cubit { // ContactListCubit final contactListRecordPointer = - nextState.avAccountRecordState.asData?.value.contactList.toVeilid(); + nextState.avAccountRecordState?.asData?.value.contactList.toVeilid(); final contactListCubit = contactListCubitUpdater.update( contactListRecordPointer == null @@ -126,18 +141,18 @@ class PerAccountCollectionCubit extends Cubit { : (accountInfo, contactListRecordPointer)); // WaitingInvitationsBlocMapCubit - waitingInvitationsBlocMapCubitUpdater.update( - contactInvitationListCubit == null + final waitingInvitationsBlocMapCubit = waitingInvitationsBlocMapCubitUpdater + .update(contactInvitationListCubit == null ? null : (accountInfo, accountRecordCubit!, contactInvitationListCubit)); // ActiveChatCubit - final activeChatCubit = activeChatCubitUpdater - .update(nextState.avAccountRecordState.isData ? true : null); + final activeChatCubit = activeChatCubitUpdater.update( + (nextState.avAccountRecordState?.isData ?? false) ? true : null); // ChatListCubit final chatListRecordPointer = - nextState.avAccountRecordState.asData?.value.chatList.toVeilid(); + nextState.avAccountRecordState?.asData?.value.chatList.toVeilid(); final chatListCubit = chatListCubitUpdater.update( chatListRecordPointer == null || activeChatCubit == null @@ -159,19 +174,31 @@ class PerAccountCollectionCubit extends Cubit { )); // ActiveSingleContactChatBlocMapCubit - activeSingleContactChatBlocMapCubitUpdater.update( - activeConversationsBlocMapCubit == null || - chatListCubit == null || - contactListCubit == null - ? null - : ( - accountInfo, - activeConversationsBlocMapCubit, - chatListCubit, - contactListCubit - )); + final activeSingleContactChatBlocMapCubit = + activeSingleContactChatBlocMapCubitUpdater.update( + activeConversationsBlocMapCubit == null || + chatListCubit == null || + contactListCubit == null + ? null + : ( + accountInfo, + activeConversationsBlocMapCubit, + chatListCubit, + contactListCubit + )); - return nextState; + // Update available blocs in our state + return nextState.copyWith( + contactInvitationListCubit: contactInvitationListCubit, + accountInfoCubit: accountInfoCubit, + accountRecordCubit: accountRecordCubit, + contactListCubit: contactListCubit, + waitingInvitationsBlocMapCubit: waitingInvitationsBlocMapCubit, + activeChatCubit: activeChatCubit, + chatListCubit: chatListCubit, + activeConversationsBlocMapCubit: activeConversationsBlocMapCubit, + activeSingleContactChatBlocMapCubit: + activeSingleContactChatBlocMapCubit); } T collectionLocator() { diff --git a/lib/account_manager/models/per_account_collection_state/per_account_collection_state.dart b/lib/account_manager/models/per_account_collection_state/per_account_collection_state.dart index 9794784..7fc8f0d 100644 --- a/lib/account_manager/models/per_account_collection_state/per_account_collection_state.dart +++ b/lib/account_manager/models/per_account_collection_state/per_account_collection_state.dart @@ -1,7 +1,13 @@ import 'package:async_tools/async_tools.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; +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' show Account; import '../../account_manager.dart'; @@ -9,9 +15,45 @@ part 'per_account_collection_state.freezed.dart'; @freezed class PerAccountCollectionState with _$PerAccountCollectionState { - const factory PerAccountCollectionState( - {required AccountInfo accountInfo, - required AsyncValue avAccountRecordState, - required ContactInvitationListCubit? contactInvitationListCubit}) = - _PerAccountCollectionState; + const factory PerAccountCollectionState({ + required AccountInfo accountInfo, + required AsyncValue? avAccountRecordState, + required AccountInfoCubit? accountInfoCubit, + required AccountRecordCubit? accountRecordCubit, + required ContactInvitationListCubit? contactInvitationListCubit, + required ContactListCubit? contactListCubit, + required WaitingInvitationsBlocMapCubit? waitingInvitationsBlocMapCubit, + required ActiveChatCubit? activeChatCubit, + required ChatListCubit? chatListCubit, + required ActiveConversationsBlocMapCubit? activeConversationsBlocMapCubit, + required ActiveSingleContactChatBlocMapCubit? + activeSingleContactChatBlocMapCubit, + }) = _PerAccountCollectionState; +} + +extension PerAccountCollectionStateExt on PerAccountCollectionState { + bool get isReady => + avAccountRecordState != null && + avAccountRecordState!.isData && + accountInfoCubit != null && + accountRecordCubit != null && + contactInvitationListCubit != null && + contactListCubit != null && + waitingInvitationsBlocMapCubit != null && + activeChatCubit != null && + chatListCubit != null && + activeConversationsBlocMapCubit != null && + activeSingleContactChatBlocMapCubit != null; + + Widget provide({required Widget child}) => MultiBlocProvider(providers: [ + BlocProvider.value(value: accountInfoCubit!), + BlocProvider.value(value: accountRecordCubit!), + BlocProvider.value(value: contactInvitationListCubit!), + BlocProvider.value(value: contactListCubit!), + BlocProvider.value(value: waitingInvitationsBlocMapCubit!), + BlocProvider.value(value: activeChatCubit!), + BlocProvider.value(value: chatListCubit!), + BlocProvider.value(value: activeConversationsBlocMapCubit!), + BlocProvider.value(value: activeSingleContactChatBlocMapCubit!), + ], child: child); } diff --git a/lib/account_manager/models/per_account_collection_state/per_account_collection_state.freezed.dart b/lib/account_manager/models/per_account_collection_state/per_account_collection_state.freezed.dart index d49f42a..8dcc549 100644 --- a/lib/account_manager/models/per_account_collection_state/per_account_collection_state.freezed.dart +++ b/lib/account_manager/models/per_account_collection_state/per_account_collection_state.freezed.dart @@ -17,10 +17,23 @@ final _privateConstructorUsedError = UnsupportedError( /// @nodoc mixin _$PerAccountCollectionState { AccountInfo get accountInfo => throw _privateConstructorUsedError; - AsyncValue get avAccountRecordState => + AsyncValue? get avAccountRecordState => + throw _privateConstructorUsedError; + AccountInfoCubit? get accountInfoCubit => throw _privateConstructorUsedError; + AccountRecordCubit? get accountRecordCubit => throw _privateConstructorUsedError; ContactInvitationListCubit? get contactInvitationListCubit => throw _privateConstructorUsedError; + ContactListCubit? get contactListCubit => throw _privateConstructorUsedError; + WaitingInvitationsBlocMapCubit? get waitingInvitationsBlocMapCubit => + throw _privateConstructorUsedError; + ActiveChatCubit? get activeChatCubit => throw _privateConstructorUsedError; + ChatListCubit? get chatListCubit => throw _privateConstructorUsedError; + ActiveConversationsBlocMapCubit? get activeConversationsBlocMapCubit => + throw _privateConstructorUsedError; + ActiveSingleContactChatBlocMapCubit? + get activeSingleContactChatBlocMapCubit => + throw _privateConstructorUsedError; @JsonKey(ignore: true) $PerAccountCollectionStateCopyWith get copyWith => @@ -35,10 +48,19 @@ abstract class $PerAccountCollectionStateCopyWith<$Res> { @useResult $Res call( {AccountInfo accountInfo, - AsyncValue avAccountRecordState, - ContactInvitationListCubit? contactInvitationListCubit}); + AsyncValue? avAccountRecordState, + AccountInfoCubit? accountInfoCubit, + AccountRecordCubit? accountRecordCubit, + ContactInvitationListCubit? contactInvitationListCubit, + ContactListCubit? contactListCubit, + WaitingInvitationsBlocMapCubit? waitingInvitationsBlocMapCubit, + ActiveChatCubit? activeChatCubit, + ChatListCubit? chatListCubit, + ActiveConversationsBlocMapCubit? activeConversationsBlocMapCubit, + ActiveSingleContactChatBlocMapCubit? + activeSingleContactChatBlocMapCubit}); - $AsyncValueCopyWith get avAccountRecordState; + $AsyncValueCopyWith? get avAccountRecordState; } /// @nodoc @@ -56,29 +78,75 @@ class _$PerAccountCollectionStateCopyWithImpl<$Res, @override $Res call({ Object? accountInfo = null, - Object? avAccountRecordState = null, + Object? avAccountRecordState = freezed, + Object? accountInfoCubit = freezed, + Object? accountRecordCubit = freezed, Object? contactInvitationListCubit = freezed, + Object? contactListCubit = freezed, + Object? waitingInvitationsBlocMapCubit = freezed, + Object? activeChatCubit = freezed, + Object? chatListCubit = freezed, + Object? activeConversationsBlocMapCubit = freezed, + Object? activeSingleContactChatBlocMapCubit = freezed, }) { return _then(_value.copyWith( accountInfo: null == accountInfo ? _value.accountInfo : accountInfo // ignore: cast_nullable_to_non_nullable as AccountInfo, - avAccountRecordState: null == avAccountRecordState + avAccountRecordState: freezed == avAccountRecordState ? _value.avAccountRecordState : avAccountRecordState // ignore: cast_nullable_to_non_nullable - as AsyncValue, + as AsyncValue?, + accountInfoCubit: freezed == accountInfoCubit + ? _value.accountInfoCubit + : accountInfoCubit // ignore: cast_nullable_to_non_nullable + as AccountInfoCubit?, + accountRecordCubit: freezed == accountRecordCubit + ? _value.accountRecordCubit + : accountRecordCubit // ignore: cast_nullable_to_non_nullable + as AccountRecordCubit?, contactInvitationListCubit: freezed == contactInvitationListCubit ? _value.contactInvitationListCubit : contactInvitationListCubit // ignore: cast_nullable_to_non_nullable as ContactInvitationListCubit?, + contactListCubit: freezed == contactListCubit + ? _value.contactListCubit + : contactListCubit // ignore: cast_nullable_to_non_nullable + as ContactListCubit?, + waitingInvitationsBlocMapCubit: freezed == waitingInvitationsBlocMapCubit + ? _value.waitingInvitationsBlocMapCubit + : waitingInvitationsBlocMapCubit // ignore: cast_nullable_to_non_nullable + as WaitingInvitationsBlocMapCubit?, + activeChatCubit: freezed == activeChatCubit + ? _value.activeChatCubit + : activeChatCubit // ignore: cast_nullable_to_non_nullable + as ActiveChatCubit?, + chatListCubit: freezed == chatListCubit + ? _value.chatListCubit + : chatListCubit // ignore: cast_nullable_to_non_nullable + as ChatListCubit?, + activeConversationsBlocMapCubit: freezed == + activeConversationsBlocMapCubit + ? _value.activeConversationsBlocMapCubit + : activeConversationsBlocMapCubit // ignore: cast_nullable_to_non_nullable + as ActiveConversationsBlocMapCubit?, + activeSingleContactChatBlocMapCubit: freezed == + activeSingleContactChatBlocMapCubit + ? _value.activeSingleContactChatBlocMapCubit + : activeSingleContactChatBlocMapCubit // ignore: cast_nullable_to_non_nullable + as ActiveSingleContactChatBlocMapCubit?, ) as $Val); } @override @pragma('vm:prefer-inline') - $AsyncValueCopyWith get avAccountRecordState { - return $AsyncValueCopyWith(_value.avAccountRecordState, + $AsyncValueCopyWith? get avAccountRecordState { + if (_value.avAccountRecordState == null) { + return null; + } + + return $AsyncValueCopyWith(_value.avAccountRecordState!, (value) { return _then(_value.copyWith(avAccountRecordState: value) as $Val); }); @@ -96,11 +164,20 @@ abstract class _$$PerAccountCollectionStateImplCopyWith<$Res> @useResult $Res call( {AccountInfo accountInfo, - AsyncValue avAccountRecordState, - ContactInvitationListCubit? contactInvitationListCubit}); + AsyncValue? avAccountRecordState, + AccountInfoCubit? accountInfoCubit, + AccountRecordCubit? accountRecordCubit, + ContactInvitationListCubit? contactInvitationListCubit, + ContactListCubit? contactListCubit, + WaitingInvitationsBlocMapCubit? waitingInvitationsBlocMapCubit, + ActiveChatCubit? activeChatCubit, + ChatListCubit? chatListCubit, + ActiveConversationsBlocMapCubit? activeConversationsBlocMapCubit, + ActiveSingleContactChatBlocMapCubit? + activeSingleContactChatBlocMapCubit}); @override - $AsyncValueCopyWith get avAccountRecordState; + $AsyncValueCopyWith? get avAccountRecordState; } /// @nodoc @@ -117,22 +194,64 @@ class __$$PerAccountCollectionStateImplCopyWithImpl<$Res> @override $Res call({ Object? accountInfo = null, - Object? avAccountRecordState = null, + Object? avAccountRecordState = freezed, + Object? accountInfoCubit = freezed, + Object? accountRecordCubit = freezed, Object? contactInvitationListCubit = freezed, + Object? contactListCubit = freezed, + Object? waitingInvitationsBlocMapCubit = freezed, + Object? activeChatCubit = freezed, + Object? chatListCubit = freezed, + Object? activeConversationsBlocMapCubit = freezed, + Object? activeSingleContactChatBlocMapCubit = freezed, }) { return _then(_$PerAccountCollectionStateImpl( accountInfo: null == accountInfo ? _value.accountInfo : accountInfo // ignore: cast_nullable_to_non_nullable as AccountInfo, - avAccountRecordState: null == avAccountRecordState + avAccountRecordState: freezed == avAccountRecordState ? _value.avAccountRecordState : avAccountRecordState // ignore: cast_nullable_to_non_nullable - as AsyncValue, + as AsyncValue?, + accountInfoCubit: freezed == accountInfoCubit + ? _value.accountInfoCubit + : accountInfoCubit // ignore: cast_nullable_to_non_nullable + as AccountInfoCubit?, + accountRecordCubit: freezed == accountRecordCubit + ? _value.accountRecordCubit + : accountRecordCubit // ignore: cast_nullable_to_non_nullable + as AccountRecordCubit?, contactInvitationListCubit: freezed == contactInvitationListCubit ? _value.contactInvitationListCubit : contactInvitationListCubit // ignore: cast_nullable_to_non_nullable as ContactInvitationListCubit?, + contactListCubit: freezed == contactListCubit + ? _value.contactListCubit + : contactListCubit // ignore: cast_nullable_to_non_nullable + as ContactListCubit?, + waitingInvitationsBlocMapCubit: freezed == waitingInvitationsBlocMapCubit + ? _value.waitingInvitationsBlocMapCubit + : waitingInvitationsBlocMapCubit // ignore: cast_nullable_to_non_nullable + as WaitingInvitationsBlocMapCubit?, + activeChatCubit: freezed == activeChatCubit + ? _value.activeChatCubit + : activeChatCubit // ignore: cast_nullable_to_non_nullable + as ActiveChatCubit?, + chatListCubit: freezed == chatListCubit + ? _value.chatListCubit + : chatListCubit // ignore: cast_nullable_to_non_nullable + as ChatListCubit?, + activeConversationsBlocMapCubit: freezed == + activeConversationsBlocMapCubit + ? _value.activeConversationsBlocMapCubit + : activeConversationsBlocMapCubit // ignore: cast_nullable_to_non_nullable + as ActiveConversationsBlocMapCubit?, + activeSingleContactChatBlocMapCubit: freezed == + activeSingleContactChatBlocMapCubit + ? _value.activeSingleContactChatBlocMapCubit + : activeSingleContactChatBlocMapCubit // ignore: cast_nullable_to_non_nullable + as ActiveSingleContactChatBlocMapCubit?, )); } } @@ -143,18 +262,43 @@ class _$PerAccountCollectionStateImpl implements _PerAccountCollectionState { const _$PerAccountCollectionStateImpl( {required this.accountInfo, required this.avAccountRecordState, - required this.contactInvitationListCubit}); + required this.accountInfoCubit, + required this.accountRecordCubit, + required this.contactInvitationListCubit, + required this.contactListCubit, + required this.waitingInvitationsBlocMapCubit, + required this.activeChatCubit, + required this.chatListCubit, + required this.activeConversationsBlocMapCubit, + required this.activeSingleContactChatBlocMapCubit}); @override final AccountInfo accountInfo; @override - final AsyncValue avAccountRecordState; + final AsyncValue? avAccountRecordState; + @override + final AccountInfoCubit? accountInfoCubit; + @override + final AccountRecordCubit? accountRecordCubit; @override final ContactInvitationListCubit? contactInvitationListCubit; + @override + final ContactListCubit? contactListCubit; + @override + final WaitingInvitationsBlocMapCubit? waitingInvitationsBlocMapCubit; + @override + final ActiveChatCubit? activeChatCubit; + @override + final ChatListCubit? chatListCubit; + @override + final ActiveConversationsBlocMapCubit? activeConversationsBlocMapCubit; + @override + final ActiveSingleContactChatBlocMapCubit? + activeSingleContactChatBlocMapCubit; @override String toString() { - return 'PerAccountCollectionState(accountInfo: $accountInfo, avAccountRecordState: $avAccountRecordState, contactInvitationListCubit: $contactInvitationListCubit)'; + return 'PerAccountCollectionState(accountInfo: $accountInfo, avAccountRecordState: $avAccountRecordState, accountInfoCubit: $accountInfoCubit, accountRecordCubit: $accountRecordCubit, contactInvitationListCubit: $contactInvitationListCubit, contactListCubit: $contactListCubit, waitingInvitationsBlocMapCubit: $waitingInvitationsBlocMapCubit, activeChatCubit: $activeChatCubit, chatListCubit: $chatListCubit, activeConversationsBlocMapCubit: $activeConversationsBlocMapCubit, activeSingleContactChatBlocMapCubit: $activeSingleContactChatBlocMapCubit)'; } @override @@ -166,15 +310,48 @@ class _$PerAccountCollectionStateImpl implements _PerAccountCollectionState { other.accountInfo == accountInfo) && (identical(other.avAccountRecordState, avAccountRecordState) || other.avAccountRecordState == avAccountRecordState) && + (identical(other.accountInfoCubit, accountInfoCubit) || + other.accountInfoCubit == accountInfoCubit) && + (identical(other.accountRecordCubit, accountRecordCubit) || + other.accountRecordCubit == accountRecordCubit) && (identical(other.contactInvitationListCubit, contactInvitationListCubit) || other.contactInvitationListCubit == - contactInvitationListCubit)); + contactInvitationListCubit) && + (identical(other.contactListCubit, contactListCubit) || + other.contactListCubit == contactListCubit) && + (identical(other.waitingInvitationsBlocMapCubit, + waitingInvitationsBlocMapCubit) || + other.waitingInvitationsBlocMapCubit == + waitingInvitationsBlocMapCubit) && + (identical(other.activeChatCubit, activeChatCubit) || + other.activeChatCubit == activeChatCubit) && + (identical(other.chatListCubit, chatListCubit) || + other.chatListCubit == chatListCubit) && + (identical(other.activeConversationsBlocMapCubit, + activeConversationsBlocMapCubit) || + other.activeConversationsBlocMapCubit == + activeConversationsBlocMapCubit) && + (identical(other.activeSingleContactChatBlocMapCubit, + activeSingleContactChatBlocMapCubit) || + other.activeSingleContactChatBlocMapCubit == + activeSingleContactChatBlocMapCubit)); } @override - int get hashCode => Object.hash(runtimeType, accountInfo, - avAccountRecordState, contactInvitationListCubit); + int get hashCode => Object.hash( + runtimeType, + accountInfo, + avAccountRecordState, + accountInfoCubit, + accountRecordCubit, + contactInvitationListCubit, + contactListCubit, + waitingInvitationsBlocMapCubit, + activeChatCubit, + chatListCubit, + activeConversationsBlocMapCubit, + activeSingleContactChatBlocMapCubit); @JsonKey(ignore: true) @override @@ -186,18 +363,45 @@ class _$PerAccountCollectionStateImpl implements _PerAccountCollectionState { abstract class _PerAccountCollectionState implements PerAccountCollectionState { const factory _PerAccountCollectionState( - {required final AccountInfo accountInfo, - required final AsyncValue avAccountRecordState, - required final ContactInvitationListCubit? - contactInvitationListCubit}) = _$PerAccountCollectionStateImpl; + {required final AccountInfo accountInfo, + required final AsyncValue? avAccountRecordState, + required final AccountInfoCubit? accountInfoCubit, + required final AccountRecordCubit? accountRecordCubit, + required final ContactInvitationListCubit? contactInvitationListCubit, + required final ContactListCubit? contactListCubit, + required final WaitingInvitationsBlocMapCubit? + waitingInvitationsBlocMapCubit, + required final ActiveChatCubit? activeChatCubit, + required final ChatListCubit? chatListCubit, + required final ActiveConversationsBlocMapCubit? + activeConversationsBlocMapCubit, + required final ActiveSingleContactChatBlocMapCubit? + activeSingleContactChatBlocMapCubit}) = + _$PerAccountCollectionStateImpl; @override AccountInfo get accountInfo; @override - AsyncValue get avAccountRecordState; + AsyncValue? get avAccountRecordState; + @override + AccountInfoCubit? get accountInfoCubit; + @override + AccountRecordCubit? get accountRecordCubit; @override ContactInvitationListCubit? get contactInvitationListCubit; @override + ContactListCubit? get contactListCubit; + @override + WaitingInvitationsBlocMapCubit? get waitingInvitationsBlocMapCubit; + @override + ActiveChatCubit? get activeChatCubit; + @override + ChatListCubit? get chatListCubit; + @override + ActiveConversationsBlocMapCubit? get activeConversationsBlocMapCubit; + @override + ActiveSingleContactChatBlocMapCubit? get activeSingleContactChatBlocMapCubit; + @override @JsonKey(ignore: true) _$$PerAccountCollectionStateImplCopyWith<_$PerAccountCollectionStateImpl> get copyWith => throw _privateConstructorUsedError; diff --git a/lib/account_manager/views/edit_account_page.dart b/lib/account_manager/views/edit_account_page.dart index 986fd0b..468bf48 100644 --- a/lib/account_manager/views/edit_account_page.dart +++ b/lib/account_manager/views/edit_account_page.dart @@ -116,14 +116,11 @@ class _EditAccountPageState extends State { }); try { // Look up account cubit for this specific account - final perAccountCollectionCubit = - context.read(); - await perAccountCollectionCubit.operateAsync( - widget.superIdentityRecordKey, closure: (c) async { - // Update account profile DHT record - // This triggers ConversationCubits to update - await c.accountRecordCubit!.updateProfile(newProfile); - }); + final accountRecordCubit = context.read(); + + // Update account profile DHT record + // This triggers ConversationCubits to update + await accountRecordCubit.updateProfile(newProfile); // Update local account profile await AccountRepository.instance.editAccountProfile( diff --git a/lib/layout/home/drawer_menu/drawer_menu.dart b/lib/layout/home/drawer_menu/drawer_menu.dart index f68a277..1e56c4b 100644 --- a/lib/layout/home/drawer_menu/drawer_menu.dart +++ b/lib/layout/home/drawer_menu/drawer_menu.dart @@ -105,7 +105,8 @@ class _DrawerMenuState extends State { Widget _getAccountList( {required IList localAccounts, required TypedKey? activeLocalAccount, - required AccountRecordsBlocMapState accountRecords}) { + required PerAccountCollectionBlocMapState + perAccountCollectionBlocMapState}) { final theme = Theme.of(context); final scaleScheme = theme.extension()!; @@ -116,11 +117,13 @@ class _DrawerMenuState extends State { final superIdentityRecordKey = la.superIdentity.recordKey; // See if this account is logged in - final acctRecord = accountRecords.get(superIdentityRecordKey); - if (acctRecord != null) { + final avAccountRecordState = perAccountCollectionBlocMapState + .get(superIdentityRecordKey) + ?.avAccountRecordState; + if (avAccountRecordState != null) { // Account is logged in final scale = theme.extension()!.tertiaryScale; - final loggedInAccount = acctRecord.when( + final loggedInAccount = avAccountRecordState.when( data: (value) => _makeAccountWidget( name: value.profile.name, scale: scale, @@ -233,7 +236,7 @@ class _DrawerMenuState extends State { final scale = theme.extension()!; //final textTheme = theme.textTheme; final localAccounts = context.watch().state; - final accountRecords = + final perAccountCollectionBlocMapState = context.watch().state; final activeLocalAccount = context.watch().state; final gradient = LinearGradient( @@ -278,7 +281,7 @@ class _DrawerMenuState extends State { _getAccountList( localAccounts: localAccounts, activeLocalAccount: activeLocalAccount, - accountRecords: accountRecords), + perAccountCollectionBlocMapState: perAccountCollectionBlocMapState), _getBottomButtons(), const Spacer(), Row(children: [ diff --git a/lib/layout/home/home_screen.dart b/lib/layout/home/home_screen.dart index ddbb99e..16d484d 100644 --- a/lib/layout/home/home_screen.dart +++ b/lib/layout/home/home_screen.dart @@ -9,11 +9,8 @@ import 'package:veilid_support/veilid_support.dart'; import '../../account_manager/account_manager.dart'; 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 '../../theme/theme.dart'; import '../../tools/tools.dart'; import 'active_account_page_controller_wrapper.dart'; @@ -98,113 +95,39 @@ class HomeScreenState extends State { return const HomeAccountReadyMain(); } - Widget _buildUnlockedAccount(BuildContext context) { - final accountRecordKey = context.select( - (c) => c.state.unlockedAccountInfo!.accountRecordKey); - final contactListRecordPointer = - context.select( - (c) => c.state.asData?.value.contactList.toVeilid()); - final contactInvitationListRecordPointer = - context.select( - (c) => c.state.asData?.value.contactInvitationRecords.toVeilid()); - final chatListRecordPointer = - context.select( - (c) => c.state.asData?.value.chatList.toVeilid()); + Widget _buildAccount(BuildContext context, TypedKey superIdentityRecordKey, + PerAccountCollectionState perAccountCollectionState) { + switch (perAccountCollectionState.accountInfo.status) { + case AccountInfoStatus.accountInvalid: + return const HomeAccountInvalid(); + case AccountInfoStatus.accountLocked: + return const HomeAccountLocked(); + case AccountInfoStatus.accountUnlocked: + // Are we ready to render? + if (!perAccountCollectionState.isReady) { + return waitingPage(); + } - if (contactListRecordPointer == null || - contactInvitationListRecordPointer == null || - chatListRecordPointer == null) { - return waitingPage(); - } - - return MultiBlocProvider( - providers: [ - // Contact Cubits - BlocProvider( - create: (context) => ContactInvitationListCubit( - locator: context.read, - accountRecordKey: accountRecordKey, - contactInvitationListRecordPointer: - contactInvitationListRecordPointer, - )), - BlocProvider( - create: (context) => ContactListCubit( - locator: context.read, - accountRecordKey: accountRecordKey, - contactListRecordPointer: contactListRecordPointer)), - BlocProvider( - create: (context) => WaitingInvitationsBlocMapCubit( - locator: context.read, - )), - // Chat Cubits - BlocProvider( - create: (context) => ActiveChatCubit( - null, - )), - BlocProvider( - create: (context) => ChatListCubit( - locator: context.read, - accountRecordKey: accountRecordKey, - chatListRecordPointer: chatListRecordPointer)), - // Conversation Cubits - BlocProvider( - create: (context) => ActiveConversationsBlocMapCubit( - locator: context.read, - )), - BlocProvider( - create: (context) => ActiveSingleContactChatBlocMapCubit( - locator: context.read, - )), - ], - child: MultiBlocListener(listeners: [ + // Re-export all ready blocs to the account display subtree + return perAccountCollectionState.provide( + child: MultiBlocListener(listeners: [ BlocListener( listener: _invitationStatusListener, ) ], child: Builder(builder: _buildAccountReadyDeviceSpecific))); + } } - Widget _buildAccount(BuildContext context, TypedKey superIdentityRecordKey, - PerAccountCollectionCubit perAccountCollectionCubit) => - BlocBuilder( - key: ValueKey(superIdentityRecordKey), - bloc: perAccountCollectionCubit, - builder: (context, state) { - - - switch (state.accountInfo.status) { - case AccountInfoStatus.accountInvalid: - return const HomeAccountInvalid(); - case AccountInfoStatus.accountLocked: - return const HomeAccountLocked(); - case AccountInfoStatus.accountUnlocked: - - // Get the current active account record cubit - final activeAccountRecordCubit = context.select< - PerAccountCollectionBlocMapCubit, - AccountRecordCubit?>( - (c) => c.tryOperate(superIdentityRecordKey, - closure: (x) => x)); - if (activeAccountRecordCubit == null) { - return waitingPage(); - } - - return MultiBlocProvider(providers: [ - BlocProvider.value( - value: activeAccountRecordCubit), - ], child: Builder(builder: _buildUnlockedAccount)); - } - }); - }; - Widget _buildAccountPageView(BuildContext context) { final localAccounts = context.watch().state; - final activeLocalAccountCubit = context.watch(); - final perAccountCollectionBlocMapCubit = - context.watch(); + final activeLocalAccountCubit = + context.watch().state; + final perAccountCollectionBlocMapState = + context.watch().state; final activeIndex = localAccounts.indexWhere( - (x) => x.superIdentity.recordKey == activeLocalAccountCubit.state); + (x) => x.superIdentity.recordKey == activeLocalAccountCubit); if (activeIndex == -1) { return const HomeNoActive(); } @@ -231,16 +154,15 @@ class HomeScreenState extends State { itemBuilder: (context, index) { final superIdentityRecordKey = localAccounts[index].superIdentity.recordKey; - final perAccountCollectionCubit = - perAccountCollectionBlocMapCubit.tryOperate( - superIdentityRecordKey, - closure: (c) => c); - if (perAccountCollectionCubit == null) { + final perAccountCollectionState = + perAccountCollectionBlocMapState + .get(superIdentityRecordKey); + if (perAccountCollectionState == null) { return HomeAccountMissing( key: ValueKey(superIdentityRecordKey)); } return _buildAccount(context, superIdentityRecordKey, - perAccountCollectionCubit); + perAccountCollectionState); }))); }