Merge branch 'room-enhance-roomsummary' into 'master'

[Room] Add support for RoomSummary

See merge request famedly/famedlysdk!64
This commit is contained in:
Marcel 2019-08-06 09:47:09 +00:00
commit 3c365bb884
8 changed files with 121 additions and 37 deletions

View file

@ -107,7 +107,7 @@ class Client {
}
for (int i = 0; i < versions.length; i++) {
if (versions[i] == "r0.4.0")
if (versions[i] == "r0.5.0")
break;
else if (i == versions.length - 1) {
connection.onError.add(ErrorResponse(errcode: "NO_SUPPORT", error: ""));

View file

@ -343,6 +343,12 @@ class Connection {
prev_batch = room["timeline"]["prev_batch"];
}
RoomSummary summary;
if (room["summary"] is Map<String, dynamic>) {
summary = RoomSummary.fromJson(room["summary"]);
}
RoomUpdate update = RoomUpdate(
id: id,
membership: membership,
@ -350,6 +356,7 @@ class Connection {
highlight_count: highlight_count,
limitedTimeline: limitedTimeline,
prev_batch: prev_batch,
summary: summary,
);
client.store?.storeRoomUpdate(update);
onRoomUpdate.add(update);

View file

@ -43,9 +43,6 @@ class Room {
/// The name of the room if set by a participant.
String name;
/// Whether this room has a name or the name is generated by member names.
bool hasName = false;
/// The topic of the room if set by a participant.
String topic;
@ -89,6 +86,10 @@ class Room {
/// The needed power levels for all actions.
Map<String, int> powerLevels = {};
List<String> mHeroes;
int mJoinedMemberCount;
int mInvitedMemberCount;
Event lastEvent;
/// Your current client instance.
@ -107,7 +108,6 @@ class Room {
this.id,
this.membership,
this.name,
this.hasName = false,
this.topic,
this.avatar,
this.notificationCount,
@ -125,8 +125,28 @@ class Room {
this.powerLevels,
this.lastEvent,
this.client,
this.mHeroes,
this.mInvitedMemberCount,
this.mJoinedMemberCount,
});
/// Calculates the displayname. First checks if there is a name, then checks for a canonical alias and
/// then generates a name from the heroes.
String get displayname {
if (name != null && !name.isEmpty) return name;
if (canonicalAlias != null &&
!canonicalAlias.isEmpty &&
canonicalAlias.length > 3)
return canonicalAlias.substring(1, canonicalAlias.length).split(":")[0];
if (mHeroes.length > 0) {
String displayname = "";
for (int i = 0; i < mHeroes.length; i++)
displayname += User(mHeroes[i]).calcDisplayname() + ", ";
return displayname.substring(0, displayname.length - 2);
}
return "Empty chat";
}
/// The last message sent to this room.
String get lastMessage {
if (lastEvent != null)
@ -378,23 +398,13 @@ class Room {
/// Returns a Room from a json String which comes normally from the store.
static Future<Room> getRoomFromTableRow(
Map<String, dynamic> row, Client matrix) async {
bool newHasName = false;
String name = row["topic"];
if (name == "" && !row["canonical_alias"].isEmpty)
name = row["canonical_alias"];
else if (name == "")
name = await matrix.store?.getChatNameFromMemberNames(row["id"]) ?? "";
else
newHasName = true;
String avatarUrl = row["avatar_url"];
if (avatarUrl == "")
avatarUrl = await matrix.store?.getAvatarFromSingleChat(row["id"]) ?? "";
return Room(
id: row["id"],
name: name,
hasName: newHasName,
name: row["topic"],
membership: Membership.values
.firstWhere((e) => e.toString() == 'Membership.' + row["membership"]),
topic: row["description"],
@ -411,6 +421,9 @@ class Room {
historyVisibility: row["history_visibility"],
joinRules: row["join_rules"],
canonicalAlias: row["canonical_alias"],
mInvitedMemberCount: row["invited_member_count"],
mJoinedMemberCount: row["joined_member_count"],
mHeroes: row["heroes"]?.split(",") ?? [],
powerLevels: {
"power_events_default": row["power_events_default"],
"power_state_default": row["power_state_default"],

View file

@ -92,7 +92,9 @@ class RoomList {
prev_batch: chatUpdate.prev_batch,
highlightCount: chatUpdate.highlight_count,
notificationCount: chatUpdate.notification_count,
hasName: false,
mHeroes: chatUpdate.summary?.mHeroes,
mJoinedMemberCount: chatUpdate.summary?.mJoinedMemberCount,
mInvitedMemberCount: chatUpdate.summary?.mInvitedMemberCount,
);
rooms.insert(position, newRoom);
if (onInsert != null) onInsert(position);
@ -110,6 +112,14 @@ class RoomList {
rooms[j].highlightCount != chatUpdate.highlight_count)) {
rooms[j].notificationCount = chatUpdate.notification_count;
rooms[j].highlightCount = chatUpdate.highlight_count;
if (chatUpdate.summary != null) {
if (chatUpdate.summary.mHeroes != null)
rooms[j].mHeroes = chatUpdate.summary.mHeroes;
if (chatUpdate.summary.mJoinedMemberCount != null)
rooms[j].mJoinedMemberCount = chatUpdate.summary.mJoinedMemberCount;
if (chatUpdate.summary.mInvitedMemberCount != null)
rooms[j].mInvitedMemberCount = chatUpdate.summary.mInvitedMemberCount;
}
}
sortAndUpdate();
}
@ -156,8 +166,6 @@ class RoomList {
// Update the room avatar
rooms[j].avatar = MxContent(eventUpdate.content["content"]["url"]);
}
if (eventUpdate.eventType == "m.room.member" && !rooms[j].hasName)
updateMemberName(j);
sortAndUpdate();
}
@ -166,11 +174,6 @@ class RoomList {
b.timeCreated.toTimeStamp().compareTo(a.timeCreated.toTimeStamp()));
if (onUpdate != null) onUpdate();
}
void updateMemberName(int position) async {
rooms[position].name =
await client.store.getChatNameFromMemberNames(rooms[position].id);
}
}
typedef onRoomListUpdateCallback = void Function();

View file

@ -55,7 +55,7 @@ class Store {
_init() async {
var databasePath = await getDatabasesPath();
String path = p.join(databasePath, "FluffyMatrix.db");
_db = await openDatabase(path, version: 10,
_db = await openDatabase(path, version: 11,
onCreate: (Database db, int version) async {
await createTables(db);
}, onUpgrade: (Database db, int oldVersion, int newVersion) async {
@ -164,18 +164,32 @@ class Store {
// Insert the chat into the database if not exists
txn.rawInsert(
"INSERT OR IGNORE INTO Rooms " +
"VALUES(?, ?, '', 0, 0, '', '', '', 0, '', '', '', '', '', '', '', '', 0, 50, 50, 0, 50, 50, 0, 50, 100, 50, 50, 50, 100) ",
"VALUES(?, ?, '', 0, 0, 0, 0, '', '', '', '', 0, '', '', '', '', '', '', '', '', 0, 50, 50, 0, 50, 50, 0, 50, 100, 50, 50, 50, 100) ",
[roomUpdate.id, roomUpdate.membership.toString().split('.').last]);
// Update the notification counts and the limited timeline boolean
txn.rawUpdate(
"UPDATE Rooms SET highlight_count=?, notification_count=?, membership=? WHERE id=? ",
[
roomUpdate.highlight_count,
roomUpdate.notification_count,
roomUpdate.membership.toString().split('.').last,
roomUpdate.id
]);
// Update the notification counts and the limited timeline boolean and the summary
String updateQuery =
"UPDATE Rooms SET highlight_count=?, notification_count=?, membership=?";
List<dynamic> updateArgs = [
roomUpdate.highlight_count,
roomUpdate.notification_count,
roomUpdate.membership.toString().split('.').last
];
if (roomUpdate.summary?.mJoinedMemberCount != null) {
updateQuery += ", joined_member_count=?";
updateArgs.add(roomUpdate.summary.mJoinedMemberCount);
}
if (roomUpdate.summary?.mInvitedMemberCount != null) {
updateQuery += ", invited_member_count=?";
updateArgs.add(roomUpdate.summary.mInvitedMemberCount);
}
if (roomUpdate.summary?.mHeroes != null) {
updateQuery += ", heroes=?";
updateArgs.add(roomUpdate.summary.mHeroes.join(","));
}
updateQuery += " WHERE id=?";
updateArgs.add(roomUpdate.id);
txn.rawUpdate(updateQuery, updateArgs);
// Is the timeline limited? Then all previous messages should be
// removed from the database!
@ -691,6 +705,9 @@ class Store {
'topic TEXT, ' +
'highlight_count INTEGER, ' +
'notification_count INTEGER, ' +
'joined_member_count INTEGER, ' +
'invited_member_count INTEGER, ' +
'heroes TEXT, ' +
'prev_batch TEXT, ' +
'avatar_url TEXT, ' +
'draft TEXT, ' +

View file

@ -46,6 +46,8 @@ class RoomUpdate {
/// Represents the current position of the client in the room history.
final String prev_batch;
final RoomSummary summary;
RoomUpdate({
this.id,
this.membership,
@ -53,5 +55,21 @@ class RoomUpdate {
this.highlight_count,
this.limitedTimeline,
this.prev_batch,
this.summary,
});
}
class RoomSummary {
List<String> mHeroes;
int mJoinedMemberCount;
int mInvitedMemberCount;
RoomSummary(
{this.mHeroes, this.mJoinedMemberCount, this.mInvitedMemberCount});
RoomSummary.fromJson(Map<String, dynamic> json) {
mHeroes = json['m.heroes']?.cast<String>();
mJoinedMemberCount = json['m.joined_member_count'];
mInvitedMemberCount = json['m.invited_member_count'];
}
}

View file

@ -138,7 +138,14 @@ class FakeMatrixApi extends MockClient {
]
},
"/client/versions": (var req) => {
"versions": ["r0.0.1", "r0.1.0", "r0.2.0", "r0.3.0", "r0.4.0"],
"versions": [
"r0.0.1",
"r0.1.0",
"r0.2.0",
"r0.3.0",
"r0.4.0",
"r0.5.0"
],
"unstable_features": {"m.lazy_load_members": true},
},
"/client/r0/login": (var req) => {

View file

@ -68,8 +68,13 @@ void main() {
final String formatted_body = "<b>Hello</b> World";
final String contentJson =
'{"msgtype":"$msgtype","body":"$body","formatted_body":"$formatted_body"}';
final List<String> heroes = [
"@alice:matrix.org",
"@bob:example.com",
"@charley:example.org"
];
final Map<String, dynamic> jsonObj = {
Map<String, dynamic> jsonObj = {
"id": id,
"membership": membership.toString().split('.').last,
"topic": name,
@ -101,6 +106,9 @@ void main() {
"power_event_name": 0,
"power_event_power_levels": 0,
"content_json": contentJson,
"joined_member_count": notificationCount,
"invited_member_count": notificationCount,
"heroes": heroes.join(","),
};
room = await Room.getRoomFromTableRow(jsonObj, matrix);
@ -108,6 +116,7 @@ void main() {
expect(room.id, id);
expect(room.membership, membership);
expect(room.name, name);
expect(room.displayname, name);
expect(room.topic, topic);
expect(room.avatar.mxc, "");
expect(room.notificationCount, notificationCount);
@ -127,6 +136,16 @@ void main() {
room.powerLevels.forEach((String key, int value) {
expect(value, 0);
});
expect(room.mJoinedMemberCount, notificationCount);
expect(room.mInvitedMemberCount, notificationCount);
expect(room.mHeroes, heroes);
jsonObj["topic"] = "";
room = await Room.getRoomFromTableRow(jsonObj, matrix);
expect(room.displayname, "testroom");
jsonObj["canonical_alias"] = "";
room = await Room.getRoomFromTableRow(jsonObj, matrix);
expect(room.displayname, "alice, bob, charley");
});
test("sendReadReceipt", () async {