// Version: 1.0.1 | Created: 2026-04-01 // Rooms repository. Reads room list from the Matrix SDK client. import 'package:matrix/matrix.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import '../../../core/network/matrix_client.dart'; import '../domain/room_model.dart'; part 'rooms_repository.g.dart'; @riverpod RoomsRepository roomsRepository(Ref ref) { return RoomsRepository(client: ref.watch(matrixClientProvider)); } class RoomsRepository { RoomsRepository({required Client client}) : _client = client; final Client _client; /// Returns the current room list, sorted unread-first then by last activity. List getRooms() { final rooms = _client.rooms; final models = rooms.map(_toModel).toList(); models.sort((a, b) { // Unread rooms first. if (a.unreadCount != b.unreadCount) { return b.unreadCount.compareTo(a.unreadCount); } // Then by most recent activity. final aTime = a.lastActivityAt ?? DateTime(0); final bTime = b.lastActivityAt ?? DateTime(0); return bTime.compareTo(aTime); }); return models; } /// Emits current rooms immediately, then re-emits on every sync. /// Immediate yield prevents indefinite spinner while waiting for first sync. Stream> watchRooms() async* { yield getRooms(); yield* _client.onSync.stream.map((_) => getRooms()); } RoomModel _toModel(Room room) { return RoomModel( id: room.id, displayName: room.getLocalizedDisplayname(), avatarUrl: room.avatar?.toString(), lastMessagePreview: _lastMessagePreview(room), lastActivityAt: room.timeCreated, unreadCount: room.notificationCount, isDirectMessage: room.isDirectChat, isDirect: room.isDirectChat, ); } String? _lastMessagePreview(Room room) { final lastEvent = room.lastEvent; if (lastEvent == null) return null; return switch (lastEvent.type) { 'm.room.message' => lastEvent.body, 'm.room.encrypted' => 'Encrypted message', 'm.sticker' => 'Sticker', _ => null, }; } }