2019-06-09 11:57:33 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2019 Zender & Kurtz GbR.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Christian Pauly <krille@famedly.com>
|
|
|
|
* Marcel Radzio <mtrnord@famedly.com>
|
|
|
|
*
|
|
|
|
* This file is part of famedlysdk.
|
|
|
|
*
|
|
|
|
* famedlysdk is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* famedlysdk is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2019-06-09 10:16:48 +00:00
|
|
|
import 'package:famedlysdk/src/Client.dart';
|
|
|
|
import 'package:famedlysdk/src/utils/ChatTime.dart';
|
|
|
|
import 'package:famedlysdk/src/utils/MxContent.dart';
|
|
|
|
import 'package:famedlysdk/src/responses/ErrorResponse.dart';
|
2019-06-11 11:44:25 +00:00
|
|
|
import 'package:famedlysdk/src/sync/EventUpdate.dart';
|
2019-06-09 10:16:48 +00:00
|
|
|
import 'package:famedlysdk/src/Event.dart';
|
2019-06-09 11:57:33 +00:00
|
|
|
import './User.dart';
|
2019-06-09 10:16:48 +00:00
|
|
|
|
2019-06-09 12:33:25 +00:00
|
|
|
/// Represents a Matrix room.
|
2019-06-09 10:16:48 +00:00
|
|
|
class Room {
|
2019-06-11 08:51:45 +00:00
|
|
|
/// The full qualified Matrix ID for the room in the format '!localid:server.abc'.
|
|
|
|
final String id;
|
|
|
|
|
|
|
|
/// Membership status of the user for this room.
|
|
|
|
String membership;
|
|
|
|
|
|
|
|
/// The name of the room if set by a participant.
|
2019-06-09 10:16:48 +00:00
|
|
|
String name;
|
2019-06-11 08:51:45 +00:00
|
|
|
|
|
|
|
/// The topic of the room if set by a participant.
|
|
|
|
String topic;
|
|
|
|
|
|
|
|
/// The avatar of the room if set by a participant.
|
2019-06-12 10:04:52 +00:00
|
|
|
MxContent avatar = MxContent("");
|
2019-06-11 08:51:45 +00:00
|
|
|
|
|
|
|
/// The count of unread notifications.
|
2019-06-09 10:16:48 +00:00
|
|
|
int notificationCount;
|
2019-06-11 08:51:45 +00:00
|
|
|
|
|
|
|
/// The count of highlighted notifications.
|
2019-06-09 10:16:48 +00:00
|
|
|
int highlightCount;
|
2019-06-11 08:51:45 +00:00
|
|
|
|
|
|
|
String prev_batch;
|
|
|
|
|
|
|
|
String draft;
|
|
|
|
|
|
|
|
/// Time when the user has last read the chat.
|
|
|
|
ChatTime unread;
|
|
|
|
|
|
|
|
/// ID of the fully read marker event.
|
|
|
|
String fullyRead;
|
|
|
|
|
|
|
|
/// The address in the format: #roomname:homeserver.org.
|
|
|
|
String canonicalAlias;
|
|
|
|
|
|
|
|
/// If this room is a direct chat, this is the matrix ID of the user
|
|
|
|
String directChatMatrixID;
|
|
|
|
|
|
|
|
/// Must be one of [all, mention]
|
|
|
|
String notificationSettings;
|
|
|
|
|
|
|
|
/// Are guest users allowed?
|
|
|
|
String guestAccess;
|
|
|
|
|
|
|
|
/// Who can see the history of this room?
|
|
|
|
String historyVisibility;
|
|
|
|
|
|
|
|
/// Who is allowed to join this room?
|
|
|
|
String joinRules;
|
|
|
|
|
|
|
|
/// The needed power levels for all actions.
|
2019-06-11 11:44:25 +00:00
|
|
|
Map<String, int> powerLevels = {};
|
2019-06-11 08:51:45 +00:00
|
|
|
|
|
|
|
/// The list of events in this room. If the room is created by the
|
|
|
|
/// [getRoomList()] of the [Store], this will contain only the last event.
|
2019-06-09 10:16:48 +00:00
|
|
|
List<Event> events = [];
|
|
|
|
|
2019-06-11 08:51:45 +00:00
|
|
|
/// The list of participants in this room. If the room is created by the
|
|
|
|
/// [getRoomList()] of the [Store], this will contain only the sender of the
|
|
|
|
/// last event.
|
|
|
|
List<User> participants = [];
|
|
|
|
|
|
|
|
/// Your current client instance.
|
|
|
|
final Client client;
|
|
|
|
|
|
|
|
@Deprecated("Rooms.roomID is deprecated! Use Rooms.id instead!")
|
2019-06-11 11:44:25 +00:00
|
|
|
String get roomID => this.id;
|
2019-06-11 08:51:45 +00:00
|
|
|
|
|
|
|
@Deprecated("Rooms.matrix is deprecated! Use Rooms.client instead!")
|
|
|
|
Client get matrix => this.client;
|
|
|
|
|
|
|
|
@Deprecated("Rooms.status is deprecated! Use Rooms.membership instead!")
|
|
|
|
String get status => this.membership;
|
|
|
|
|
2019-06-09 10:16:48 +00:00
|
|
|
Room({
|
2019-06-11 08:51:45 +00:00
|
|
|
this.id,
|
|
|
|
this.membership,
|
2019-06-09 10:16:48 +00:00
|
|
|
this.name,
|
2019-06-11 08:51:45 +00:00
|
|
|
this.topic,
|
2019-06-09 10:16:48 +00:00
|
|
|
this.avatar,
|
|
|
|
this.notificationCount,
|
|
|
|
this.highlightCount,
|
2019-06-11 08:51:45 +00:00
|
|
|
this.prev_batch,
|
|
|
|
this.draft,
|
|
|
|
this.unread,
|
|
|
|
this.fullyRead,
|
|
|
|
this.canonicalAlias,
|
|
|
|
this.directChatMatrixID,
|
|
|
|
this.notificationSettings,
|
|
|
|
this.guestAccess,
|
|
|
|
this.historyVisibility,
|
|
|
|
this.joinRules,
|
|
|
|
this.powerLevels,
|
2019-06-09 10:16:48 +00:00
|
|
|
this.events,
|
2019-06-11 08:51:45 +00:00
|
|
|
this.participants,
|
|
|
|
this.client,
|
2019-06-09 10:16:48 +00:00
|
|
|
});
|
|
|
|
|
2019-06-11 08:51:45 +00:00
|
|
|
/// The last message sent to this room.
|
|
|
|
String get lastMessage {
|
2019-06-15 07:16:45 +00:00
|
|
|
if (events != null && events.length > 0)
|
2019-06-11 08:51:45 +00:00
|
|
|
return events[0].getBody();
|
2019-06-11 11:44:25 +00:00
|
|
|
else
|
|
|
|
return "";
|
2019-06-11 08:51:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// When the last message received.
|
|
|
|
ChatTime get timeCreated {
|
2019-06-14 05:40:11 +00:00
|
|
|
if (events?.length > 0)
|
2019-06-11 08:51:45 +00:00
|
|
|
return events[0].time;
|
2019-06-11 11:44:25 +00:00
|
|
|
else
|
|
|
|
return ChatTime.now();
|
2019-06-09 10:16:48 +00:00
|
|
|
}
|
|
|
|
|
2019-06-11 08:51:45 +00:00
|
|
|
/// Call the Matrix API to change the name of this room.
|
2019-06-11 11:44:25 +00:00
|
|
|
Future<dynamic> setName(String newName) async {
|
2019-06-11 08:51:45 +00:00
|
|
|
dynamic res = await client.connection.jsonRequest(
|
2019-06-09 10:16:48 +00:00
|
|
|
type: "PUT",
|
2019-06-11 11:44:25 +00:00
|
|
|
action: "/client/r0/rooms/${id}/send/m.room.name/${new DateTime.now()}",
|
2019-06-09 10:16:48 +00:00
|
|
|
data: {"name": newName});
|
2019-06-11 08:51:45 +00:00
|
|
|
if (res is ErrorResponse) client.connection.onError.add(res);
|
2019-06-09 10:16:48 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2019-06-11 08:51:45 +00:00
|
|
|
/// Call the Matrix API to change the topic of this room.
|
2019-06-11 11:44:25 +00:00
|
|
|
Future<dynamic> setDescription(String newName) async {
|
2019-06-11 08:51:45 +00:00
|
|
|
dynamic res = await client.connection.jsonRequest(
|
2019-06-09 10:16:48 +00:00
|
|
|
type: "PUT",
|
|
|
|
action:
|
2019-06-12 09:46:57 +00:00
|
|
|
"/client/r0/rooms/${id}/send/m.room.topic/${new DateTime.now()}",
|
2019-06-09 10:16:48 +00:00
|
|
|
data: {"topic": newName});
|
2019-06-11 08:51:45 +00:00
|
|
|
if (res is ErrorResponse) client.connection.onError.add(res);
|
2019-06-09 10:16:48 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2019-06-11 08:51:45 +00:00
|
|
|
@Deprecated("Use the client.connection streams instead!")
|
2019-06-09 10:16:48 +00:00
|
|
|
Stream<List<Event>> get eventsStream {
|
|
|
|
return Stream<List<Event>>.fromIterable(Iterable<List<Event>>.generate(
|
|
|
|
this.events.length, (int index) => this.events)).asBroadcastStream();
|
|
|
|
}
|
|
|
|
|
2019-06-11 08:51:45 +00:00
|
|
|
/// Call the Matrix API to send a simple text message.
|
2019-06-11 15:16:01 +00:00
|
|
|
Future<dynamic> sendText(String message, {String txid = null}) async {
|
|
|
|
if (txid == null) txid = "txid${DateTime.now().millisecondsSinceEpoch}";
|
|
|
|
final dynamic res = await client.connection.jsonRequest(
|
2019-06-09 10:16:48 +00:00
|
|
|
type: "PUT",
|
2019-06-12 09:46:57 +00:00
|
|
|
action: "/client/r0/rooms/${id}/send/m.room.message/$txid",
|
2019-06-09 10:16:48 +00:00
|
|
|
data: {"msgtype": "m.text", "body": message});
|
2019-06-11 11:44:25 +00:00
|
|
|
if (res["errcode"] == "M_LIMIT_EXCEEDED")
|
|
|
|
client.connection.onError.add(res["error"]);
|
2019-06-11 15:16:01 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<String> sendTextEvent(String message) async {
|
|
|
|
final String type = "m.room.message";
|
|
|
|
final int now = DateTime.now().millisecondsSinceEpoch;
|
|
|
|
final String messageID = "msg$now";
|
|
|
|
|
2019-06-12 09:46:57 +00:00
|
|
|
EventUpdate eventUpdate =
|
|
|
|
EventUpdate(type: type, roomID: id, eventType: "timeline", content: {
|
|
|
|
"type": type,
|
|
|
|
"id": messageID,
|
|
|
|
"sender": client.userID,
|
|
|
|
"status": 0,
|
|
|
|
"origin_server_ts": now,
|
|
|
|
"content": {
|
|
|
|
"msgtype": "m.text",
|
|
|
|
"body": message,
|
2019-06-11 15:16:01 +00:00
|
|
|
}
|
2019-06-12 09:46:57 +00:00
|
|
|
});
|
2019-06-11 15:16:01 +00:00
|
|
|
client.connection.onEvent.add(eventUpdate);
|
|
|
|
await client.store.transaction(() {
|
|
|
|
client.store.storeEventUpdate(eventUpdate);
|
|
|
|
});
|
|
|
|
final dynamic res = await sendText(message, txid: messageID);
|
|
|
|
if (res is ErrorResponse) {
|
2019-06-12 09:46:57 +00:00
|
|
|
client.store.db
|
|
|
|
.rawUpdate("UPDATE Events SET status=-1 WHERE id=?", [messageID]);
|
|
|
|
} else {
|
2019-06-11 15:16:01 +00:00
|
|
|
final String newEventID = res["event_id"];
|
2019-06-12 09:46:57 +00:00
|
|
|
final List<Map<String, dynamic>> event = await client.store.db
|
|
|
|
.rawQuery("SELECT * FROM Events WHERE id=?", [newEventID]);
|
2019-06-11 15:16:01 +00:00
|
|
|
if (event.length > 0) {
|
|
|
|
client.store.db.rawDelete("DELETE FROM Events WHERE id=?", [messageID]);
|
2019-06-12 09:46:57 +00:00
|
|
|
} else {
|
|
|
|
client.store.db.rawUpdate("UPDATE Events SET id=?, status=1 WHERE id=?",
|
|
|
|
[newEventID, messageID]);
|
2019-06-11 15:16:01 +00:00
|
|
|
}
|
|
|
|
return newEventID;
|
|
|
|
}
|
|
|
|
return null;
|
2019-06-09 10:16:48 +00:00
|
|
|
}
|
|
|
|
|
2019-06-11 08:51:45 +00:00
|
|
|
/// Call the Matrix API to leave this room.
|
2019-06-09 10:16:48 +00:00
|
|
|
Future<dynamic> leave() async {
|
2019-06-11 11:44:25 +00:00
|
|
|
dynamic res = await client.connection
|
|
|
|
.jsonRequest(type: "POST", action: "/client/r0/rooms/${id}/leave");
|
2019-06-11 08:51:45 +00:00
|
|
|
if (res is ErrorResponse) client.connection.onError.add(res);
|
2019-06-09 10:16:48 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2019-06-11 08:51:45 +00:00
|
|
|
/// Call the Matrix API to forget this room if you already left it.
|
2019-06-09 10:16:48 +00:00
|
|
|
Future<dynamic> forget() async {
|
2019-06-12 11:22:16 +00:00
|
|
|
client.store.forgetRoom(id);
|
2019-06-11 11:44:25 +00:00
|
|
|
dynamic res = await client.connection
|
|
|
|
.jsonRequest(type: "POST", action: "/client/r0/rooms/${id}/forget");
|
2019-06-11 08:51:45 +00:00
|
|
|
if (res is ErrorResponse) client.connection.onError.add(res);
|
2019-06-09 10:16:48 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2019-06-11 08:51:45 +00:00
|
|
|
/// Call the Matrix API to kick a user from this room.
|
2019-06-09 10:16:48 +00:00
|
|
|
Future<dynamic> kick(String userID) async {
|
2019-06-11 08:51:45 +00:00
|
|
|
dynamic res = await client.connection.jsonRequest(
|
2019-06-09 10:16:48 +00:00
|
|
|
type: "POST",
|
2019-06-11 11:44:25 +00:00
|
|
|
action: "/client/r0/rooms/${id}/kick",
|
2019-06-09 10:16:48 +00:00
|
|
|
data: {"user_id": userID});
|
2019-06-11 08:51:45 +00:00
|
|
|
if (res is ErrorResponse) client.connection.onError.add(res);
|
2019-06-09 10:16:48 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2019-06-11 08:51:45 +00:00
|
|
|
/// Call the Matrix API to ban a user from this room.
|
2019-06-09 10:16:48 +00:00
|
|
|
Future<dynamic> ban(String userID) async {
|
2019-06-11 08:51:45 +00:00
|
|
|
dynamic res = await client.connection.jsonRequest(
|
2019-06-09 10:16:48 +00:00
|
|
|
type: "POST",
|
2019-06-11 11:44:25 +00:00
|
|
|
action: "/client/r0/rooms/${id}/ban",
|
2019-06-09 10:16:48 +00:00
|
|
|
data: {"user_id": userID});
|
2019-06-11 08:51:45 +00:00
|
|
|
if (res is ErrorResponse) client.connection.onError.add(res);
|
2019-06-09 10:16:48 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2019-06-11 08:51:45 +00:00
|
|
|
/// Call the Matrix API to unban a banned user from this room.
|
2019-06-09 10:16:48 +00:00
|
|
|
Future<dynamic> unban(String userID) async {
|
2019-06-11 08:51:45 +00:00
|
|
|
dynamic res = await client.connection.jsonRequest(
|
2019-06-09 10:16:48 +00:00
|
|
|
type: "POST",
|
2019-06-11 11:44:25 +00:00
|
|
|
action: "/client/r0/rooms/${id}/unban",
|
2019-06-09 10:16:48 +00:00
|
|
|
data: {"user_id": userID});
|
2019-06-11 08:51:45 +00:00
|
|
|
if (res is ErrorResponse) client.connection.onError.add(res);
|
2019-06-09 10:16:48 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2019-06-11 11:32:14 +00:00
|
|
|
/// Call the Matrix API to unban a banned user from this room.
|
|
|
|
Future<dynamic> setPower(String userID, int power) async {
|
2019-06-11 11:44:25 +00:00
|
|
|
Map<String, int> powerMap = await client.store.getPowerLevels(id);
|
2019-06-11 11:32:14 +00:00
|
|
|
powerMap[userID] = power;
|
|
|
|
|
|
|
|
dynamic res = await client.connection.jsonRequest(
|
|
|
|
type: "PUT",
|
2019-06-11 11:44:25 +00:00
|
|
|
action: "/client/r0/rooms/$id/state/m.room.power_levels/",
|
2019-06-11 11:32:14 +00:00
|
|
|
data: {"users": powerMap});
|
|
|
|
if (res is ErrorResponse) client.connection.onError.add(res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2019-06-11 08:51:45 +00:00
|
|
|
/// Call the Matrix API to invite a user to this room.
|
2019-06-09 10:16:48 +00:00
|
|
|
Future<dynamic> invite(String userID) async {
|
2019-06-11 08:51:45 +00:00
|
|
|
dynamic res = await client.connection.jsonRequest(
|
2019-06-09 10:16:48 +00:00
|
|
|
type: "POST",
|
2019-06-11 11:44:25 +00:00
|
|
|
action: "/client/r0/rooms/${id}/invite",
|
2019-06-09 10:16:48 +00:00
|
|
|
data: {"user_id": userID});
|
2019-06-11 08:51:45 +00:00
|
|
|
if (res is ErrorResponse) client.connection.onError.add(res);
|
2019-06-09 10:16:48 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2019-06-11 11:44:25 +00:00
|
|
|
/// Request more previous events from the server.
|
|
|
|
Future<void> requestHistory({int historyCount = 100}) async {
|
|
|
|
final dynamic resp = client.connection.jsonRequest(
|
|
|
|
type: "GET",
|
|
|
|
action: "/client/r0/rooms/$id/messages",
|
|
|
|
data: {"from": prev_batch, "dir": "b", "limit": historyCount});
|
|
|
|
|
|
|
|
if (resp is ErrorResponse) return;
|
|
|
|
|
2019-06-12 09:46:57 +00:00
|
|
|
if (!(resp["chunk"] is List<dynamic> &&
|
|
|
|
resp["chunk"].length > 0 &&
|
2019-06-11 11:44:25 +00:00
|
|
|
resp["end"] is String)) return;
|
|
|
|
|
|
|
|
List<dynamic> history = resp["chunk"];
|
|
|
|
client.store.transaction(() {
|
|
|
|
for (int i = 0; i < history.length; i++) {
|
|
|
|
EventUpdate eventUpdate = EventUpdate(
|
|
|
|
eventType: "history",
|
|
|
|
roomID: id,
|
|
|
|
type: history[i]["type"],
|
|
|
|
content: history[i],
|
|
|
|
);
|
|
|
|
client.connection.onEvent.add(eventUpdate);
|
|
|
|
client.store.storeEventUpdate(eventUpdate);
|
|
|
|
client.store.txn.rawUpdate(
|
2019-06-12 09:46:57 +00:00
|
|
|
"UPDATE Rooms SET prev_batch=? WHERE id=?", [resp["end"], id]);
|
2019-06-11 11:44:25 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2019-06-09 10:16:48 +00:00
|
|
|
|
2019-06-12 09:46:57 +00:00
|
|
|
Future<dynamic> addToDirectChat(String userID) async {
|
|
|
|
Map<String, List<String>> directChats =
|
|
|
|
await client.store.getAccountDataDirectChats();
|
|
|
|
if (directChats.containsKey(userID)) if (!directChats[userID].contains(id))
|
|
|
|
directChats[userID].add(id);
|
|
|
|
else
|
|
|
|
return null; // Is already in direct chats
|
|
|
|
else
|
|
|
|
directChats[userID] = [id];
|
|
|
|
|
|
|
|
final resp = await client.connection.jsonRequest(
|
|
|
|
type: "PUT",
|
|
|
|
action: "/client/r0/user/${client.userID}/account_data/m.direct",
|
|
|
|
data: directChats);
|
|
|
|
return resp;
|
|
|
|
}
|
|
|
|
|
2019-06-11 12:13:30 +00:00
|
|
|
Future<dynamic> sendReadReceipt(String eventID) async {
|
|
|
|
final dynamic resp = client.connection.jsonRequest(
|
2019-06-14 07:52:52 +00:00
|
|
|
type: "POST",
|
2019-06-11 12:13:30 +00:00
|
|
|
action: "/client/r0/rooms/$id/read_markers",
|
2019-06-12 09:46:57 +00:00
|
|
|
data: {
|
|
|
|
"m.fully_read": eventID,
|
|
|
|
"m.read": eventID,
|
|
|
|
});
|
2019-06-11 12:13:30 +00:00
|
|
|
return resp;
|
|
|
|
}
|
|
|
|
|
2019-06-11 11:44:25 +00:00
|
|
|
/// Returns a Room from a json String which comes normally from the store.
|
2019-06-12 09:46:57 +00:00
|
|
|
static Future<Room> getRoomFromTableRow(
|
|
|
|
Map<String, dynamic> row, Client matrix) async {
|
2019-06-11 10:21:45 +00:00
|
|
|
String name = row["topic"];
|
2019-06-11 11:44:25 +00:00
|
|
|
if (name == "")
|
|
|
|
name = await matrix.store?.getChatNameFromMemberNames(row["id"]) ?? "";
|
2019-06-09 10:16:48 +00:00
|
|
|
|
2019-06-12 06:13:04 +00:00
|
|
|
String avatarUrl = row["avatar_url"];
|
|
|
|
if (avatarUrl == "")
|
|
|
|
avatarUrl = await matrix.store?.getAvatarFromSingleChat(row["id"]) ?? "";
|
2019-06-09 10:16:48 +00:00
|
|
|
|
|
|
|
return Room(
|
2019-06-11 08:51:45 +00:00
|
|
|
id: row["id"],
|
2019-06-09 10:16:48 +00:00
|
|
|
name: name,
|
2019-06-12 10:30:22 +00:00
|
|
|
membership: row["membership"],
|
2019-06-11 10:21:45 +00:00
|
|
|
topic: row["description"],
|
2019-06-12 07:04:04 +00:00
|
|
|
avatar: MxContent(avatarUrl),
|
2019-06-09 10:16:48 +00:00
|
|
|
notificationCount: row["notification_count"],
|
|
|
|
highlightCount: row["highlight_count"],
|
2019-06-11 10:21:45 +00:00
|
|
|
unread: ChatTime(row["unread"]),
|
|
|
|
fullyRead: row["fully_read"],
|
|
|
|
notificationSettings: row["notification_settings"],
|
|
|
|
directChatMatrixID: row["direct_chat_matrix_id"],
|
|
|
|
draft: row["draft"],
|
|
|
|
prev_batch: row["prev_batch"],
|
|
|
|
guestAccess: row["guest_access"],
|
|
|
|
historyVisibility: row["history_visibility"],
|
|
|
|
joinRules: row["join_rules"],
|
|
|
|
powerLevels: {
|
|
|
|
"power_events_default": row["power_events_default"],
|
|
|
|
"power_state_default": row["power_state_default"],
|
|
|
|
"power_redact": row["power_redact"],
|
|
|
|
"power_invite": row["power_invite"],
|
|
|
|
"power_ban": row["power_ban"],
|
|
|
|
"power_kick": row["power_kick"],
|
|
|
|
"power_user_default": row["power_user_default"],
|
|
|
|
"power_event_avatar": row["power_event_avatar"],
|
|
|
|
"power_event_history_visibility": row["power_event_history_visibility"],
|
|
|
|
"power_event_canonical_alias": row["power_event_canonical_alias"],
|
|
|
|
"power_event_aliases": row["power_event_aliases"],
|
|
|
|
"power_event_name": row["power_event_name"],
|
|
|
|
"power_event_power_levels": row["power_event_power_levels"],
|
|
|
|
},
|
2019-06-11 08:51:45 +00:00
|
|
|
client: matrix,
|
2019-06-12 06:26:19 +00:00
|
|
|
events: [Event.fromJson(row, null)],
|
2019-06-11 08:51:45 +00:00
|
|
|
participants: [],
|
2019-06-09 10:16:48 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-06-11 08:51:45 +00:00
|
|
|
@Deprecated("Use client.store.getRoomById(String id) instead!")
|
2019-06-09 10:16:48 +00:00
|
|
|
static Future<Room> getRoomById(String id, Client matrix) async {
|
2019-06-11 08:51:45 +00:00
|
|
|
Room room = await matrix.store.getRoomById(id);
|
|
|
|
return room;
|
2019-06-09 10:16:48 +00:00
|
|
|
}
|
|
|
|
|
2019-06-11 08:51:45 +00:00
|
|
|
/// Load a room from the store including all room events.
|
2019-06-09 10:16:48 +00:00
|
|
|
static Future<Room> loadRoomEvents(String id, Client matrix) async {
|
2019-06-11 11:44:25 +00:00
|
|
|
Room room = await matrix.store.getRoomById(id);
|
|
|
|
await room.loadEvents();
|
|
|
|
return room;
|
2019-06-09 10:16:48 +00:00
|
|
|
}
|
|
|
|
|
2019-06-11 08:51:45 +00:00
|
|
|
/// Load all events for a given room from the store. This includes all
|
|
|
|
/// senders of those events, who will be added to the participants list.
|
|
|
|
Future<List<Event>> loadEvents() async {
|
2019-06-11 09:13:14 +00:00
|
|
|
this.events = await client.store.getEventList(this);
|
2019-06-11 08:51:45 +00:00
|
|
|
|
2019-06-11 11:44:25 +00:00
|
|
|
Map<String, bool> participantMap = {};
|
2019-06-11 08:51:45 +00:00
|
|
|
for (num i = 0; i < events.length; i++) {
|
|
|
|
if (!participantMap.containsKey(events[i].sender.mxid)) {
|
|
|
|
participants.add(events[i].sender);
|
|
|
|
participantMap[events[i].sender.mxid] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.events;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Load all participants for a given room from the store.
|
|
|
|
Future<List<User>> loadParticipants() async {
|
2019-06-11 09:13:14 +00:00
|
|
|
this.participants = await client.store.loadParticipants(this);
|
2019-06-11 08:51:45 +00:00
|
|
|
return this.participants;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Request the full list of participants from the server. The local list
|
|
|
|
/// from the store is not complete if the client uses lazy loading.
|
2019-06-18 10:06:55 +00:00
|
|
|
Future<List<User>> requestParticipants() async {
|
2019-06-09 10:16:48 +00:00
|
|
|
List<User> participants = [];
|
|
|
|
|
2019-06-18 10:06:55 +00:00
|
|
|
dynamic res = await client.connection
|
2019-06-11 11:44:25 +00:00
|
|
|
.jsonRequest(type: "GET", action: "/client/r0/rooms/${id}/members");
|
2019-06-09 10:16:48 +00:00
|
|
|
if (res is ErrorResponse || !(res["chunk"] is List<dynamic>))
|
|
|
|
return participants;
|
|
|
|
|
|
|
|
for (num i = 0; i < res["chunk"].length; i++) {
|
|
|
|
User newUser = User(res["chunk"][i]["state_key"],
|
|
|
|
displayName: res["chunk"][i]["content"]["displayname"] ?? "",
|
2019-06-11 09:13:14 +00:00
|
|
|
membership: res["chunk"][i]["content"]["membership"] ?? "",
|
2019-06-11 11:44:25 +00:00
|
|
|
avatarUrl: MxContent(res["chunk"][i]["content"]["avatar_url"] ?? ""),
|
2019-06-11 09:13:14 +00:00
|
|
|
room: this);
|
|
|
|
if (newUser.membership != "leave") participants.add(newUser);
|
2019-06-09 10:16:48 +00:00
|
|
|
}
|
|
|
|
|
2019-06-11 08:51:45 +00:00
|
|
|
this.participants = participants;
|
|
|
|
|
|
|
|
return this.participants;
|
2019-06-09 10:16:48 +00:00
|
|
|
}
|
|
|
|
}
|