import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../controls/image_control.dart'; import '../controls/responsive_max_width.dart'; import '../controls/standard_appbar.dart'; import '../controls/status_and_refresh_button.dart'; import '../models/auth/profile.dart'; import '../riverpod_controllers/account_services.dart'; import '../riverpod_controllers/connection_manager_services.dart'; import '../riverpod_controllers/direct_message_services.dart'; import '../riverpod_controllers/networking/network_status_services.dart'; import '../routes.dart'; import '../utils/dateutils.dart'; class MessagesScreen extends ConsumerWidget { const MessagesScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final profile = ref.watch(activeProfileProvider); ref.watch(directMessageThreadIdsProvider(profile)); final loading = ref.watch(directMessageLoadingProvider(profile)); return Scaffold( appBar: StandardAppBar.build(context, 'Direct Message Threads', actions: [ StatusAndRefreshButton( executing: loading, refreshFunction: () async => await ref .read(directMessageThreadIdsProvider(profile).notifier) .update(), busyColor: Theme.of(context).colorScheme.surface, ), IconButton( onPressed: () { context.push('/messages/new_thread'); }, icon: const Icon(Icons.add), ) ]), body: RefreshIndicator( onRefresh: () async { await ref .read(directMessageThreadIdsProvider(profile).notifier) .update(); }, child: Center( child: Column( children: [ if (loading) const LinearProgressIndicator(), Expanded(child: buildBody(profile, ref)) ], )), ), ); } Widget buildBody(Profile profile, WidgetRef ref) { final threadIds = ref.watch(directMessageThreadIdsProvider(profile)); return threadIds.isEmpty ? const Text('No Direct Message Threads') : ResponsiveMaxWidth( child: ListView.separated( itemCount: threadIds.length, itemBuilder: (context, i) { final index = i; final threadId = threadIds[index]; final thread = ref.watch( directMessageThreadServiceProvider(profile, threadId)); final style = thread.allSeen ? null : const TextStyle(fontWeight: FontWeight.bold); final participantsAvatars = []; final participantNames = []; for (final pid in thread.participantIds) { if (pid == profile.userId) { continue; } ref.watch(connectionByIdProvider(profile, pid)).match( onSuccess: (c) { participantsAvatars.add(c.avatarUrl); participantNames.add('${c.name}(${c.handle})'); }, onError: (_) => participantNames.add('Person 1')); } return ListTile( onTap: () => context.pushNamed( ScreenPaths.thread, queryParameters: {'uri': thread.parentUri}, ), leading: thread.participantIds.isEmpty ? null : ImageControl( imageUrl: participantsAvatars.first, iconOverride: const Icon(Icons.person), width: 32.0, onTap: null, ), title: Text( [ 'You', ...participantNames, ].join(participantNames.length == 1 ? ' & ' : ', '), softWrap: true, style: style, ), subtitle: Text( thread.title, style: style, ), trailing: Text( thread.messages.isEmpty ? '' : ElapsedDateUtils.elapsedTimeStringFromEpochSeconds( thread.messages.last.createdAt), style: style, ), ); }, separatorBuilder: (_, __) => const Divider(), ), ); } }