From a21ead8cd58ab71b88f0785386b7c10257ae8f85 Mon Sep 17 00:00:00 2001 From: Krille Date: Tue, 21 May 2024 14:38:21 +0200 Subject: [PATCH 1/2] fix: Requst profiles for left users This has been set to false to prevent storing global user profiles as member states in the database. However looks like this is already solved below. We can safely store the profile in the local cache, otherwise we cannot calc the body for an event synchroniously. --- lib/src/room.dart | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/src/room.dart b/lib/src/room.dart index e26672fd..ba622900 100644 --- a/lib/src/room.dart +++ b/lib/src/room.dart @@ -1644,7 +1644,6 @@ class Room { requestUser( mxID, ignoreErrors: true, - requestProfile: false, ); } return User(mxID, room: this); @@ -1702,13 +1701,17 @@ class Room { try { final profile = await client.getUserProfile(mxID); _requestingMatrixIds.remove(mxID); - return User( + final user = User( mxID, displayName: profile.displayname, avatarUrl: profile.avatarUrl?.toString(), membership: Membership.leave.name, room: this, ); + // Set it as temporary state but do not store in database: + setState(user); + onUpdate.add(id); + return user; } catch (e, s) { _requestingMatrixIds.remove(mxID); if (!ignoreErrors) { From 14b8ceb2eb7aa4df7e1195f89106af96c834f9df Mon Sep 17 00:00:00 2001 From: Krille Date: Tue, 21 May 2024 15:08:52 +0200 Subject: [PATCH 2/2] refactor: requestUser logic --- lib/src/room.dart | 136 +++++++++++++++++++++------------------------- 1 file changed, 61 insertions(+), 75 deletions(-) diff --git a/lib/src/room.dart b/lib/src/room.dart index ba622900..3302cd00 100644 --- a/lib/src/room.dart +++ b/lib/src/room.dart @@ -18,7 +18,6 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:typed_data'; import 'package:collection/collection.dart'; import 'package:html_unescape/html_unescape.dart'; @@ -26,7 +25,6 @@ import 'package:html_unescape/html_unescape.dart'; import 'package:matrix/matrix.dart'; import 'package:matrix/src/models/timeline_chunk.dart'; import 'package:matrix/src/utils/cached_stream_controller.dart'; -import 'package:matrix/src/utils/crypto/crypto.dart'; import 'package:matrix/src/utils/file_send_request_credentials.dart'; import 'package:matrix/src/utils/markdown.dart'; import 'package:matrix/src/utils/marked_unread.dart'; @@ -1662,58 +1660,74 @@ class Room { }) async { assert(mxID.isValidMatrixId); - // Checks if the user is really missing - final stateUser = getState(EventTypes.RoomMember, mxID); - if (stateUser != null) { - return stateUser.asUser(this); - } + // Is user already in cache? + var foundUser = getState(EventTypes.RoomMember, mxID)?.asUser(this); - // it may be in the database - final dbuser = await client.database?.getUser(mxID, this); - if (dbuser != null) { - setState(dbuser); - // ignore: deprecated_member_use_from_same_package - onUpdate.add(id); - return dbuser; - } + // If not, is it in the database? + foundUser ??= await client.database?.getUser(mxID, this); - if (!_requestingMatrixIds.add(mxID)) return null; - Map? resp; - try { - Logs().v( - 'Request missing user $mxID in room ${getLocalizedDisplayname()} from the server...'); - resp = await client.getRoomStateWithKey( - id, - EventTypes.RoomMember, - mxID, - ); - } on MatrixException catch (_) { - // Ignore if we have no permission - } catch (e, s) { - if (!ignoreErrors) { + // If not, can we request it from the server? + if (foundUser == null) { + if (!_requestingMatrixIds.add(mxID)) return null; + Map? resp; + try { + Logs().v( + 'Request missing user $mxID in room ${getLocalizedDisplayname()} from the server...'); + resp = await client.getRoomStateWithKey( + id, + EventTypes.RoomMember, + mxID, + ); + foundUser = User( + mxID, + room: this, + displayName: resp['displayname'], + avatarUrl: resp['avatar_url'], + membership: resp['membership'], + ); _requestingMatrixIds.remove(mxID); - rethrow; - } else { - Logs().w('Unable to request the user $mxID from the server', e, s); + + // Store user in database: + await client.database?.transaction(() async { + await client.database?.storeEventUpdate( + EventUpdate( + content: foundUser!.toJson(), + roomID: id, + type: EventUpdateType.state, + ), + client, + ); + }); + } on MatrixException catch (_) { + // Ignore if we have no permission + } catch (e, s) { + if (!ignoreErrors) { + _requestingMatrixIds.remove(mxID); + rethrow; + } else { + Logs().w('Unable to request the user $mxID from the server', e, s); + } } } - if (resp == null && requestProfile) { + + // User not found anywhere? Set a blank one: + foundUser ??= User(mxID, room: this, membership: 'leave'); + + // Is it a left user without any displayname/avatar info? Try fetch profile: + if (requestProfile && + {Membership.ban, Membership.leave}.contains(foundUser.membership) && + foundUser.displayName == null && + foundUser.avatarUrl == null) { try { - final profile = await client.getUserProfile(mxID); - _requestingMatrixIds.remove(mxID); - final user = User( + final profile = await client.getProfileFromUserId(mxID); + foundUser = User( mxID, - displayName: profile.displayname, + displayName: profile.displayName, avatarUrl: profile.avatarUrl?.toString(), membership: Membership.leave.name, room: this, ); - // Set it as temporary state but do not store in database: - setState(user); - onUpdate.add(id); - return user; } catch (e, s) { - _requestingMatrixIds.remove(mxID); if (!ignoreErrors) { rethrow; } else { @@ -1721,41 +1735,13 @@ class Room { } } } - if (resp == null) { - return null; - } - final user = User(mxID, - displayName: resp['displayname'], - avatarUrl: resp['avatar_url'], - room: this); - setState(user); - await client.database?.transaction(() async { - final fakeEventId = String.fromCharCodes( - await sha256( - Uint8List.fromList( - (id + mxID + client.generateUniqueTransactionId()).codeUnits), - ), - ); - await client.database?.storeEventUpdate( - EventUpdate( - content: MatrixEvent( - type: EventTypes.RoomMember, - content: resp!, - stateKey: mxID, - originServerTs: DateTime.now(), - senderId: mxID, - eventId: fakeEventId, - ).toJson(), - roomID: id, - type: EventUpdateType.state, - ), - client, - ); - }); + + // Set user in the local state + setState(foundUser!); // ignore: deprecated_member_use_from_same_package onUpdate.add(id); - _requestingMatrixIds.remove(mxID); - return user; + + return foundUser; } /// Searches for the event in the local cache and then on the server if not