From 4cc5d263abb85fd49ff29804e47a383329fa00f7 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Sat, 18 Jan 2020 15:49:15 +0100 Subject: [PATCH] [SDK] Implement more matrix methods --- lib/src/client.dart | 25 ++++++++++ lib/src/room.dart | 98 +++++++++++++++++++++++++++++++++++++- lib/src/utils/profile.dart | 4 ++ pubspec.yaml | 2 +- 4 files changed, 126 insertions(+), 3 deletions(-) diff --git a/lib/src/client.dart b/lib/src/client.dart index 3095107..2172977 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -341,6 +341,22 @@ class Client { } } + /// Returns the user's own displayname and avatar url. In Matrix it is possible that + /// one user can have different displaynames and avatar urls in different rooms. So + /// this endpoint first checks if the profile is the same in all rooms. If not, the + /// profile will be requested from the homserver. + Future get ownProfile async { + if (rooms.isNotEmpty) { + Set profileSet = {}; + for (Room room in rooms) { + final user = room.getUserByMXIDSync(userID); + profileSet.add(Profile.fromJson(user.content)); + } + if (profileSet.length == 1) return profileSet.first; + } + return getProfileFromUserId(userID); + } + /// Get the combined profile information for this user. This API may be used to /// fetch the user's own profile information or other users; either locally /// or on remote homeservers. @@ -452,6 +468,15 @@ class Client { } } + /// Changes the user's displayname. + Future setDisplayname(String displayname) async { + await this.jsonRequest( + type: HTTPType.PUT, + action: "/client/r0/profile/$userID/displayname", + data: {"displayname": displayname}); + return; + } + /// Uploads a new user avatar for this user. Future setAvatar(MatrixFile file) async { final uploadResp = await this.upload(file); diff --git a/lib/src/room.dart b/lib/src/room.dart index 0ad6120..2abf041 100644 --- a/lib/src/room.dart +++ b/lib/src/room.dart @@ -37,6 +37,11 @@ import './user.dart'; import 'timeline.dart'; import 'utils/states_map.dart'; +enum PushRuleState { notify, mentions_only, dont_notify } +enum JoinRules { public, knock, invite, private } +enum GuestAccess { can_join, forbidden } +enum HistoryVisibility { invited, joined, shared, world_readable } + /// Represents a Matrix room. class Room { /// The full qualified Matrix ID for the room in the format '!localid:server.abc'. @@ -1145,6 +1150,95 @@ class Room { ); return response["event_id"]; } -} -enum PushRuleState { notify, mentions_only, dont_notify } + /// Returns all aliases for this room. + List get aliases { + List aliases = []; + for (Event aliasEvent in states.states["m.room.aliases"].values) { + if (aliasEvent.content["aliases"] is List) { + aliases.addAll(aliasEvent.content["aliases"]); + } + } + return aliases; + } + + /// A room may be public meaning anyone can join the room without any prior action. Alternatively, + /// it can be invite meaning that a user who wishes to join the room must first receive an invite + /// to the room from someone already inside of the room. Currently, knock and private are reserved + /// keywords which are not implemented. + JoinRules get joinRules => getState("m.room.join_rules") != null + ? JoinRules.values.firstWhere( + (r) => + r.toString().replaceAll("JoinRules.", "") == + getState("m.room.join_rules").content["join_rule"], + orElse: () => null) + : null; + + /// Changes the join rules. You should check first if the user is able to change it. + Future setJoinRules(JoinRules joinRules) async { + await client.jsonRequest( + type: HTTPType.PUT, + action: "/client/r0/rooms/$id/state/m.room.join_rules/", + data: { + "join_rule": joinRules.toString().replaceAll("JoinRules.", ""), + }, + ); + return; + } + + /// Whether the user has the permission to change the join rules. + bool get canChangeJoinRules => canSendEvent("m.room.join_rules"); + + /// This event controls whether guest users are allowed to join rooms. If this event + /// is absent, servers should act as if it is present and has the guest_access value "forbidden". + GuestAccess get guestAccess => getState("m.room.guest_access") != null + ? GuestAccess.values.firstWhere( + (r) => + r.toString().replaceAll("GuestAccess.", "") == + getState("m.room.guest_access").content["guest_access"], + orElse: () => GuestAccess.forbidden) + : GuestAccess.forbidden; + + /// Changes the guest access. You should check first if the user is able to change it. + Future setGuestAccess(GuestAccess guestAccess) async { + await client.jsonRequest( + type: HTTPType.PUT, + action: "/client/r0/rooms/$id/state/m.room.guest_access/", + data: { + "guest_access": guestAccess.toString().replaceAll("GuestAccess.", ""), + }, + ); + return; + } + + /// Whether the user has the permission to change the guest access. + bool get canChangeGuestAccess => canSendEvent("m.room.guest_access"); + + /// This event controls whether a user can see the events that happened in a room from before they joined. + HistoryVisibility get historyVisibility => + getState("m.room.history_visibility") != null + ? HistoryVisibility.values.firstWhere( + (r) => + r.toString().replaceAll("HistoryVisibility.", "") == + getState("m.room.history_visibility") + .content["history_visibility"], + orElse: () => null) + : null; + + /// Changes the history visibility. You should check first if the user is able to change it. + Future setHistoryVisibility(HistoryVisibility historyVisibility) async { + await client.jsonRequest( + type: HTTPType.PUT, + action: "/client/r0/rooms/$id/state/m.room.history_visibility/", + data: { + "history_visibility": + historyVisibility.toString().replaceAll("HistoryVisibility.", ""), + }, + ); + return; + } + + /// Whether the user has the permission to change the history visibility. + bool get canChangeHistoryVisibility => + canSendEvent("m.room.history_visibility"); +} diff --git a/lib/src/utils/profile.dart b/lib/src/utils/profile.dart index 5a2c3c7..8dbd2de 100644 --- a/lib/src/utils/profile.dart +++ b/lib/src/utils/profile.dart @@ -15,4 +15,8 @@ class Profile { : avatarUrl = MxContent(json['avatar_url']), displayname = json['displayname'], content = json; + + bool operator ==(dynamic other) => + this.avatarUrl.mxc == other.avatarUrl.mxc && + this.displayname == other.displayname; } diff --git a/pubspec.yaml b/pubspec.yaml index c408297..e171bb4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ author: Zender & Kurtz GbR homepage: https://famedly.com environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dependencies: http: ^0.12.0+2