relatica/lib/screens/message_threads_browser_scr...

127 wiersze
4.6 KiB
Dart

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 = <String>[];
final participantNames = <String>[];
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(),
),
);
}
}