Merge pull request #1786 from famedly/use-stripped-state-for-room-state
refactor: Use strippedstatevent as base for room state and user class
This commit is contained in:
commit
587ce378c7
|
|
@ -1312,7 +1312,10 @@ class Client extends MatrixApi {
|
|||
|
||||
final CachedStreamController<Event> onGroupMember = CachedStreamController();
|
||||
|
||||
final CachedStreamController<Event> onRoomState = CachedStreamController();
|
||||
/// When a state in a room has been updated this will return the room ID
|
||||
/// and the state event.
|
||||
final CachedStreamController<({String roomId, StrippedStateEvent state})>
|
||||
onRoomState = CachedStreamController();
|
||||
|
||||
/// How long should the app wait until it retrys the synchronisation after
|
||||
/// an error?
|
||||
|
|
@ -2385,7 +2388,7 @@ class Client extends MatrixApi {
|
|||
|
||||
switch (eventUpdate.type) {
|
||||
case EventUpdateType.inviteState:
|
||||
room.setState(Event.fromJson(eventUpdate.content, room));
|
||||
room.setState(StrippedStateEvent.fromJson(eventUpdate.content));
|
||||
break;
|
||||
case EventUpdateType.state:
|
||||
case EventUpdateType.timeline:
|
||||
|
|
|
|||
|
|
@ -247,10 +247,7 @@ class Event extends MatrixEvent {
|
|||
prevContent: prevContent,
|
||||
content: content,
|
||||
typeKey: type,
|
||||
eventId: eventId,
|
||||
senderId: senderId,
|
||||
originServerTs: originServerTs,
|
||||
unsigned: unsigned,
|
||||
room: room,
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ class Room {
|
|||
/// The room states are a key value store of the key (`type`,`state_key`) => State(event).
|
||||
/// In a lot of cases the `state_key` might be an empty string. You **should** use the
|
||||
/// methods `getState()` and `setState()` to interact with the room states.
|
||||
Map<String, Map<String, Event>> states = {};
|
||||
Map<String, Map<String, StrippedStateEvent>> states = {};
|
||||
|
||||
/// Key-Value store for ephemerals.
|
||||
Map<String, BasicRoomEvent> ephemerals = {};
|
||||
|
|
@ -157,19 +157,31 @@ class Room {
|
|||
|
||||
/// Returns the [Event] for the given [typeKey] and optional [stateKey].
|
||||
/// If no [stateKey] is provided, it defaults to an empty string.
|
||||
Event? getState(String typeKey, [String stateKey = '']) =>
|
||||
/// This returns either a `StrippedStateEvent` for rooms with membership
|
||||
/// "invite" or a `User`/`Event`. If you need additional information like
|
||||
/// the Event ID or originServerTs you need to do a type check like:
|
||||
/// ```dart
|
||||
/// if (state is Event) { /*...*/ }
|
||||
/// ```
|
||||
StrippedStateEvent? getState(String typeKey, [String stateKey = '']) =>
|
||||
states[typeKey]?[stateKey];
|
||||
|
||||
/// Adds the [state] to this room and overwrites a state with the same
|
||||
/// typeKey/stateKey key pair if there is one.
|
||||
void setState(Event state) {
|
||||
void setState(StrippedStateEvent state) {
|
||||
// Ignore other non-state events
|
||||
final stateKey = state.stateKey;
|
||||
final roomId = state.roomId;
|
||||
if (roomId == null || roomId != id) {
|
||||
Logs().w('Tried to set state event for wrong room!');
|
||||
return;
|
||||
|
||||
// For non invite rooms this is usually an Event and we should validate
|
||||
// the room ID:
|
||||
if (state is Event) {
|
||||
final roomId = state.roomId;
|
||||
if (roomId == null || roomId != id) {
|
||||
Logs().wtf('Tried to set state event for wrong room!');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (stateKey == null) {
|
||||
Logs().w(
|
||||
'Tried to set a non state event with type "${state.type}" as state event for a room',
|
||||
|
|
@ -179,7 +191,7 @@ class Room {
|
|||
|
||||
(states[state.type] ??= {})[stateKey] = state;
|
||||
|
||||
client.onRoomState.add(state);
|
||||
client.onRoomState.add((roomId: id, state: state));
|
||||
}
|
||||
|
||||
/// ID of the fully read marker event.
|
||||
|
|
@ -276,9 +288,11 @@ class Room {
|
|||
if (membership == Membership.invite) {
|
||||
final ownMember = unsafeGetUserFromMemoryOrFallback(client.userID!);
|
||||
|
||||
ownMember.senderFromMemoryOrFallback.calcDisplayname(i18n: i18n);
|
||||
unsafeGetUserFromMemoryOrFallback(ownMember.senderId)
|
||||
.calcDisplayname(i18n: i18n);
|
||||
if (ownMember.senderId != ownMember.stateKey) {
|
||||
return ownMember.senderFromMemoryOrFallback.calcDisplayname(i18n: i18n);
|
||||
return unsafeGetUserFromMemoryOrFallback(ownMember.senderId)
|
||||
.calcDisplayname(i18n: i18n);
|
||||
}
|
||||
}
|
||||
if (membership == Membership.leave) {
|
||||
|
|
@ -312,7 +326,7 @@ class Room {
|
|||
if (heroes != null && heroes.length == 1) {
|
||||
final hero = getState(EventTypes.RoomMember, heroes.first);
|
||||
if (hero != null) {
|
||||
return hero.asUser.avatarUrl;
|
||||
return hero.asUser(this).avatarUrl;
|
||||
}
|
||||
}
|
||||
if (isDirectChat) {
|
||||
|
|
@ -383,6 +397,7 @@ class Room {
|
|||
states.forEach((final String key, final entry) {
|
||||
final state = entry[''];
|
||||
if (state == null) return;
|
||||
if (state is! Event) return;
|
||||
if (state.originServerTs.millisecondsSinceEpoch >
|
||||
lastTime.millisecondsSinceEpoch) {
|
||||
lastTime = state.originServerTs;
|
||||
|
|
@ -1554,7 +1569,7 @@ class Room {
|
|||
if (members != null) {
|
||||
return members.entries
|
||||
.where((entry) => entry.value.type == EventTypes.RoomMember)
|
||||
.map((entry) => entry.value.asUser)
|
||||
.map((entry) => entry.value.asUser(this))
|
||||
.where((user) => membershipFilter.contains(user.membership))
|
||||
.toList();
|
||||
}
|
||||
|
|
@ -1643,7 +1658,7 @@ class Room {
|
|||
User unsafeGetUserFromMemoryOrFallback(String mxID) {
|
||||
final user = getState(EventTypes.RoomMember, mxID);
|
||||
if (user != null) {
|
||||
return user.asUser;
|
||||
return user.asUser(this);
|
||||
} else {
|
||||
if (mxID.isValidMatrixId) {
|
||||
// ignore: discarded_futures
|
||||
|
|
@ -1672,7 +1687,7 @@ class Room {
|
|||
// Checks if the user is really missing
|
||||
final stateUser = getState(EventTypes.RoomMember, mxID);
|
||||
if (stateUser != null) {
|
||||
return stateUser.asUser;
|
||||
return stateUser.asUser(this);
|
||||
}
|
||||
|
||||
// it may be in the database
|
||||
|
|
|
|||
|
|
@ -19,7 +19,10 @@
|
|||
import 'package:matrix/matrix.dart';
|
||||
|
||||
/// Represents a Matrix User which may be a participant in a Matrix Room.
|
||||
class User extends Event {
|
||||
class User extends StrippedStateEvent {
|
||||
final Room room;
|
||||
final Map<String, Object?>? prevContent;
|
||||
|
||||
factory User(
|
||||
String id, {
|
||||
String? membership,
|
||||
|
|
@ -30,7 +33,6 @@ class User extends Event {
|
|||
return User.fromState(
|
||||
stateKey: id,
|
||||
senderId: id,
|
||||
eventId: 'fake_event',
|
||||
content: {
|
||||
if (membership != null) 'membership': membership,
|
||||
if (displayName != null) 'displayname': displayName,
|
||||
|
|
@ -38,20 +40,16 @@ class User extends Event {
|
|||
},
|
||||
typeKey: EventTypes.RoomMember,
|
||||
room: room,
|
||||
originServerTs: DateTime.now(),
|
||||
);
|
||||
}
|
||||
|
||||
User.fromState({
|
||||
super.prevContent,
|
||||
required String super.stateKey,
|
||||
super.content = const {},
|
||||
required String typeKey,
|
||||
required super.eventId,
|
||||
required super.senderId,
|
||||
required super.originServerTs,
|
||||
super.unsigned,
|
||||
required super.room,
|
||||
required this.room,
|
||||
this.prevContent,
|
||||
}) : super(
|
||||
type: typeKey,
|
||||
);
|
||||
|
|
@ -241,3 +239,14 @@ class User extends Event {
|
|||
const _maximumHashLength = 10000;
|
||||
String _hash(String s) =>
|
||||
(s.codeUnits.fold<int>(0, (a, b) => a + b) % _maximumHashLength).toString();
|
||||
|
||||
extension FromStrippedStateEventExtension on StrippedStateEvent {
|
||||
User asUser(Room room) => User.fromState(
|
||||
// state key should always be set for member events
|
||||
stateKey: stateKey!,
|
||||
content: content,
|
||||
typeKey: type,
|
||||
senderId: senderId,
|
||||
room: room,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
*/
|
||||
|
||||
import 'package:matrix/matrix_api_lite.dart';
|
||||
import 'package:matrix/src/event.dart';
|
||||
|
||||
class SpaceChild {
|
||||
final String? roomId;
|
||||
|
|
@ -25,7 +24,7 @@ class SpaceChild {
|
|||
final String order;
|
||||
final bool? suggested;
|
||||
|
||||
SpaceChild.fromState(Event state)
|
||||
SpaceChild.fromState(StrippedStateEvent state)
|
||||
: assert(state.type == EventTypes.SpaceChild),
|
||||
roomId = state.stateKey,
|
||||
via = state.content.tryGetList<String>('via') ?? [],
|
||||
|
|
@ -38,7 +37,7 @@ class SpaceParent {
|
|||
final List<String> via;
|
||||
final bool? canonical;
|
||||
|
||||
SpaceParent.fromState(Event state)
|
||||
SpaceParent.fromState(StrippedStateEvent state)
|
||||
: assert(state.type == EventTypes.SpaceParent),
|
||||
roomId = state.stateKey,
|
||||
via = state.content.tryGetList<String>('via') ?? [],
|
||||
|
|
|
|||
|
|
@ -89,19 +89,22 @@ class VoIP {
|
|||
|
||||
// handles the com.famedly.call events.
|
||||
client.onRoomState.stream.listen(
|
||||
(event) async {
|
||||
if (event.type == EventTypes.GroupCallMember) {
|
||||
Logs().v('[VOIP] onRoomState: type ${event.toJson()}');
|
||||
final mems = event.room.getCallMembershipsFromEvent(event);
|
||||
for (final mem in mems) {
|
||||
unawaited(createGroupCallFromRoomStateEvent(mem));
|
||||
}
|
||||
for (final map in groupCalls.entries) {
|
||||
if (map.key.roomId == event.room.id) {
|
||||
// because we don't know which call got updated, just update all
|
||||
// group calls we have entered for that room
|
||||
await map.value.onMemberStateChanged();
|
||||
}
|
||||
(update) async {
|
||||
final event = update.state;
|
||||
if (event is! Event) return;
|
||||
if (event.room.membership != Membership.join) return;
|
||||
if (event.type != EventTypes.GroupCallMember) return;
|
||||
|
||||
Logs().v('[VOIP] onRoomState: type ${event.toJson()}');
|
||||
final mems = event.room.getCallMembershipsFromEvent(event);
|
||||
for (final mem in mems) {
|
||||
unawaited(createGroupCallFromRoomStateEvent(mem));
|
||||
}
|
||||
for (final map in groupCalls.entries) {
|
||||
if (map.key.roomId == event.room.id) {
|
||||
// because we don't know which call got updated, just update all
|
||||
// group calls we have entered for that room
|
||||
await map.value.onMemberStateChanged();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue