chat list work

This commit is contained in:
Christien Rioux 2024-01-30 18:32:56 -05:00
parent 03a6a781a6
commit ba73123702
2 changed files with 78 additions and 89 deletions

View File

@ -1,9 +1,12 @@
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:flutter_translate/flutter_translate.dart'; import 'package:flutter_translate/flutter_translate.dart';
import '../../chat/cubits/active_chat_cubit.dart';
import '../../proto/proto.dart' as proto; import '../../proto/proto.dart' as proto;
import '../../theme/theme.dart'; import '../../theme/theme.dart';
import '../chat_list.dart';
class ChatSingleContactItemWidget extends StatelessWidget { class ChatSingleContactItemWidget extends StatelessWidget {
const ChatSingleContactItemWidget({required proto.Contact contact, super.key}) const ChatSingleContactItemWidget({required proto.Contact contact, super.key})
@ -20,10 +23,10 @@ class ChatSingleContactItemWidget extends StatelessWidget {
//final textTheme = theme.textTheme; //final textTheme = theme.textTheme;
final scale = theme.extension<ScaleScheme>()!; final scale = theme.extension<ScaleScheme>()!;
final activeChat = ref.watch(activeChatStateProvider); final activeChatCubit = context.watch<ActiveChatCubit>();
final remoteConversationRecordKey = final remoteConversationRecordKey =
proto.TypedKeyProto.fromProto(contact.remoteConversationRecordKey); proto.TypedKeyProto.fromProto(_contact.remoteConversationRecordKey);
final selected = activeChat == remoteConversationRecordKey; final selected = activeChatCubit.state == remoteConversationRecordKey;
return Container( return Container(
margin: const EdgeInsets.fromLTRB(0, 4, 0, 0), margin: const EdgeInsets.fromLTRB(0, 4, 0, 0),
@ -34,21 +37,16 @@ class ChatSingleContactItemWidget extends StatelessWidget {
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
)), )),
child: Slidable( child: Slidable(
key: ObjectKey(contact), key: ObjectKey(_contact),
endActionPane: ActionPane( endActionPane: ActionPane(
motion: const DrawerMotion(), motion: const DrawerMotion(),
children: [ children: [
SlidableAction( SlidableAction(
onPressed: (context) async { onPressed: (context) async {
final activeAccountInfo = final chatListCubit = context.read<ChatListCubit>();
await ref.read(fetchActiveAccountProvider.future); await chatListCubit.deleteChat(
if (activeAccountInfo != null) { remoteConversationRecordKey:
await deleteChat( remoteConversationRecordKey);
activeAccountInfo: activeAccountInfo,
remoteConversationRecordKey:
remoteConversationRecordKey);
ref.invalidate(fetchChatListProvider);
}
}, },
backgroundColor: scale.tertiaryScale.background, backgroundColor: scale.tertiaryScale.background,
foregroundColor: scale.tertiaryScale.text, foregroundColor: scale.tertiaryScale.text,
@ -68,16 +66,14 @@ class ChatSingleContactItemWidget extends StatelessWidget {
// The child of the Slidable is what the user sees when the // The child of the Slidable is what the user sees when the
// component is not dragged. // component is not dragged.
child: ListTile( child: ListTile(
onTap: () async { onTap: () {
ref.read(activeChatStateProvider.notifier).state = activeChatCubit.setActiveChat(remoteConversationRecordKey);
remoteConversationRecordKey;
ref.invalidate(fetchChatListProvider);
}, },
title: Text(contact.editedProfile.name), title: Text(_contact.editedProfile.name),
/// xxx show last message here /// xxx show last message here
subtitle: (contact.editedProfile.pronouns.isNotEmpty) subtitle: (_contact.editedProfile.pronouns.isNotEmpty)
? Text(contact.editedProfile.pronouns) ? Text(_contact.editedProfile.pronouns)
: null, : null,
iconColor: scale.tertiaryScale.background, iconColor: scale.tertiaryScale.background,
textColor: scale.tertiaryScale.text, textColor: scale.tertiaryScale.text,
@ -89,6 +85,6 @@ class ChatSingleContactItemWidget extends StatelessWidget {
@override @override
void debugFillProperties(DiagnosticPropertiesBuilder properties) { void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties); super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<proto.Contact>('contact', contact)); properties.add(DiagnosticsProperty<proto.Contact>('contact', _contact));
} }
} }

View File

@ -1,92 +1,85 @@
import 'package:awesome_extensions/awesome_extensions.dart'; import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:fast_immutable_collections/fast_immutable_collections.dart'; import 'package:fast_immutable_collections/fast_immutable_collections.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_translate/flutter_translate.dart'; import 'package:flutter_translate/flutter_translate.dart';
import 'package:searchable_listview/searchable_listview.dart'; import 'package:searchable_listview/searchable_listview.dart';
import '../proto/proto.dart' as proto; import '../../contacts/contacts.dart';
import '../tools/tools.dart'; import '../../proto/proto.dart' as proto;
import '../../theme/theme.dart';
import '../../tools/tools.dart';
import '../chat_list.dart';
import 'chat_single_contact_item_widget.dart'; import 'chat_single_contact_item_widget.dart';
import 'empty_chat_list_widget.dart'; import 'empty_chat_list_widget.dart';
class ChatSingleContactListWidget extends ConsumerWidget { class ChatSingleContactListWidget extends StatelessWidget {
ChatSingleContactListWidget( const ChatSingleContactListWidget({super.key});
{required IList<proto.Contact> contactList,
required this.chatList,
super.key})
: contactMap = IMap.fromIterable(contactList,
keyMapper: (c) => c.remoteConversationRecordKey,
valueMapper: (c) => c);
final IMap<proto.TypedKey, proto.Contact> contactMap;
final IList<proto.Chat> chatList;
@override @override
// ignore: prefer_expression_function_bodies // ignore: prefer_expression_function_bodies
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context) {
final theme = Theme.of(context); final theme = Theme.of(context);
//final textTheme = theme.textTheme; //final textTheme = theme.textTheme;
final scale = theme.extension<ScaleScheme>()!; final scale = theme.extension<ScaleScheme>()!;
return SizedBox.expand( final contactListV = context.watch<ContactListCubit>().state;
child: styledTitleContainer(
context: context, return contactListV.builder((context, contactList) {
title: translate('chat_list.chats'), final contactMap = IMap.fromIterable(contactList,
child: SizedBox.expand( keyMapper: (c) => c.remoteConversationRecordKey,
child: (chatList.isEmpty) valueMapper: (c) => c);
? const EmptyChatListWidget()
: SearchableList<proto.Chat>( final chatListV = context.watch<ChatListCubit>().state;
autoFocusOnSearch: false, return chatListV.builder((context, chatList) => SizedBox.expand(
initialList: chatList.toList(), child: styledTitleContainer(
builder: (l, i, c) { context: context,
final contact = title: translate('chat_list.chats'),
contactMap[c.remoteConversationKey]; child: SizedBox.expand(
if (contact == null) { child: (chatList.isEmpty)
return const Text('...'); ? const EmptyChatListWidget()
} : SearchableList<proto.Chat>(
return ChatSingleContactItemWidget( autoFocusOnSearch: false,
contact: contact); initialList: chatList.toList(),
}, builder: (l, i, c) {
filter: (value) {
final lowerValue = value.toLowerCase();
return chatList.where((c) {
final contact = final contact =
contactMap[c.remoteConversationKey]; contactMap[c.remoteConversationKey];
if (contact == null) { if (contact == null) {
return false; return const Text('...');
} }
return contact.editedProfile.name return ChatSingleContactItemWidget(
.toLowerCase() contact: contact);
.contains(lowerValue) || },
contact.editedProfile.pronouns filter: (value) {
.toLowerCase() final lowerValue = value.toLowerCase();
.contains(lowerValue); return chatList.where((c) {
}).toList(); final contact =
}, contactMap[c.remoteConversationKey];
spaceBetweenSearchAndList: 4, if (contact == null) {
inputDecoration: InputDecoration( return false;
labelText: translate('chat_list.search'), }
contentPadding: const EdgeInsets.all(2), return contact.editedProfile.name
fillColor: scale.primaryScale.text, .toLowerCase()
focusedBorder: OutlineInputBorder( .contains(lowerValue) ||
borderSide: BorderSide( contact.editedProfile.pronouns
color: scale.primaryScale.hoverBorder, .toLowerCase()
.contains(lowerValue);
}).toList();
},
spaceBetweenSearchAndList: 4,
inputDecoration: InputDecoration(
labelText: translate('chat_list.search'),
contentPadding: const EdgeInsets.all(2),
fillColor: scale.primaryScale.text,
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: scale.primaryScale.hoverBorder,
),
borderRadius: BorderRadius.circular(8),
), ),
borderRadius: BorderRadius.circular(8),
), ),
), ).paddingAll(8))))
).paddingAll(8)))) .paddingLTRB(8, 8, 8, 65));
.paddingLTRB(8, 8, 8, 65); });
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(DiagnosticsProperty<IMap<proto.TypedKey, proto.Contact>>(
'contactMap', contactMap))
..add(IterableProperty<proto.Chat>('chatList', chatList));
} }
} }