kopia lustrzana https://gitlab.com/mysocialportal/relatica
127 wiersze
4.6 KiB
Dart
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(),
|
|
),
|
|
);
|
|
}
|
|
}
|