fix titles

This commit is contained in:
Christien Rioux 2024-06-20 21:38:59 -04:00
parent 17211f3515
commit c42736ce24
2 changed files with 43 additions and 23 deletions

View File

@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:async_tools/async_tools.dart'; import 'package:async_tools/async_tools.dart';
import 'package:bloc_advanced_tools/bloc_advanced_tools.dart';
import 'package:fast_immutable_collections/fast_immutable_collections.dart'; import 'package:fast_immutable_collections/fast_immutable_collections.dart';
import 'package:fixnum/fixnum.dart'; import 'package:fixnum/fixnum.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
@ -24,6 +25,7 @@ const metadataKeyIdentityPublicKey = 'identityPublicKey';
const metadataKeyExpirationDuration = 'expiration'; const metadataKeyExpirationDuration = 'expiration';
const metadataKeyViewLimit = 'view_limit'; const metadataKeyViewLimit = 'view_limit';
const metadataKeyAttachments = 'attachments'; const metadataKeyAttachments = 'attachments';
const _sfChangedContacts = 'changedContacts';
class ChatComponentCubit extends Cubit<ChatComponentState> { class ChatComponentCubit extends Cubit<ChatComponentState> {
ChatComponentCubit._({ ChatComponentCubit._({
@ -80,11 +82,17 @@ class ChatComponentCubit extends Cubit<ChatComponentState> {
// Subscribe to messages // Subscribe to messages
_messagesSubscription = _messagesCubit.stream.listen(_onChangedMessages); _messagesSubscription = _messagesCubit.stream.listen(_onChangedMessages);
_onChangedMessages(_messagesCubit.state); _onChangedMessages(_messagesCubit.state);
// Subscribe to contact list changes
_contactListSubscription =
_contactListCubit.stream.listen(_onChangedContacts);
_onChangedContacts(_contactListCubit.state);
} }
@override @override
Future<void> close() async { Future<void> close() async {
await _initWait(); await _initWait();
await _contactListSubscription.cancel();
await _accountRecordSubscription.cancel(); await _accountRecordSubscription.cancel();
await _messagesSubscription.cancel(); await _messagesSubscription.cancel();
await _conversationSubscriptions.values.map((v) => v.cancel()).wait; await _conversationSubscriptions.values.map((v) => v.cancel()).wait;
@ -170,6 +178,13 @@ class ChatComponentCubit extends Cubit<ChatComponentState> {
emit(_convertMessages(state, avMessagesState)); emit(_convertMessages(state, avMessagesState));
} }
void _onChangedContacts(
BlocBusyState<AsyncValue<IList<DHTShortArrayElementState<proto.Contact>>>>
bavContacts) {
// Rewrite users when contacts change
singleFuture((this, _sfChangedContacts), _updateConversationSubscriptions);
}
void _onChangedConversation( void _onChangedConversation(
TypedKey remoteIdentityPublicKey, TypedKey remoteIdentityPublicKey,
AsyncValue<ActiveConversationState> avConversationState, AsyncValue<ActiveConversationState> avConversationState,
@ -180,11 +195,23 @@ class ChatComponentCubit extends Cubit<ChatComponentState> {
// Don't change user information on loading state // Don't change user information on loading state
return; return;
} }
emit(state.copyWith( emit(_updateTitle(state.copyWith(
remoteUsers: state.remoteUsers.add( remoteUsers: state.remoteUsers.add(
remoteIdentityPublicKey, remoteIdentityPublicKey,
_convertRemoteUser( _convertRemoteUser(
remoteIdentityPublicKey, activeConversationState)))); remoteIdentityPublicKey, activeConversationState)))));
}
static ChatComponentState _updateTitle(ChatComponentState currentState) {
if (currentState.remoteUsers.length == 0) {
return currentState.copyWith(title: 'Empty Chat');
}
if (currentState.remoteUsers.length == 1) {
final remoteUser = currentState.remoteUsers.values.first;
return currentState.copyWith(title: remoteUser.firstName ?? '<unnamed>');
}
return currentState.copyWith(
title: '<group chat with ${currentState.remoteUsers.length} users>');
} }
types.User _convertRemoteUser(TypedKey remoteIdentityPublicKey, types.User _convertRemoteUser(TypedKey remoteIdentityPublicKey,
@ -227,18 +254,18 @@ class ChatComponentCubit extends Cubit<ChatComponentState> {
// If the cubit is already being listened to we have nothing to do // If the cubit is already being listened to we have nothing to do
if (existing.remove(remoteIdentityPublicKey)) { if (existing.remove(remoteIdentityPublicKey)) {
continue;
}
// If the cubit is not already being listened to we should do that // If the cubit is not already being listened to we should do that
_conversationSubscriptions[remoteIdentityPublicKey] = cc.stream.listen( _conversationSubscriptions[remoteIdentityPublicKey] = cc.stream.listen(
(avConv) => _onChangedConversation(remoteIdentityPublicKey, avConv)); (avConv) =>
_onChangedConversation(remoteIdentityPublicKey, avConv));
}
final activeConversationState = cc.state.asData?.value; final activeConversationState = cc.state.asData?.value;
if (activeConversationState != null) { if (activeConversationState != null) {
final remoteUser = _convertRemoteUser( currentRemoteUsersState = currentRemoteUsersState.add(
remoteIdentityPublicKey, activeConversationState); remoteIdentityPublicKey,
currentRemoteUsersState = _convertRemoteUser(
currentRemoteUsersState.add(remoteIdentityPublicKey, remoteUser); remoteIdentityPublicKey, activeConversationState));
} }
} }
// Purge remote users we didn't see in the cubit list any more // Purge remote users we didn't see in the cubit list any more
@ -253,18 +280,6 @@ class ChatComponentCubit extends Cubit<ChatComponentState> {
emit(_updateTitle(state.copyWith(remoteUsers: currentRemoteUsersState))); emit(_updateTitle(state.copyWith(remoteUsers: currentRemoteUsersState)));
} }
ChatComponentState _updateTitle(ChatComponentState currentState) {
if (currentState.remoteUsers.length == 0) {
return currentState.copyWith(title: 'Empty Chat');
}
if (currentState.remoteUsers.length == 1) {
final remoteUser = currentState.remoteUsers.values.first;
return currentState.copyWith(title: remoteUser.firstName ?? '<unnamed>');
}
return currentState.copyWith(
title: '<group chat with ${state.remoteUsers.length} users>');
}
(ChatComponentState, types.Message?) _messageStateToChatMessage( (ChatComponentState, types.Message?) _messageStateToChatMessage(
ChatComponentState currentState, MessageState message) { ChatComponentState currentState, MessageState message) {
final authorIdentityPublicKey = message.content.author.toVeilid(); final authorIdentityPublicKey = message.content.author.toVeilid();
@ -417,6 +432,9 @@ class ChatComponentCubit extends Cubit<ChatComponentState> {
final Map<TypedKey, StreamSubscription<AsyncValue<ActiveConversationState>>> final Map<TypedKey, StreamSubscription<AsyncValue<ActiveConversationState>>>
_conversationSubscriptions = {}; _conversationSubscriptions = {};
late StreamSubscription<SingleContactMessagesState> _messagesSubscription; late StreamSubscription<SingleContactMessagesState> _messagesSubscription;
late StreamSubscription<
BlocBusyState<
AsyncValue<IList<DHTShortArrayElementState<proto.Contact>>>>>
_contactListSubscription;
double scrollOffset = 0; double scrollOffset = 0;
} }

View File

@ -320,6 +320,7 @@ class ConversationCubit extends Cubit<AsyncValue<ConversationState>> {
open: open, decodeState: proto.Conversation.fromBuffer); open: open, decodeState: proto.Conversation.fromBuffer);
_localSubscription = _localSubscription =
_localConversationCubit!.stream.listen(_updateLocalConversationState); _localConversationCubit!.stream.listen(_updateLocalConversationState);
_updateLocalConversationState(_localConversationCubit!.state);
} }
// Open remote converation key // Open remote converation key
@ -330,6 +331,7 @@ class ConversationCubit extends Cubit<AsyncValue<ConversationState>> {
open: open, decodeState: proto.Conversation.fromBuffer); open: open, decodeState: proto.Conversation.fromBuffer);
_remoteSubscription = _remoteSubscription =
_remoteConversationCubit!.stream.listen(_updateRemoteConversationState); _remoteConversationCubit!.stream.listen(_updateRemoteConversationState);
_updateRemoteConversationState(_remoteConversationCubit!.state);
} }
// Initialize local messages // Initialize local messages