Merge branch 'krille/add-profile-cache' into 'master'
Add profile cache Closes #65 See merge request famedly/famedlysdk!302
This commit is contained in:
commit
a27c93e7a8
|
@ -373,13 +373,39 @@ class Client {
|
||||||
return getProfileFromUserId(userID);
|
return getProfileFromUserId(userID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the combined profile information for this user. This API may be used to
|
final Map<String, Profile> _profileCache = {};
|
||||||
/// fetch the user's own profile information or other users; either locally
|
|
||||||
/// or on remote homeservers.
|
/// Get the combined profile information for this user.
|
||||||
Future<Profile> getProfileFromUserId(String userId) async {
|
/// If [getFromRooms] is true then the profile will first be searched from the
|
||||||
final dynamic resp = await jsonRequest(
|
/// room memberships. This is unstable if the given user makes use of different displaynames
|
||||||
|
/// and avatars per room, which is common for some bots and bridges.
|
||||||
|
/// If [cache] is true then
|
||||||
|
/// the profile get cached for this session. Please note that then the profile may
|
||||||
|
/// become outdated if the user changes the displayname or avatar in this session.
|
||||||
|
Future<Profile> getProfileFromUserId(String userId,
|
||||||
|
{bool cache = true, bool getFromRooms = true}) async {
|
||||||
|
if (getFromRooms) {
|
||||||
|
final room = rooms.firstWhere(
|
||||||
|
(Room room) =>
|
||||||
|
room
|
||||||
|
.getParticipants()
|
||||||
|
.indexWhere((User user) => user.id == userId) !=
|
||||||
|
-1,
|
||||||
|
orElse: () => null);
|
||||||
|
if (room != null) {
|
||||||
|
final user =
|
||||||
|
room.getParticipants().firstWhere((User user) => user.id == userId);
|
||||||
|
return Profile(user.displayName, user.avatarUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cache && _profileCache.containsKey(userId)) {
|
||||||
|
return _profileCache[userId];
|
||||||
|
}
|
||||||
|
final resp = await jsonRequest(
|
||||||
type: HTTPType.GET, action: '/client/r0/profile/${userId}');
|
type: HTTPType.GET, action: '/client/r0/profile/${userId}');
|
||||||
return Profile.fromJson(resp);
|
final profile = Profile.fromJson(resp);
|
||||||
|
_profileCache[userId] = profile;
|
||||||
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Room>> get archive async {
|
Future<List<Room>> get archive async {
|
||||||
|
@ -635,7 +661,8 @@ class Client {
|
||||||
StreamController.broadcast();
|
StreamController.broadcast();
|
||||||
|
|
||||||
/// Will be called when another device is requesting verification with this device.
|
/// Will be called when another device is requesting verification with this device.
|
||||||
final StreamController<KeyVerification> onKeyVerificationRequest = StreamController.broadcast();
|
final StreamController<KeyVerification> onKeyVerificationRequest =
|
||||||
|
StreamController.broadcast();
|
||||||
|
|
||||||
final Map<String, KeyVerification> _keyVerificationRequests = {};
|
final Map<String, KeyVerification> _keyVerificationRequests = {};
|
||||||
|
|
||||||
|
@ -1065,7 +1092,9 @@ class Client {
|
||||||
void _cleanupKeyVerificationRequests() {
|
void _cleanupKeyVerificationRequests() {
|
||||||
for (final entry in _keyVerificationRequests.entries) {
|
for (final entry in _keyVerificationRequests.entries) {
|
||||||
(() async {
|
(() async {
|
||||||
var dispose = entry.value.canceled || entry.value.state == KeyVerificationState.done || entry.value.state == KeyVerificationState.error;
|
var dispose = entry.value.canceled ||
|
||||||
|
entry.value.state == KeyVerificationState.done ||
|
||||||
|
entry.value.state == KeyVerificationState.error;
|
||||||
if (!dispose) {
|
if (!dispose) {
|
||||||
dispose = !(await entry.value.verifyActivity());
|
dispose = !(await entry.value.verifyActivity());
|
||||||
}
|
}
|
||||||
|
@ -1119,13 +1148,18 @@ class Client {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// we have key verification going on!
|
// we have key verification going on!
|
||||||
final transactionId = KeyVerification.getTransactionId(toDeviceEvent.content);
|
final transactionId =
|
||||||
|
KeyVerification.getTransactionId(toDeviceEvent.content);
|
||||||
if (transactionId != null) {
|
if (transactionId != null) {
|
||||||
if (_keyVerificationRequests.containsKey(transactionId)) {
|
if (_keyVerificationRequests.containsKey(transactionId)) {
|
||||||
_keyVerificationRequests[transactionId].handlePayload(toDeviceEvent.type, toDeviceEvent.content);
|
_keyVerificationRequests[transactionId]
|
||||||
|
.handlePayload(toDeviceEvent.type, toDeviceEvent.content);
|
||||||
} else {
|
} else {
|
||||||
final newKeyRequest = KeyVerification(client: this, userId: toDeviceEvent.sender);
|
final newKeyRequest =
|
||||||
newKeyRequest.handlePayload(toDeviceEvent.type, toDeviceEvent.content).then((res) {
|
KeyVerification(client: this, userId: toDeviceEvent.sender);
|
||||||
|
newKeyRequest
|
||||||
|
.handlePayload(toDeviceEvent.type, toDeviceEvent.content)
|
||||||
|
.then((res) {
|
||||||
if (newKeyRequest.state != KeyVerificationState.askAccept) {
|
if (newKeyRequest.state != KeyVerificationState.askAccept) {
|
||||||
// okay, something went wrong (unknown transaction id?), just dispose it
|
// okay, something went wrong (unknown transaction id?), just dispose it
|
||||||
newKeyRequest.dispose();
|
newKeyRequest.dispose();
|
||||||
|
|
|
@ -9,8 +9,11 @@ class Profile {
|
||||||
/// This API may return keys which are not limited to displayname or avatar_url.
|
/// This API may return keys which are not limited to displayname or avatar_url.
|
||||||
final Map<String, dynamic> content;
|
final Map<String, dynamic> content;
|
||||||
|
|
||||||
|
const Profile(this.displayname, this.avatarUrl, {this.content = const {}});
|
||||||
|
|
||||||
Profile.fromJson(Map<String, dynamic> json)
|
Profile.fromJson(Map<String, dynamic> json)
|
||||||
: avatarUrl = json['avatar_url'] != null ? Uri.parse(json['avatar_url']) : null,
|
: avatarUrl =
|
||||||
|
json['avatar_url'] != null ? Uri.parse(json['avatar_url']) : null,
|
||||||
displayname = json['displayname'],
|
displayname = json['displayname'],
|
||||||
content = json;
|
content = json;
|
||||||
|
|
||||||
|
|
|
@ -160,14 +160,16 @@ void main() {
|
||||||
expect(
|
expect(
|
||||||
matrix
|
matrix
|
||||||
.rooms[1]
|
.rooms[1]
|
||||||
.inboundGroupSessions['ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU']
|
.inboundGroupSessions[
|
||||||
|
'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU']
|
||||||
.content['session_key'],
|
.content['session_key'],
|
||||||
'AgAAAAAQcQ6XrFJk6Prm8FikZDqfry/NbDz8Xw7T6e+/9Yf/q3YHIPEQlzv7IZMNcYb51ifkRzFejVvtphS7wwG2FaXIp4XS2obla14iKISR0X74ugB2vyb1AydIHE/zbBQ1ic5s3kgjMFlWpu/S3FQCnCrv+DPFGEt3ERGWxIl3Bl5X53IjPyVkz65oljz2TZESwz0GH/QFvyOOm8ci0q/gceaF3S7Dmafg3dwTKYwcA5xkcc+BLyrLRzB6Hn+oMAqSNSscnm4mTeT5zYibIhrzqyUTMWr32spFtI9dNR/RFSzfCw');
|
'AgAAAAAQcQ6XrFJk6Prm8FikZDqfry/NbDz8Xw7T6e+/9Yf/q3YHIPEQlzv7IZMNcYb51ifkRzFejVvtphS7wwG2FaXIp4XS2obla14iKISR0X74ugB2vyb1AydIHE/zbBQ1ic5s3kgjMFlWpu/S3FQCnCrv+DPFGEt3ERGWxIl3Bl5X53IjPyVkz65oljz2TZESwz0GH/QFvyOOm8ci0q/gceaF3S7Dmafg3dwTKYwcA5xkcc+BLyrLRzB6Hn+oMAqSNSscnm4mTeT5zYibIhrzqyUTMWr32spFtI9dNR/RFSzfCw');
|
||||||
if (olmEnabled) {
|
if (olmEnabled) {
|
||||||
expect(
|
expect(
|
||||||
matrix
|
matrix
|
||||||
.rooms[1]
|
.rooms[1]
|
||||||
.inboundGroupSessions['ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU']
|
.inboundGroupSessions[
|
||||||
|
'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU']
|
||||||
.inboundGroupSession !=
|
.inboundGroupSession !=
|
||||||
null,
|
null,
|
||||||
true);
|
true);
|
||||||
|
@ -464,11 +466,17 @@ void main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('getProfileFromUserId', () async {
|
test('getProfileFromUserId', () async {
|
||||||
final profile = await matrix.getProfileFromUserId('@getme:example.com');
|
final profile = await matrix.getProfileFromUserId('@getme:example.com',
|
||||||
|
getFromRooms: false);
|
||||||
expect(profile.avatarUrl.toString(), 'mxc://test');
|
expect(profile.avatarUrl.toString(), 'mxc://test');
|
||||||
expect(profile.displayname, 'You got me');
|
expect(profile.displayname, 'You got me');
|
||||||
expect(profile.content['avatar_url'], profile.avatarUrl.toString());
|
expect(profile.content['avatar_url'], profile.avatarUrl.toString());
|
||||||
expect(profile.content['displayname'], profile.displayname);
|
expect(profile.content['displayname'], profile.displayname);
|
||||||
|
final aliceProfile =
|
||||||
|
await matrix.getProfileFromUserId('@alice:example.com');
|
||||||
|
expect(aliceProfile.avatarUrl.toString(),
|
||||||
|
'mxc://example.org/SEsfnsuifSDFSSEF');
|
||||||
|
expect(aliceProfile.displayname, 'Alice Margatroid');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('signJson', () {
|
test('signJson', () {
|
||||||
|
|
Loading…
Reference in a new issue