Refactor User class

This commit is contained in:
Christian Pauly 2019-06-11 11:13:14 +02:00
parent efa2ed5379
commit 6b94ac220f
4 changed files with 100 additions and 62 deletions

View file

@ -25,6 +25,7 @@ import 'dart:convert';
import 'package:famedlysdk/src/utils/ChatTime.dart';
import 'package:famedlysdk/src/Client.dart';
import './User.dart';
import './Room.dart';
/// A single Matrix event, e.g. a message in a chat.
class Event {
@ -77,7 +78,7 @@ class Event {
}
static Event fromJson(Map<String, dynamic> jsonObj) {
static Event fromJson(Map<String, dynamic> jsonObj, Room room) {
Map<String,dynamic> content;
try {
content = json.decode(jsonObj["content_json"]);
@ -87,7 +88,7 @@ class Event {
}
return Event(
jsonObj["id"],
User.fromJson(jsonObj),
User.fromJson(jsonObj, room),
ChatTime(jsonObj["origin_server_ts"]),
stateKey: User(jsonObj["state_key"]),
environment: jsonObj["type"],
@ -97,7 +98,7 @@ class Event {
);
}
static Future<List<Event>> getEventList(Client matrix, String roomID) async{
static Future<List<Event>> getEventList(Client matrix, Room room) async{
List<Map<String, dynamic>> eventRes = await matrix.store.db.rawQuery(
"SELECT * " +
" FROM Events events, Participants participants " +
@ -105,12 +106,12 @@ class Event {
" AND events.sender=participants.matrix_id " +
" GROUP BY events.id " +
" ORDER BY origin_server_ts DESC",
[roomID]);
[room.id]);
List<Event> eventList = [];
for (num i = 0; i < eventRes.length; i++)
eventList.add(Event.fromJson(eventRes[i]));
eventList.add(Event.fromJson(eventRes[i], room));
return eventList;
}

View file

@ -287,7 +287,7 @@ class Room {
/// 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 {
this.events = await client.store.getEventList(id);
this.events = await client.store.getEventList(this);
Map<String,bool> participantMap = {};
for (num i = 0; i < events.length; i++) {
@ -302,7 +302,7 @@ class Room {
/// Load all participants for a given room from the store.
Future<List<User>> loadParticipants() async {
this.participants = await client.store.loadParticipants(id);
this.participants = await client.store.loadParticipants(this);
return this.participants;
}
@ -319,11 +319,11 @@ class Room {
for (num i = 0; i < res["chunk"].length; i++) {
User newUser = User(res["chunk"][i]["state_key"],
displayName: res["chunk"][i]["content"]["displayname"] ?? "",
status: res["chunk"][i]["content"]["membership"] ?? "",
directChatRoomId: "",
avatar_url:
MxContent(res["chunk"][i]["content"]["avatar_url"] ?? ""));
if (newUser.status != "leave") participants.add(newUser);
membership: res["chunk"][i]["content"]["membership"] ?? "",
avatarUrl:
MxContent(res["chunk"][i]["content"]["avatar_url"] ?? ""),
room: this);
if (newUser.membership != "leave") participants.add(newUser);
}
this.participants = participants;

View file

@ -62,6 +62,7 @@ class Store {
if (oldVersion != newVersion) {
await db.execute("DROP TABLE IF EXISTS Rooms");
await db.execute("DROP TABLE IF EXISTS Participants");
await db.execute("DROP TABLE IF EXISTS User");
await db.execute("DROP TABLE IF EXISTS Events");
db.rawUpdate("UPDATE Clients SET prev_batch='' WHERE client=?",
[client.clientName]);
@ -92,7 +93,7 @@ class Store {
Future<void> createTables(Database db) async{
await db.execute(ClientsScheme);
await db.execute(RoomsScheme);
await db.execute(ParticipantsScheme);
await db.execute(UserScheme);
await db.execute(EventsScheme);
}
@ -122,7 +123,7 @@ class Store {
Future<void> clear() async{
await _db.rawDelete("DELETE FROM Clients WHERE client=?", [client.clientName]);
await _db.rawDelete("DELETE FROM Rooms");
await _db.rawDelete("DELETE FROM Participants");
await _db.rawDelete("DELETE FROM User");
await _db.rawDelete("DELETE FROM Events");
return;
}
@ -284,14 +285,14 @@ class Store {
}
// Update membership table
txn.rawInsert("INSERT OR IGNORE INTO Participants VALUES(?,?,?,?,?,0)", [
txn.rawInsert("INSERT OR IGNORE INTO User VALUES(?,?,?,?,?,0)", [
chat_id,
state_key,
insertDisplayname,
insertAvatarUrl,
membership
]);
String queryStr = "UPDATE Participants SET membership=?";
String queryStr = "UPDATE User SET membership=?";
List<String> queryArgs = [membership];
if (eventContent["content"]["displayname"] is String) {
@ -366,10 +367,10 @@ class Store {
.forEach((String user, dynamic value) async {
num power_level = eventContent["content"]["users"][user];
txn.rawUpdate(
"UPDATE Participants SET power_level=? WHERE matrix_id=? AND chat_id=?",
"UPDATE User SET power_level=? WHERE matrix_id=? AND chat_id=?",
[power_level, user, chat_id]);
txn.rawInsert(
"INSERT OR IGNORE INTO Participants VALUES(?, ?, '', '', ?, ?)",
"INSERT OR IGNORE INTO User VALUES(?, ?, '', '', ?, ?)",
[chat_id, user, "unknown", power_level]);
});
}
@ -377,59 +378,59 @@ class Store {
}
}
/// Returns a User object by a given Matrix ID and a Room ID.
/// Returns a User object by a given Matrix ID and a Room.
Future<User> getUser(
{String matrixID, String roomID}) async {
{String matrixID, Room room}) async {
List<Map<String, dynamic>> res = await db.rawQuery(
"SELECT * FROM Participants WHERE matrix_id=? AND chat_id=?",
[matrixID, roomID]);
"SELECT * FROM User WHERE matrix_id=? AND chat_id=?",
[matrixID, room.id]);
if (res.length != 1) return null;
return User.fromJson(res[0]);
return User.fromJson(res[0], room);
}
/// Loads all Users in the database to provide a contact list.
Future<List<User>> loadContacts() async {
List<Map<String, dynamic>> res = await db.rawQuery(
"SELECT * FROM Participants WHERE matrix_id!=? GROUP BY matrix_id ORDER BY displayname",
"SELECT * FROM User WHERE matrix_id!=? GROUP BY matrix_id ORDER BY displayname",
[client.userID]);
List<User> userList = [];
for (int i = 0; i < res.length; i++) userList.add(User.fromJson(res[i]));
for (int i = 0; i < res.length; i++) userList.add(User.fromJson(res[i], null));
return userList;
}
/// Returns all users of a room by a given [roomID].
Future<List<User>> loadParticipants(String roomID) async {
Future<List<User>> loadParticipants(Room room) async {
List<Map<String, dynamic>> res = await db.rawQuery(
"SELECT * " +
" FROM Participants " +
" FROM User " +
" WHERE chat_id=? " +
" AND membership='join'",
[roomID]);
[room.id]);
List<User> participants = [];
for (num i = 0; i < res.length; i++) {
participants.add(User.fromJson(res[i]));
participants.add(User.fromJson(res[i], room));
}
return participants;
}
/// Returns a list of events for the given room and sets all participants.
Future<List<Event>> getEventList(String roomID) async{
Future<List<Event>> getEventList(Room room) async{
List<Map<String, dynamic>> eventRes = await db.rawQuery(
"SELECT * " +
" FROM Events events, Participants participants " +
" FROM Events events, User user " +
" WHERE events.chat_id=?" +
" AND events.sender=participants.matrix_id " +
" AND events.sender=user.matrix_id " +
" GROUP BY events.id " +
" ORDER BY origin_server_ts DESC",
[roomID]);
[room.id]);
List<Event> eventList = [];
for (num i = 0; i < eventRes.length; i++)
eventList.add(Event.fromJson(eventRes[i]));
eventList.add(Event.fromJson(eventRes[i], room));
return eventList;
}
@ -469,10 +470,10 @@ class Store {
String roomID) async {
String avatarStr = "";
List<Map<String, dynamic>> res = await db.rawQuery(
"SELECT avatar_url FROM Participants " +
" WHERE Participants.chat_id=? " +
" AND (Participants.membership='join' OR Participants.membership='invite') " +
" AND Participants.matrix_id!=? ",
"SELECT avatar_url FROM User " +
" WHERE User.chat_id=? " +
" AND (User.membership='join' OR User.membership='invite') " +
" AND User.matrix_id!=? ",
[roomID, client.userID]);
if (res.length == 1) avatarStr = res[0]["avatar_url"];
return avatarStr;
@ -485,10 +486,10 @@ class Store {
String roomID) async {
String displayname = 'Empty chat';
List<Map<String, dynamic>> rs = await db.rawQuery(
"SELECT Participants.displayname, Participants.matrix_id, Participants.membership FROM Participants " +
" WHERE Participants.chat_id=? " +
" AND (Participants.membership='join' OR Participants.membership='invite') " +
" AND Participants.matrix_id!=? ",
"SELECT User.displayname, User.matrix_id, User.membership FROM User " +
" WHERE User.chat_id=? " +
" AND (User.membership='join' OR User.membership='invite') " +
" AND User.matrix_id!=? ",
[roomID, client.userID]);
if (rs.length > 0) {
displayname = "";
@ -572,7 +573,7 @@ class Store {
'UNIQUE(id))';
/// The database sheme for the User class.
static final String ParticipantsScheme = 'CREATE TABLE IF NOT EXISTS Participants(' +
static final String UserScheme = 'CREATE TABLE IF NOT EXISTS User(' +
'chat_id TEXT, ' + // The chat id of this membership
'matrix_id TEXT, ' + // The matrix id of this user
'displayname TEXT, ' +

View file

@ -28,43 +28,79 @@ import 'package:famedlysdk/src/Room.dart';
/// Represents a Matrix User which may be a participant in a Matrix Room.
class User {
/// The membership status of the user
final String status;
/// The full qualified Matrix ID in the format @username:server.abc
final String mxid;
/// The full qualified Matrix ID in the format @username:server.abc.
final String id;
/// The displayname of the user if the user has set one.
final String displayName;
/// The membership status of the user. One of:
/// join
/// invite
/// leave
/// ban
String membership;
/// The avatar if the user has one.
final MxContent avatar_url;
MxContent avatarUrl;
final String directChatRoomId;
/// The powerLevel of the user. Normally:
/// 0=Normal user
/// 50=Moderator
/// 100=Admin
int powerLevel = 0;
/// All users normally belong to a room.
final Room room;
const User(
this.mxid, {
this.status,
@Deprecated("Use membership instead!")
String get status => membership;
@Deprecated("Use ID instead!")
String get mxid => id;
@Deprecated("Use avatarUrl instead!")
MxContent get avatar_url => avatarUrl;
User(this.id, {
this.membership,
this.displayName,
this.avatar_url,
this.directChatRoomId,
this.avatarUrl,
this.powerLevel,
this.room,
});
/// Returns the displayname or the local part of the Matrix ID if the user
/// has no displayname.
String calcDisplayname() => displayName.isEmpty
? mxid.replaceFirst("@", "").split(":")[0]
: displayName;
String calcDisplayname() =>
displayName.isEmpty
? mxid.replaceFirst("@", "").split(":")[0]
: displayName;
/// Creates a new User object from a json string like a row from the database.
static User fromJson(Map<String, dynamic> json) {
static User fromJson(Map<String, dynamic> json, Room room) {
return User(json['matrix_id'],
displayName: json['displayname'],
avatar_url: MxContent(json['avatar_url']),
status: "",
directChatRoomId: "");
avatarUrl: MxContent(json['avatar_url']),
membership: "",
room: room);
}
/// Call the Matrix API to kick this user from this room.
Future<dynamic> kick() async {
dynamic res = await room.kick(id);
return res;
}
/// Call the Matrix API to ban this user from this room.
Future<dynamic> ban() async {
dynamic res = await room.ban(id);
return res;
}
/// Call the Matrix API to unban this banned user from this room.
Future<dynamic> unban() async {
dynamic res = await room.unban(id);
return res;
}
}