✨ Ordering and show the last message in channel
This commit is contained in:
		| @@ -1,7 +1,9 @@ | |||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:hive_flutter/hive_flutter.dart'; | import 'package:hive_flutter/hive_flutter.dart'; | ||||||
| import 'package:provider/provider.dart'; | import 'package:provider/provider.dart'; | ||||||
|  | import 'package:surface/controllers/chat_message_controller.dart'; | ||||||
| import 'package:surface/providers/sn_network.dart'; | import 'package:surface/providers/sn_network.dart'; | ||||||
|  | import 'package:surface/providers/user_directory.dart'; | ||||||
| import 'package:surface/types/chat.dart'; | import 'package:surface/types/chat.dart'; | ||||||
| import 'package:surface/types/realm.dart'; | import 'package:surface/types/realm.dart'; | ||||||
|  |  | ||||||
| @@ -9,11 +11,13 @@ class ChatChannelProvider extends ChangeNotifier { | |||||||
|   static const kChatChannelBoxName = 'nex_chat_channels'; |   static const kChatChannelBoxName = 'nex_chat_channels'; | ||||||
|  |  | ||||||
|   late final SnNetworkProvider _sn; |   late final SnNetworkProvider _sn; | ||||||
|  |   late final UserDirectoryProvider _ud; | ||||||
|  |  | ||||||
|   Box<SnChannel>? get _channelBox => Hive.box<SnChannel>(kChatChannelBoxName); |   Box<SnChannel>? get _channelBox => Hive.box<SnChannel>(kChatChannelBoxName); | ||||||
|  |  | ||||||
|   ChatChannelProvider(BuildContext context) { |   ChatChannelProvider(BuildContext context) { | ||||||
|     _sn = context.read<SnNetworkProvider>(); |     _sn = context.read<SnNetworkProvider>(); | ||||||
|  |     _ud = context.read<UserDirectoryProvider>(); | ||||||
|     _initializeLocalData(); |     _initializeLocalData(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -113,6 +117,25 @@ class ChatChannelProvider extends ChangeNotifier { | |||||||
|     yield result; |     yield result; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   Future<List<SnChatMessage>> getLastMessages( | ||||||
|  |     Iterable<SnChannel> channels, | ||||||
|  |   ) async { | ||||||
|  |     final result = List<SnChatMessage>.empty(growable: true); | ||||||
|  |     for (final channel in channels) { | ||||||
|  |       final channelBox = await Hive.openBox<SnChatMessage>( | ||||||
|  |         '${ChatMessageController.kChatMessageBoxPrefix}${channel.id}', | ||||||
|  |       ); | ||||||
|  |       final lastMessage = channelBox.isNotEmpty | ||||||
|  |           ? channelBox.values | ||||||
|  |               .reduce((a, b) => a.createdAt.isAfter(b.createdAt) ? a : b) | ||||||
|  |           : null; | ||||||
|  |       if (lastMessage != null) result.add(lastMessage); | ||||||
|  |       channelBox.close(); | ||||||
|  |     } | ||||||
|  |     await _ud.listAccount(result.map((ele) => ele.sender.accountId).toSet()); | ||||||
|  |     return result; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void dispose() { |   void dispose() { | ||||||
|     _channelBox?.close(); |     _channelBox?.close(); | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart'; | |||||||
| import 'package:material_symbols_icons/symbols.dart'; | import 'package:material_symbols_icons/symbols.dart'; | ||||||
| import 'package:provider/provider.dart'; | import 'package:provider/provider.dart'; | ||||||
| import 'package:surface/providers/channel.dart'; | import 'package:surface/providers/channel.dart'; | ||||||
|  | import 'package:surface/providers/user_directory.dart'; | ||||||
| import 'package:surface/types/chat.dart'; | import 'package:surface/types/chat.dart'; | ||||||
| import 'package:surface/widgets/account/account_image.dart'; | import 'package:surface/widgets/account/account_image.dart'; | ||||||
| import 'package:surface/widgets/dialog.dart'; | import 'package:surface/widgets/dialog.dart'; | ||||||
| @@ -20,10 +21,25 @@ class _ChatScreenState extends State<ChatScreen> { | |||||||
|   bool _isBusy = true; |   bool _isBusy = true; | ||||||
|  |  | ||||||
|   List<SnChannel>? _channels; |   List<SnChannel>? _channels; | ||||||
|  |   Map<int, SnChatMessage>? _lastMessages; | ||||||
|  |  | ||||||
|   void _refreshChannels() { |   void _refreshChannels() { | ||||||
|     final chan = context.read<ChatChannelProvider>(); |     final chan = context.read<ChatChannelProvider>(); | ||||||
|     chan.fetchChannels().listen((channels) { |     chan.fetchChannels().listen((channels) async { | ||||||
|  |       final lastMessages = await chan.getLastMessages(channels); | ||||||
|  |       _lastMessages = {for (final val in lastMessages) val.channelId: val}; | ||||||
|  |       channels.sort((a, b) { | ||||||
|  |         if (_lastMessages!.containsKey(a.id) && | ||||||
|  |             _lastMessages!.containsKey(b.id)) { | ||||||
|  |           return _lastMessages![b.id]! | ||||||
|  |               .createdAt | ||||||
|  |               .compareTo(_lastMessages![a.id]!.createdAt); | ||||||
|  |         } | ||||||
|  |         if (_lastMessages!.containsKey(a.id)) return -1; | ||||||
|  |         if (_lastMessages!.containsKey(b.id)) return 1; | ||||||
|  |         return 0; | ||||||
|  |       }); | ||||||
|  |  | ||||||
|       if (mounted) setState(() => _channels = channels); |       if (mounted) setState(() => _channels = channels); | ||||||
|     }) |     }) | ||||||
|       ..onError((err) { |       ..onError((err) { | ||||||
| @@ -45,6 +61,8 @@ class _ChatScreenState extends State<ChatScreen> { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|  |     final ud = context.read<UserDirectoryProvider>(); | ||||||
|  |  | ||||||
|     return Scaffold( |     return Scaffold( | ||||||
|       appBar: AppBar( |       appBar: AppBar( | ||||||
|         title: Text('screenChat').tr(), |         title: Text('screenChat').tr(), | ||||||
| @@ -67,9 +85,16 @@ class _ChatScreenState extends State<ChatScreen> { | |||||||
|                 itemCount: _channels?.length ?? 0, |                 itemCount: _channels?.length ?? 0, | ||||||
|                 itemBuilder: (context, idx) { |                 itemBuilder: (context, idx) { | ||||||
|                   final channel = _channels![idx]; |                   final channel = _channels![idx]; | ||||||
|  |                   final lastMessage = _lastMessages?[channel.id]; | ||||||
|                   return ListTile( |                   return ListTile( | ||||||
|                     title: Text(channel.name), |                     title: Text(channel.name), | ||||||
|                     subtitle: Text( |                     subtitle: lastMessage != null | ||||||
|  |                         ? Text( | ||||||
|  |                             '${ud.getAccountFromCache(lastMessage.sender.accountId)?.nick}: ${lastMessage.body['text'] ?? 'Unable preview'}', | ||||||
|  |                             maxLines: 1, | ||||||
|  |                             overflow: TextOverflow.ellipsis, | ||||||
|  |                           ) | ||||||
|  |                         : Text( | ||||||
|                             channel.description, |                             channel.description, | ||||||
|                             maxLines: 1, |                             maxLines: 1, | ||||||
|                             overflow: TextOverflow.ellipsis, |                             overflow: TextOverflow.ellipsis, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user