- Chats: Direktnachrichten + Gruppen ohne Server zusammen, Filter-Chips (Alle/Ungelesen/Personen/Gruppen), Leerzustaende mit Handlung; virtuelles 'Raeume'-Symbol entfaellt, Server-Kanaele nur noch im Server - Gruppen: runder Gruppen-Avatar, Kopf mit Mitgliederzahl, Anruf-/Video-Knopf - Gruppenanruf: LiveKit + Anwesenheit, Start-Nachricht (Push), Karte 'Gruppenanruf laeuft · Beitreten', Hinweis-Karte im Verlauf - Anrufansicht: aneinandergedrueckte Bubbles (Federphysik, Sprecher waechst), Kacheln umschaltbar, Bildschirm automatisch gross, Gespraechsdauer, Matrix-Namen/-Avatare statt LiveKit-IDs - Tests: test/bubble_physics_test.dart Co-Authored-By: Claude Opus 5.5 <[email protected]>
57 lines
1.7 KiB
Dart
57 lines
1.7 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
import 'package:matrix/matrix.dart';
|
||
import 'package:pyramid/core/matrix_client.dart';
|
||
import 'package:pyramid/core/room_kinds.dart';
|
||
|
||
final roomListProvider = StreamProvider<List<Room>>((ref) async* {
|
||
final client = await ref.watch(matrixClientProvider.future);
|
||
|
||
yield _sortedRooms(client);
|
||
|
||
await for (final _ in client.onSync.stream) {
|
||
yield _sortedRooms(client);
|
||
}
|
||
});
|
||
|
||
/// IDs aller Server-Kanäle (siehe [spaceChannelIds]); wird mit jeder
|
||
/// Synchronisation neu berechnet.
|
||
final spaceChannelIdsProvider = Provider<Set<String>>((ref) {
|
||
ref.watch(roomListProvider);
|
||
final client = ref.watch(matrixClientProvider).valueOrNull;
|
||
return client == null ? const {} : spaceChannelIds(client);
|
||
});
|
||
|
||
/// Ungelesene Unterhaltungen in „Chats“ (Direktnachrichten + Gruppen ohne
|
||
/// Server) – für das Abzeichen am Chats-Symbol.
|
||
final dmUnreadCountProvider = StreamProvider<int>((ref) async* {
|
||
final client = await ref.watch(matrixClientProvider.future);
|
||
|
||
yield _countChatUnread(client);
|
||
|
||
await for (final _ in client.onSync.stream) {
|
||
yield _countChatUnread(client);
|
||
}
|
||
});
|
||
|
||
int _countChatUnread(Client client) {
|
||
final channels = spaceChannelIds(client);
|
||
return client.rooms
|
||
.where((r) =>
|
||
r.membership == Membership.join &&
|
||
isChatListRoom(r, channels) &&
|
||
r.notificationCount > 0)
|
||
.length;
|
||
}
|
||
|
||
List<Room> _sortedRooms(Client client) {
|
||
final rooms = client.rooms
|
||
.where((r) => !r.isSpace)
|
||
.toList()
|
||
..sort((a, b) {
|
||
final aTime = a.lastEvent?.originServerTs ?? DateTime(0);
|
||
final bTime = b.lastEvent?.originServerTs ?? DateTime(0);
|
||
return bTime.compareTo(aTime);
|
||
});
|
||
return rooms;
|
||
}
|