import "dart:isolate"; import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:nexus/models/event.dart"; import "package:nexus/models/read_receipt.dart"; import "package:nexus/models/room.dart"; class RoomsController extends Notifier> { @override IMap build() => const IMap.empty(); Future addState( String roomId, IList state, { bool isMembers = false, }) async => update( { roomId: Room( events: IMap.fromEntries( state.map((event) => MapEntry(event.rowId, event)), ), hasFetchedState: true, hasFetchedMembers: isMembers, state: await Isolate.run(() { final newState = state.fold( const IMap>.empty(), (previousValue, stateEvent) => previousValue.add( stateEvent.type, (previousValue[stateEvent.type] ?? const IMap.empty()).add( stateEvent.stateKey!, stateEvent.rowId, ), ), ); return newState; }), ), }.toIMap(), const ISet.empty(), ); void update(IMap rooms, ISet leftRooms) { final merged = rooms.entries.fold(state, (acc, entry) { final roomId = entry.key; final incoming = entry.value; final existing = acc[roomId]; return acc.add( roomId, existing?.copyWith( hasMore: incoming.hasMore, metadata: incoming.metadata ?? existing.metadata, events: incoming.events.isEmpty ? existing.events : existing.events.addAll(incoming.events), state: incoming.state.entries.fold( existing.state, (previousValue, event) => previousValue.add( event.key, (previousValue[event.key] ?? const IMap.empty()).addAll( event.value, ), ), ), reset: false, hasFetchedMembers: incoming.hasFetchedMembers || existing.hasFetchedMembers, hasFetchedState: incoming.hasFetchedState || existing.hasFetchedState, timeline: (incoming.reset ? incoming.timeline : existing.timeline.addAll(incoming.timeline)), receipts: incoming.receipts.entries.fold( existing.receipts, (receiptAcc, event) => receiptAcc.add( event.key, (receiptAcc[event.key] ?? IList()).addAll( event.value, ), ), ), ) ?? incoming, ); }); final prunedList = leftRooms.fold( merged, (acc, roomId) => acc.remove(roomId), ); state = prunedList; } static final provider = NotifierProvider>( RoomsController.new, ); }