refactor: make timeline nullsafe
This commit is contained in:
parent
8146aa05b8
commit
d5e5500ac5
|
|
@ -1,4 +1,3 @@
|
||||||
// @dart=2.9
|
|
||||||
/*
|
/*
|
||||||
* Famedly Matrix SDK
|
* Famedly Matrix SDK
|
||||||
* Copyright (C) 2019, 2020, 2021 Famedly GmbH
|
* Copyright (C) 2019, 2020, 2021 Famedly GmbH
|
||||||
|
|
@ -34,12 +33,12 @@ class Timeline {
|
||||||
/// Map of event ID to map of type to set of aggregated events
|
/// Map of event ID to map of type to set of aggregated events
|
||||||
final Map<String, Map<String, Set<Event>>> aggregatedEvents = {};
|
final Map<String, Map<String, Set<Event>>> aggregatedEvents = {};
|
||||||
|
|
||||||
final void Function() onUpdate;
|
final void Function()? onUpdate;
|
||||||
final void Function(int insertID) onInsert;
|
final void Function(int insertID)? onInsert;
|
||||||
|
|
||||||
StreamSubscription<EventUpdate> sub;
|
StreamSubscription<EventUpdate>? sub;
|
||||||
StreamSubscription<SyncUpdate> roomSub;
|
StreamSubscription<SyncUpdate>? roomSub;
|
||||||
StreamSubscription<String> sessionIdReceivedSub;
|
StreamSubscription<String>? sessionIdReceivedSub;
|
||||||
bool isRequestingHistory = false;
|
bool isRequestingHistory = false;
|
||||||
|
|
||||||
final Map<String, Event> _eventCache = {};
|
final Map<String, Event> _eventCache = {};
|
||||||
|
|
@ -47,7 +46,7 @@ class Timeline {
|
||||||
/// Searches for the event in this timeline. If not
|
/// Searches for the event in this timeline. If not
|
||||||
/// found, requests from the server. Requested events
|
/// found, requests from the server. Requested events
|
||||||
/// are cached.
|
/// are cached.
|
||||||
Future<Event> getEventById(String id) async {
|
Future<Event?> getEventById(String id) async {
|
||||||
for (final event in events) {
|
for (final event in events) {
|
||||||
if (event.eventId == id) return event;
|
if (event.eventId == id) return event;
|
||||||
}
|
}
|
||||||
|
|
@ -84,7 +83,7 @@ class Timeline {
|
||||||
start: events.length,
|
start: events.length,
|
||||||
limit: Room.defaultHistoryCount,
|
limit: Room.defaultHistoryCount,
|
||||||
);
|
);
|
||||||
if (eventsFromStore.isNotEmpty) {
|
if (eventsFromStore != null && eventsFromStore.isNotEmpty) {
|
||||||
events.addAll(eventsFromStore);
|
events.addAll(eventsFromStore);
|
||||||
} else {
|
} else {
|
||||||
Logs().v('No more events found in the store. Request from server...');
|
Logs().v('No more events found in the store. Request from server...');
|
||||||
|
|
@ -102,24 +101,22 @@ class Timeline {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Timeline({this.room, List<Event> events, this.onUpdate, this.onInsert})
|
Timeline(
|
||||||
|
{required this.room, List<Event>? events, this.onUpdate, this.onInsert})
|
||||||
: events = events ?? [] {
|
: events = events ?? [] {
|
||||||
sub ??= room.client.onEvent.stream.listen(_handleEventUpdate);
|
sub = room.client.onEvent.stream.listen(_handleEventUpdate);
|
||||||
// If the timeline is limited we want to clear our events cache
|
// If the timeline is limited we want to clear our events cache
|
||||||
roomSub ??= room.client.onSync.stream
|
roomSub = room.client.onSync.stream
|
||||||
.where((sync) =>
|
.where((sync) => sync.rooms?.join?[room.id]?.timeline?.limited == true)
|
||||||
sync.rooms?.join != null &&
|
|
||||||
sync.rooms.join.containsKey(room.id) &&
|
|
||||||
sync.rooms.join[room.id]?.timeline?.limited == true)
|
|
||||||
.listen((_) {
|
.listen((_) {
|
||||||
events.clear();
|
this.events.clear();
|
||||||
aggregatedEvents.clear();
|
aggregatedEvents.clear();
|
||||||
});
|
});
|
||||||
sessionIdReceivedSub ??=
|
sessionIdReceivedSub =
|
||||||
room.onSessionKeyReceived.stream.listen(_sessionKeyReceived);
|
room.onSessionKeyReceived.stream.listen(_sessionKeyReceived);
|
||||||
|
|
||||||
// we want to populate our aggregated events
|
// we want to populate our aggregated events
|
||||||
for (final e in events) {
|
for (final e in this.events) {
|
||||||
addAggregatedEvent(e);
|
addAggregatedEvent(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -154,7 +151,7 @@ class Timeline {
|
||||||
} else {
|
} else {
|
||||||
await decryptFn();
|
await decryptFn();
|
||||||
}
|
}
|
||||||
if (decryptAtLeastOneEvent) onUpdate();
|
if (decryptAtLeastOneEvent) onUpdate?.call();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Request the keys for undecryptable events of this timeline
|
/// Request the keys for undecryptable events of this timeline
|
||||||
|
|
@ -173,7 +170,7 @@ class Timeline {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int _findEvent({String event_id, String unsigned_txid}) {
|
int _findEvent({String? event_id, String? unsigned_txid}) {
|
||||||
// we want to find any existing event where either the passed event_id or the passed unsigned_txid
|
// we want to find any existing event where either the passed event_id or the passed unsigned_txid
|
||||||
// matches either the event_id or transaction_id of the existing event.
|
// matches either the event_id or transaction_id of the existing event.
|
||||||
// For that we create two sets, searchNeedle, what we search, and searchHaystack, where we check if there is a match.
|
// For that we create two sets, searchNeedle, what we search, and searchHaystack, where we check if there is a match.
|
||||||
|
|
@ -218,18 +215,12 @@ class Timeline {
|
||||||
if (!aggregatedEvents.containsKey(event.relationshipEventId)) {
|
if (!aggregatedEvents.containsKey(event.relationshipEventId)) {
|
||||||
aggregatedEvents[event.relationshipEventId] = <String, Set<Event>>{};
|
aggregatedEvents[event.relationshipEventId] = <String, Set<Event>>{};
|
||||||
}
|
}
|
||||||
if (!aggregatedEvents[event.relationshipEventId]
|
final events = (aggregatedEvents[event.relationshipEventId] ??=
|
||||||
.containsKey(event.relationshipType)) {
|
<String, Set<Event>>{})[event.relationshipType] ??= <Event>{};
|
||||||
aggregatedEvents[event.relationshipEventId]
|
|
||||||
[event.relationshipType] = <Event>{};
|
|
||||||
}
|
|
||||||
// remove a potential old event
|
// remove a potential old event
|
||||||
_removeEventFromSet(
|
_removeEventFromSet(events, event);
|
||||||
aggregatedEvents[event.relationshipEventId][event.relationshipType],
|
|
||||||
event);
|
|
||||||
// add the new one
|
// add the new one
|
||||||
aggregatedEvents[event.relationshipEventId][event.relationshipType]
|
events.add(event);
|
||||||
.add(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeAggregatedEvent(Event event) {
|
void removeAggregatedEvent(Event event) {
|
||||||
|
|
@ -304,17 +295,16 @@ class Timeline {
|
||||||
-1) return;
|
-1) return;
|
||||||
if (eventUpdate.type == EventUpdateType.history) {
|
if (eventUpdate.type == EventUpdateType.history) {
|
||||||
events.add(newEvent);
|
events.add(newEvent);
|
||||||
} else if (status == -1) {
|
|
||||||
events.insert(events.firstIndexWhereNotError, newEvent);
|
|
||||||
} else {
|
} else {
|
||||||
events.insert(events.firstIndexWhereNotError, newEvent);
|
events.insert(events.firstIndexWhereNotError, newEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
addAggregatedEvent(newEvent);
|
addAggregatedEvent(newEvent);
|
||||||
if (onInsert != null) onInsert(0);
|
onInsert?.call(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (update && !_collectHistoryUpdates) {
|
if (update && !_collectHistoryUpdates) {
|
||||||
if (onUpdate != null) onUpdate();
|
onUpdate?.call();
|
||||||
}
|
}
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
Logs().w('Handle event update failed', e, s);
|
Logs().w('Handle event update failed', e, s);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue