mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2025-09-20 04:24:50 -04:00
checkpoint
This commit is contained in:
parent
3edf2ebb46
commit
c40f835ec5
25 changed files with 378 additions and 312 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue