Merge branch 'maintance' into 'master'

Maintance fixes

See merge request famedly/famedlysdk!28
This commit is contained in:
Christian 2019-07-12 09:26:07 +00:00
commit 457350e82b
14 changed files with 188 additions and 130 deletions

View file

@ -23,13 +23,14 @@
import 'dart:async'; import 'dart:async';
import 'dart:core'; import 'dart:core';
import 'requests/SetPushersRequest.dart';
import 'responses/ErrorResponse.dart';
import 'Connection.dart'; import 'Connection.dart';
import 'RoomList.dart';
import 'Room.dart'; import 'Room.dart';
import 'RoomList.dart';
import 'Store.dart'; import 'Store.dart';
import 'User.dart'; import 'User.dart';
import 'requests/SetPushersRequest.dart';
import 'responses/ErrorResponse.dart';
import 'responses/PushrulesResponse.dart'; import 'responses/PushrulesResponse.dart';
/// Represents a Matrix client to communicate with a /// Represents a Matrix client to communicate with a
@ -91,8 +92,8 @@ class Client {
Future<bool> checkServer(serverUrl) async { Future<bool> checkServer(serverUrl) async {
homeserver = serverUrl; homeserver = serverUrl;
final versionResp = final versionResp = await connection.jsonRequest(
await connection.jsonRequest(type: "GET", action: "/client/versions"); type: HTTPType.GET, action: "/client/versions");
if (versionResp is ErrorResponse) { if (versionResp is ErrorResponse) {
connection.onError.add(ErrorResponse(errcode: "NO_RESPONSE", error: "")); connection.onError.add(ErrorResponse(errcode: "NO_RESPONSE", error: ""));
return false; return false;
@ -123,8 +124,8 @@ class Client {
: false; : false;
} }
final loginResp = final loginResp = await connection.jsonRequest(
await connection.jsonRequest(type: "GET", action: "/client/r0/login"); type: HTTPType.GET, action: "/client/r0/login");
if (loginResp is ErrorResponse) { if (loginResp is ErrorResponse) {
connection.onError.add(loginResp); connection.onError.add(loginResp);
return false; return false;
@ -149,7 +150,7 @@ class Client {
/// authentication. Returns false if the login was not successful. /// authentication. Returns false if the login was not successful.
Future<bool> login(String username, String password) async { Future<bool> login(String username, String password) async {
final loginResp = await connection final loginResp = await connection
.jsonRequest(type: "POST", action: "/client/r0/login", data: { .jsonRequest(type: HTTPType.POST, action: "/client/r0/login", data: {
"type": "m.login.password", "type": "m.login.password",
"user": username, "user": username,
"identifier": { "identifier": {
@ -186,7 +187,7 @@ class Client {
/// including all persistent data from the store. /// including all persistent data from the store.
Future<void> logout() async { Future<void> logout() async {
final dynamic resp = await connection.jsonRequest( final dynamic resp = await connection.jsonRequest(
type: "POST", action: "/client/r0/logout/all"); type: HTTPType.POST, action: "/client/r0/logout/all");
if (resp is ErrorResponse) connection.onError.add(resp); if (resp is ErrorResponse) connection.onError.add(resp);
await connection.clear(); await connection.clear();
@ -213,6 +214,11 @@ class Client {
rooms: rooms); rooms: rooms);
} }
Future<dynamic> joinRoomById(String id) async {
return await connection.jsonRequest(
type: HTTPType.POST, action: "/client/r0/join/$id");
}
/// Creates a new group chat and invites the given Users and returns the new /// Creates a new group chat and invites the given Users and returns the new
/// created room ID. /// created room ID.
Future<String> createGroup(List<User> users) async { Future<String> createGroup(List<User> users) async {
@ -220,7 +226,7 @@ class Client {
for (int i = 0; i < users.length; i++) inviteIDs.add(users[i].id); for (int i = 0; i < users.length; i++) inviteIDs.add(users[i].id);
final dynamic resp = await connection.jsonRequest( final dynamic resp = await connection.jsonRequest(
type: "POST", type: HTTPType.POST,
action: "/client/r0/createRoom", action: "/client/r0/createRoom",
data: {"invite": inviteIDs, "preset": "private_chat"}); data: {"invite": inviteIDs, "preset": "private_chat"});
@ -236,7 +242,7 @@ class Client {
/// These are needed for notifications on Android /// These are needed for notifications on Android
Future<PushrulesResponse> getPushrules() async { Future<PushrulesResponse> getPushrules() async {
final dynamic resp = await connection.jsonRequest( final dynamic resp = await connection.jsonRequest(
type: "GET", type: HTTPType.GET,
action: "/client/r0/pushrules", action: "/client/r0/pushrules",
); );
@ -251,7 +257,7 @@ class Client {
/// This endpoint allows the creation, modification and deletion of pushers for this user ID. /// This endpoint allows the creation, modification and deletion of pushers for this user ID.
Future setPushers(SetPushersRequest data) async { Future setPushers(SetPushersRequest data) async {
final dynamic resp = await connection.jsonRequest( final dynamic resp = await connection.jsonRequest(
type: "POST", type: HTTPType.POST,
action: "/client/r0/pushers/set", action: "/client/r0/pushers/set",
data: data, data: data,
); );

View file

@ -24,13 +24,18 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:core'; import 'dart:core';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'Client.dart';
import 'User.dart';
import 'responses/ErrorResponse.dart'; import 'responses/ErrorResponse.dart';
import 'sync/EventUpdate.dart'; import 'sync/EventUpdate.dart';
import 'sync/UserUpdate.dart';
import 'sync/RoomUpdate.dart'; import 'sync/RoomUpdate.dart';
import 'Client.dart'; import 'sync/UserUpdate.dart';
enum HTTPType { GET, POST, PUT, DELETE }
/// Represents a Matrix connection to communicate with a /// Represents a Matrix connection to communicate with a
/// [Matrix](https://matrix.org) homeserver. /// [Matrix](https://matrix.org) homeserver.
@ -41,10 +46,12 @@ class Connection {
WidgetsBinding.instance WidgetsBinding.instance
?.addObserver(_LifecycleEventHandler(resumeCallBack: () { ?.addObserver(_LifecycleEventHandler(resumeCallBack: () {
_sync(); _sync();
return;
})); }));
} }
String get _syncFilters => '{"room":{"state":{"lazy_load_members":true}}}'; String get _syncFilters => '{"room":{"state":{"lazy_load_members":true}}}';
String get _firstSyncFilters => String get _firstSyncFilters =>
'{"room":{"include_leave":true,"state":{"lazy_load_members":true}}}'; '{"room":{"include_leave":true,"state":{"lazy_load_members":true}}}';
@ -103,7 +110,7 @@ class Connection {
/// ///
/// ``` /// ```
/// final resp = await matrix /// final resp = await matrix
/// .jsonRequest(type: "POST", action: "/client/r0/login", data: { /// .jsonRequest(type: HTTPType.POST, action: "/client/r0/login", data: {
/// "type": "m.login.password", /// "type": "m.login.password",
/// "user": "test", /// "user": "test",
/// "password": "1234", /// "password": "1234",
@ -164,7 +171,7 @@ class Connection {
/// ///
/// ``` /// ```
/// final resp = await jsonRequest( /// final resp = await jsonRequest(
/// type: "PUT", /// type: HTTPType.PUT,
/// action: "/r0/rooms/!fjd823j:example.com/send/m.room.message/$txnId", /// action: "/r0/rooms/!fjd823j:example.com/send/m.room.message/$txnId",
/// data: { /// data: {
/// "msgtype": "m.text", /// "msgtype": "m.text",
@ -174,7 +181,7 @@ class Connection {
/// ``` /// ```
/// ///
Future<dynamic> jsonRequest( Future<dynamic> jsonRequest(
{String type, String action, dynamic data = "", int timeout}) async { {HTTPType type, String action, dynamic data = "", int timeout}) async {
if (client.isLogged() == false && client.homeserver == null) if (client.isLogged() == false && client.homeserver == null)
throw ("No homeserver specified."); throw ("No homeserver specified.");
if (timeout == null) timeout = syncTimeoutSec + 5; if (timeout == null) timeout = syncTimeoutSec + 5;
@ -188,11 +195,13 @@ class Connection {
if (client.isLogged()) if (client.isLogged())
headers["Authorization"] = "Bearer ${client.accessToken}"; headers["Authorization"] = "Bearer ${client.accessToken}";
if (client.debug) print("[REQUEST $type] Action: $action, Data: $data"); if (client.debug)
print(
"[REQUEST ${type.toString().split('.').last}] Action: $action, Data: $data");
http.Response resp; http.Response resp;
try { try {
switch (type) { switch (type.toString().split('.').last) {
case "GET": case "GET":
resp = await httpClient resp = await httpClient
.get(url, headers: headers) .get(url, headers: headers)
@ -257,7 +266,7 @@ class Connection {
action += "&timeout=30000"; action += "&timeout=30000";
action += "&since=${client.prevBatch}"; action += "&since=${client.prevBatch}";
} }
_syncRequest = jsonRequest(type: "GET", action: action); _syncRequest = jsonRequest(type: HTTPType.GET, action: action);
final int hash = _syncRequest.hashCode; final int hash = _syncRequest.hashCode;
final syncResp = await _syncRequest; final syncResp = await _syncRequest;
if (hash != _syncRequest.hashCode) return; if (hash != _syncRequest.hashCode) return;
@ -270,6 +279,7 @@ class Connection {
await client.store.transaction(() { await client.store.transaction(() {
_handleSync(syncResp); _handleSync(syncResp);
client.store.storePrevBatch(syncResp); client.store.storePrevBatch(syncResp);
return;
}); });
else else
await _handleSync(syncResp); await _handleSync(syncResp);
@ -287,11 +297,11 @@ class Connection {
void _handleSync(dynamic sync) { void _handleSync(dynamic sync) {
if (sync["rooms"] is Map<String, dynamic>) { if (sync["rooms"] is Map<String, dynamic>) {
if (sync["rooms"]["join"] is Map<String, dynamic>) if (sync["rooms"]["join"] is Map<String, dynamic>)
_handleRooms(sync["rooms"]["join"], "join"); _handleRooms(sync["rooms"]["join"], Membership.join);
if (sync["rooms"]["invite"] is Map<String, dynamic>) if (sync["rooms"]["invite"] is Map<String, dynamic>)
_handleRooms(sync["rooms"]["invite"], "invite"); _handleRooms(sync["rooms"]["invite"], Membership.invite);
if (sync["rooms"]["leave"] is Map<String, dynamic>) if (sync["rooms"]["leave"] is Map<String, dynamic>)
_handleRooms(sync["rooms"]["leave"], "leave"); _handleRooms(sync["rooms"]["leave"], Membership.leave);
} }
if (sync["presence"] is Map<String, dynamic> && if (sync["presence"] is Map<String, dynamic> &&
sync["presence"]["events"] is List<dynamic>) { sync["presence"]["events"] is List<dynamic>) {
@ -308,7 +318,7 @@ class Connection {
onSync.add(sync); onSync.add(sync);
} }
void _handleRooms(Map<String, dynamic> rooms, String membership) { void _handleRooms(Map<String, dynamic> rooms, Membership membership) {
rooms.forEach((String id, dynamic room) async { rooms.forEach((String id, dynamic room) async {
// calculate the notification counts, the limitedTimeline and prevbatch // calculate the notification counts, the limitedTimeline and prevbatch
num highlight_count = 0; num highlight_count = 0;

View file

@ -22,11 +22,13 @@
*/ */
import 'dart:convert'; import 'dart:convert';
import 'package:famedlysdk/src/Client.dart';
import 'package:famedlysdk/src/sync/EventUpdate.dart'; import 'package:famedlysdk/src/sync/EventUpdate.dart';
import 'package:famedlysdk/src/utils/ChatTime.dart'; import 'package:famedlysdk/src/utils/ChatTime.dart';
import 'package:famedlysdk/src/Client.dart';
import './User.dart';
import './Room.dart'; import './Room.dart';
import './User.dart';
/// A single Matrix event, e.g. a message in a chat. /// A single Matrix event, e.g. a message in a chat.
class Event { class Event {
@ -106,6 +108,9 @@ class Event {
case "m.room.message": case "m.room.message":
switch (content["msgtype"] ?? "m.text") { switch (content["msgtype"] ?? "m.text") {
case "m.text": case "m.text":
if (content.containsKey("m.relates_to")) {
return EventTypes.Reply;
}
return EventTypes.Text; return EventTypes.Text;
case "m.notice": case "m.notice":
return EventTypes.Notice; return EventTypes.Notice;
@ -135,7 +140,9 @@ class Event {
try { try {
content = json.decode(jsonObj["content_json"]); content = json.decode(jsonObj["content_json"]);
} catch (e) { } catch (e) {
print("jsonObj decode of event content failed: ${e.toString()}"); if (room.client.debug) {
print("jsonObj decode of event content failed: ${e.toString()}");
}
content = {}; content = {};
} }
else if (content == null) content = {}; else if (content == null) content = {};
@ -198,6 +205,7 @@ enum EventTypes {
Audio, Audio,
File, File,
Location, Location,
Reply,
RoomAliases, RoomAliases,
RoomCanonicalAlias, RoomCanonicalAlias,
RoomCreate, RoomCreate,

View file

@ -22,12 +22,14 @@
*/ */
import 'package:famedlysdk/src/Client.dart'; import 'package:famedlysdk/src/Client.dart';
import 'package:famedlysdk/src/utils/ChatTime.dart'; import 'package:famedlysdk/src/Event.dart';
import 'package:famedlysdk/src/utils/MxContent.dart';
import 'package:famedlysdk/src/responses/ErrorResponse.dart'; import 'package:famedlysdk/src/responses/ErrorResponse.dart';
import 'package:famedlysdk/src/sync/EventUpdate.dart'; import 'package:famedlysdk/src/sync/EventUpdate.dart';
import 'package:famedlysdk/src/Event.dart'; import 'package:famedlysdk/src/utils/ChatTime.dart';
import 'package:famedlysdk/src/utils/MxContent.dart';
import './User.dart'; import './User.dart';
import 'Connection.dart';
import 'Timeline.dart'; import 'Timeline.dart';
/// Represents a Matrix room. /// Represents a Matrix room.
@ -36,7 +38,7 @@ class Room {
final String id; final String id;
/// Membership status of the user for this room. /// Membership status of the user for this room.
String membership; Membership membership;
/// The name of the room if set by a participant. /// The name of the room if set by a participant.
String name; String name;
@ -96,7 +98,7 @@ class Room {
Client get matrix => this.client; Client get matrix => this.client;
@Deprecated("Rooms.status is deprecated! Use Rooms.membership instead!") @Deprecated("Rooms.status is deprecated! Use Rooms.membership instead!")
String get status => this.membership; String get status => this.membership.toString().split('.').last;
Room({ Room({
this.id, this.id,
@ -140,7 +142,7 @@ class Room {
/// Call the Matrix API to change the name of this room. /// Call the Matrix API to change the name of this room.
Future<dynamic> setName(String newName) async { Future<dynamic> setName(String newName) async {
dynamic res = await client.connection.jsonRequest( dynamic res = await client.connection.jsonRequest(
type: "PUT", type: HTTPType.PUT,
action: "/client/r0/rooms/${id}/send/m.room.name/${new DateTime.now()}", action: "/client/r0/rooms/${id}/send/m.room.name/${new DateTime.now()}",
data: {"name": newName}); data: {"name": newName});
if (res is ErrorResponse) client.connection.onError.add(res); if (res is ErrorResponse) client.connection.onError.add(res);
@ -150,7 +152,7 @@ class Room {
/// Call the Matrix API to change the topic of this room. /// Call the Matrix API to change the topic of this room.
Future<dynamic> setDescription(String newName) async { Future<dynamic> setDescription(String newName) async {
dynamic res = await client.connection.jsonRequest( dynamic res = await client.connection.jsonRequest(
type: "PUT", type: HTTPType.PUT,
action: action:
"/client/r0/rooms/${id}/send/m.room.topic/${new DateTime.now()}", "/client/r0/rooms/${id}/send/m.room.topic/${new DateTime.now()}",
data: {"topic": newName}); data: {"topic": newName});
@ -162,7 +164,7 @@ class Room {
Future<dynamic> sendText(String message, {String txid = null}) async { Future<dynamic> sendText(String message, {String txid = null}) async {
if (txid == null) txid = "txid${DateTime.now().millisecondsSinceEpoch}"; if (txid == null) txid = "txid${DateTime.now().millisecondsSinceEpoch}";
final dynamic res = await client.connection.jsonRequest( final dynamic res = await client.connection.jsonRequest(
type: "PUT", type: HTTPType.PUT,
action: "/client/r0/rooms/${id}/send/m.room.message/$txid", action: "/client/r0/rooms/${id}/send/m.room.message/$txid",
data: {"msgtype": "m.text", "body": message}); data: {"msgtype": "m.text", "body": message});
if (res is ErrorResponse) client.connection.onError.add(res); if (res is ErrorResponse) client.connection.onError.add(res);
@ -197,6 +199,7 @@ class Room {
client.connection.onEvent.add(eventUpdate); client.connection.onEvent.add(eventUpdate);
await client.store?.transaction(() { await client.store?.transaction(() {
client.store.storeEventUpdate(eventUpdate); client.store.storeEventUpdate(eventUpdate);
return;
}); });
// Send the text and on success, store and display a *sent* event. // Send the text and on success, store and display a *sent* event.
@ -208,6 +211,7 @@ class Room {
client.connection.onEvent.add(eventUpdate); client.connection.onEvent.add(eventUpdate);
await client.store?.transaction(() { await client.store?.transaction(() {
client.store.storeEventUpdate(eventUpdate); client.store.storeEventUpdate(eventUpdate);
return;
}); });
} else { } else {
eventUpdate.content["status"] = 1; eventUpdate.content["status"] = 1;
@ -215,6 +219,7 @@ class Room {
client.connection.onEvent.add(eventUpdate); client.connection.onEvent.add(eventUpdate);
await client.store?.transaction(() { await client.store?.transaction(() {
client.store.storeEventUpdate(eventUpdate); client.store.storeEventUpdate(eventUpdate);
return;
}); });
return res["event_id"]; return res["event_id"];
} }
@ -223,8 +228,8 @@ class Room {
/// Call the Matrix API to leave this room. /// Call the Matrix API to leave this room.
Future<dynamic> leave() async { Future<dynamic> leave() async {
dynamic res = await client.connection dynamic res = await client.connection.jsonRequest(
.jsonRequest(type: "POST", action: "/client/r0/rooms/${id}/leave"); type: HTTPType.POST, action: "/client/r0/rooms/${id}/leave");
if (res is ErrorResponse) client.connection.onError.add(res); if (res is ErrorResponse) client.connection.onError.add(res);
return res; return res;
} }
@ -232,8 +237,8 @@ class Room {
/// Call the Matrix API to forget this room if you already left it. /// Call the Matrix API to forget this room if you already left it.
Future<dynamic> forget() async { Future<dynamic> forget() async {
client.store.forgetRoom(id); client.store.forgetRoom(id);
dynamic res = await client.connection dynamic res = await client.connection.jsonRequest(
.jsonRequest(type: "POST", action: "/client/r0/rooms/${id}/forget"); type: HTTPType.POST, action: "/client/r0/rooms/${id}/forget");
if (res is ErrorResponse) client.connection.onError.add(res); if (res is ErrorResponse) client.connection.onError.add(res);
return res; return res;
} }
@ -241,7 +246,7 @@ class Room {
/// Call the Matrix API to kick a user from this room. /// Call the Matrix API to kick a user from this room.
Future<dynamic> kick(String userID) async { Future<dynamic> kick(String userID) async {
dynamic res = await client.connection.jsonRequest( dynamic res = await client.connection.jsonRequest(
type: "POST", type: HTTPType.POST,
action: "/client/r0/rooms/${id}/kick", action: "/client/r0/rooms/${id}/kick",
data: {"user_id": userID}); data: {"user_id": userID});
if (res is ErrorResponse) client.connection.onError.add(res); if (res is ErrorResponse) client.connection.onError.add(res);
@ -251,7 +256,7 @@ class Room {
/// Call the Matrix API to ban a user from this room. /// Call the Matrix API to ban a user from this room.
Future<dynamic> ban(String userID) async { Future<dynamic> ban(String userID) async {
dynamic res = await client.connection.jsonRequest( dynamic res = await client.connection.jsonRequest(
type: "POST", type: HTTPType.POST,
action: "/client/r0/rooms/${id}/ban", action: "/client/r0/rooms/${id}/ban",
data: {"user_id": userID}); data: {"user_id": userID});
if (res is ErrorResponse) client.connection.onError.add(res); if (res is ErrorResponse) client.connection.onError.add(res);
@ -261,7 +266,7 @@ class Room {
/// Call the Matrix API to unban a banned user from this room. /// Call the Matrix API to unban a banned user from this room.
Future<dynamic> unban(String userID) async { Future<dynamic> unban(String userID) async {
dynamic res = await client.connection.jsonRequest( dynamic res = await client.connection.jsonRequest(
type: "POST", type: HTTPType.POST,
action: "/client/r0/rooms/${id}/unban", action: "/client/r0/rooms/${id}/unban",
data: {"user_id": userID}); data: {"user_id": userID});
if (res is ErrorResponse) client.connection.onError.add(res); if (res is ErrorResponse) client.connection.onError.add(res);
@ -274,7 +279,7 @@ class Room {
powerMap[userID] = power; powerMap[userID] = power;
dynamic res = await client.connection.jsonRequest( dynamic res = await client.connection.jsonRequest(
type: "PUT", type: HTTPType.PUT,
action: "/client/r0/rooms/$id/state/m.room.power_levels/", action: "/client/r0/rooms/$id/state/m.room.power_levels/",
data: {"users": powerMap}); data: {"users": powerMap});
if (res is ErrorResponse) client.connection.onError.add(res); if (res is ErrorResponse) client.connection.onError.add(res);
@ -284,7 +289,7 @@ class Room {
/// Call the Matrix API to invite a user to this room. /// Call the Matrix API to invite a user to this room.
Future<dynamic> invite(String userID) async { Future<dynamic> invite(String userID) async {
dynamic res = await client.connection.jsonRequest( dynamic res = await client.connection.jsonRequest(
type: "POST", type: HTTPType.POST,
action: "/client/r0/rooms/${id}/invite", action: "/client/r0/rooms/${id}/invite",
data: {"user_id": userID}); data: {"user_id": userID});
if (res is ErrorResponse) client.connection.onError.add(res); if (res is ErrorResponse) client.connection.onError.add(res);
@ -294,7 +299,7 @@ class Room {
/// Request more previous events from the server. /// Request more previous events from the server.
Future<void> requestHistory({int historyCount = 100}) async { Future<void> requestHistory({int historyCount = 100}) async {
final dynamic resp = await client.connection.jsonRequest( final dynamic resp = await client.connection.jsonRequest(
type: "GET", type: HTTPType.GET,
action: action:
"/client/r0/rooms/$id/messages?from=${prev_batch}&dir=b&limit=$historyCount"); "/client/r0/rooms/$id/messages?from=${prev_batch}&dir=b&limit=$historyCount");
@ -321,6 +326,7 @@ class Room {
client.store.txn.rawUpdate( client.store.txn.rawUpdate(
"UPDATE Rooms SET prev_batch=? WHERE id=?", [resp["end"], id]); "UPDATE Rooms SET prev_batch=? WHERE id=?", [resp["end"], id]);
} }
return;
}); });
if (client.store == null) { if (client.store == null) {
for (int i = 0; i < history.length; i++) { for (int i = 0; i < history.length; i++) {
@ -347,7 +353,7 @@ class Room {
directChats[userID] = [id]; directChats[userID] = [id];
final resp = await client.connection.jsonRequest( final resp = await client.connection.jsonRequest(
type: "PUT", type: HTTPType.PUT,
action: "/client/r0/user/${client.userID}/account_data/m.direct", action: "/client/r0/user/${client.userID}/account_data/m.direct",
data: directChats); data: directChats);
return resp; return resp;
@ -356,7 +362,7 @@ class Room {
/// Sends *m.fully_read* and *m.read* for the given event ID. /// Sends *m.fully_read* and *m.read* for the given event ID.
Future<dynamic> sendReadReceipt(String eventID) async { Future<dynamic> sendReadReceipt(String eventID) async {
final dynamic resp = client.connection.jsonRequest( final dynamic resp = client.connection.jsonRequest(
type: "POST", type: HTTPType.POST,
action: "/client/r0/rooms/$id/read_markers", action: "/client/r0/rooms/$id/read_markers",
data: { data: {
"m.fully_read": eventID, "m.fully_read": eventID,
@ -379,7 +385,8 @@ class Room {
return Room( return Room(
id: row["id"], id: row["id"],
name: name, name: name,
membership: row["membership"], membership: Membership.values
.firstWhere((e) => e.toString() == 'Membership.' + row["membership"]),
topic: row["description"], topic: row["description"],
avatar: MxContent(avatarUrl), avatar: MxContent(avatarUrl),
notificationCount: row["notification_count"], notificationCount: row["notification_count"],
@ -455,18 +462,21 @@ class Room {
Future<List<User>> requestParticipants() async { Future<List<User>> requestParticipants() async {
List<User> participants = []; List<User> participants = [];
dynamic res = await client.connection dynamic res = await client.connection.jsonRequest(
.jsonRequest(type: "GET", action: "/client/r0/rooms/${id}/members"); type: HTTPType.GET, action: "/client/r0/rooms/${id}/members");
if (res is ErrorResponse || !(res["chunk"] is List<dynamic>)) if (res is ErrorResponse || !(res["chunk"] is List<dynamic>))
return participants; return participants;
for (num i = 0; i < res["chunk"].length; i++) { for (num i = 0; i < res["chunk"].length; i++) {
User newUser = User(res["chunk"][i]["state_key"], User newUser = User(res["chunk"][i]["state_key"],
displayName: res["chunk"][i]["content"]["displayname"] ?? "", displayName: res["chunk"][i]["content"]["displayname"] ?? "",
membership: res["chunk"][i]["content"]["membership"] ?? "", membership: Membership.values.firstWhere((e) =>
e.toString() ==
'Membership.' + res["chunk"][i]["content"]["membership"] ??
""),
avatarUrl: MxContent(res["chunk"][i]["content"]["avatar_url"] ?? ""), avatarUrl: MxContent(res["chunk"][i]["content"]["avatar_url"] ?? ""),
room: this); room: this);
if (newUser.membership != "leave") participants.add(newUser); if (newUser.membership != Membership.leave) participants.add(newUser);
} }
return participants; return participants;
@ -480,7 +490,7 @@ class Room {
if (storeEvent != null) return storeEvent; if (storeEvent != null) return storeEvent;
} }
final dynamic resp = await client.connection.jsonRequest( final dynamic resp = await client.connection.jsonRequest(
type: "GET", action: "/client/r0/rooms/$id/event/$eventID"); type: HTTPType.GET, action: "/client/r0/rooms/$id/event/$eventID");
if (resp is ErrorResponse) return null; if (resp is ErrorResponse) return null;
return Event.fromJson(resp, this); return Event.fromJson(resp, this);
} }

View file

@ -23,14 +23,15 @@
import 'dart:async'; import 'dart:async';
import 'dart:core'; import 'dart:core';
import 'Client.dart'; import 'Client.dart';
import 'Event.dart'; import 'Event.dart';
import 'Room.dart'; import 'Room.dart';
import 'User.dart'; import 'User.dart';
import 'utils/ChatTime.dart';
import 'utils/MxContent.dart';
import 'sync/EventUpdate.dart'; import 'sync/EventUpdate.dart';
import 'sync/RoomUpdate.dart'; import 'sync/RoomUpdate.dart';
import 'utils/ChatTime.dart';
import 'utils/MxContent.dart';
/// Represents a list of rooms for this client, which will automatically update /// Represents a list of rooms for this client, which will automatically update
/// itself and call the [onUpdate], [onInsert] and [onDelete] callbacks. To get /// itself and call the [onUpdate], [onInsert] and [onDelete] callbacks. To get
@ -78,11 +79,11 @@ class RoomList {
if (rooms[j].id == chatUpdate.id) break; if (rooms[j].id == chatUpdate.id) break;
} }
final bool found = (j < rooms.length - 1 && rooms[j].id == chatUpdate.id); final bool found = (j < rooms.length - 1 && rooms[j].id == chatUpdate.id);
final bool isLeftRoom = chatUpdate.membership == "leave"; final bool isLeftRoom = chatUpdate.membership == Membership.leave;
// Does the chat already exist in the list rooms? // Does the chat already exist in the list rooms?
if (!found && ((!onlyLeft && !isLeftRoom) || (onlyLeft && isLeftRoom))) { if (!found && ((!onlyLeft && !isLeftRoom) || (onlyLeft && isLeftRoom))) {
num position = chatUpdate.membership == "invite" ? 0 : j; num position = chatUpdate.membership == Membership.invite ? 0 : j;
// Add the new chat to the list // Add the new chat to the list
Room newRoom = Room( Room newRoom = Room(
id: chatUpdate.id, id: chatUpdate.id,
@ -102,7 +103,7 @@ class RoomList {
} }
// Update notification and highlight count // Update notification and highlight count
else if (found && else if (found &&
chatUpdate.membership != "leave" && chatUpdate.membership != Membership.leave &&
(rooms[j].notificationCount != chatUpdate.notification_count || (rooms[j].notificationCount != chatUpdate.notification_count ||
rooms[j].highlightCount != chatUpdate.highlight_count)) { rooms[j].highlightCount != chatUpdate.highlight_count)) {
rooms[j].notificationCount = chatUpdate.notification_count; rooms[j].notificationCount = chatUpdate.notification_count;

View file

@ -24,16 +24,18 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:core'; import 'dart:core';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart' as p; import 'package:path/path.dart' as p;
import 'sync/EventUpdate.dart'; import 'package:sqflite/sqflite.dart';
import 'sync/UserUpdate.dart';
import 'sync/RoomUpdate.dart';
import 'Client.dart'; import 'Client.dart';
import 'User.dart';
import 'Room.dart';
import 'Event.dart';
import 'Connection.dart'; import 'Connection.dart';
import 'Event.dart';
import 'Room.dart';
import 'User.dart';
import 'sync/EventUpdate.dart';
import 'sync/RoomUpdate.dart';
import 'sync/UserUpdate.dart';
/// Responsible to store all data persistent and to query objects from the /// Responsible to store all data persistent and to query objects from the
/// database. /// database.
@ -53,7 +55,7 @@ class Store {
_init() async { _init() async {
var databasePath = await getDatabasesPath(); var databasePath = await getDatabasesPath();
String path = p.join(databasePath, "FluffyMatrix.db"); String path = p.join(databasePath, "FluffyMatrix.db");
_db = await openDatabase(path, version: 4, _db = await openDatabase(path, version: 5,
onCreate: (Database db, int version) async { onCreate: (Database db, int version) async {
await createTables(db); await createTables(db);
}, onUpgrade: (Database db, int oldVersion, int newVersion) async { }, onUpgrade: (Database db, int oldVersion, int newVersion) async {
@ -61,7 +63,7 @@ class Store {
if (oldVersion != newVersion) { if (oldVersion != newVersion) {
await db.execute("DROP TABLE IF EXISTS Rooms"); await db.execute("DROP TABLE IF EXISTS Rooms");
await db.execute("DROP TABLE IF EXISTS Participants"); await db.execute("DROP TABLE IF EXISTS Participants");
await db.execute("DROP TABLE IF EXISTS User"); await db.execute("DROP TABLE IF EXISTS Users");
await db.execute("DROP TABLE IF EXISTS Events"); await db.execute("DROP TABLE IF EXISTS Events");
db.rawUpdate("UPDATE Clients SET prev_batch='' WHERE client=?", db.rawUpdate("UPDATE Clients SET prev_batch='' WHERE client=?",
[client.clientName]); [client.clientName]);
@ -127,7 +129,7 @@ class Store {
await _db await _db
.rawDelete("DELETE FROM Clients WHERE client=?", [client.clientName]); .rawDelete("DELETE FROM Clients WHERE client=?", [client.clientName]);
await _db.rawDelete("DELETE FROM Rooms"); await _db.rawDelete("DELETE FROM Rooms");
await _db.rawDelete("DELETE FROM User"); await _db.rawDelete("DELETE FROM Users");
await _db.rawDelete("DELETE FROM Events"); await _db.rawDelete("DELETE FROM Events");
return; return;
} }
@ -162,7 +164,7 @@ class Store {
txn.rawInsert( txn.rawInsert(
"INSERT OR IGNORE INTO Rooms " + "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, 50, 50, 0, 50, 50, 0, 50, 100, 50, 50, 50, 100) ",
[roomUpdate.id, roomUpdate.membership]); [roomUpdate.id, roomUpdate.membership.toString().split('.').last]);
// Update the notification counts and the limited timeline boolean // Update the notification counts and the limited timeline boolean
txn.rawUpdate( txn.rawUpdate(
@ -170,7 +172,7 @@ class Store {
[ [
roomUpdate.highlight_count, roomUpdate.highlight_count,
roomUpdate.notification_count, roomUpdate.notification_count,
roomUpdate.membership, roomUpdate.membership.toString().split('.').last,
roomUpdate.id roomUpdate.id
]); ]);
@ -329,14 +331,14 @@ class Store {
} }
// Update membership table // Update membership table
txn.rawInsert("INSERT OR IGNORE INTO User VALUES(?,?,?,?,?,0)", [ txn.rawInsert("INSERT OR IGNORE INTO Users VALUES(?,?,?,?,?,0)", [
chat_id, chat_id,
state_key, state_key,
insertDisplayname, insertDisplayname,
insertAvatarUrl, insertAvatarUrl,
membership membership
]); ]);
String queryStr = "UPDATE User SET membership=?"; String queryStr = "UPDATE Users SET membership=?";
List<String> queryArgs = [membership]; List<String> queryArgs = [membership];
if (eventContent["content"]["displayname"] is String) { if (eventContent["content"]["displayname"] is String) {
@ -411,10 +413,10 @@ class Store {
.forEach((String user, dynamic value) async { .forEach((String user, dynamic value) async {
num power_level = eventContent["content"]["users"][user]; num power_level = eventContent["content"]["users"][user];
txn.rawUpdate( txn.rawUpdate(
"UPDATE User SET power_level=? WHERE matrix_id=? AND chat_id=?", "UPDATE Users SET power_level=? WHERE matrix_id=? AND chat_id=?",
[power_level, user, chat_id]); [power_level, user, chat_id]);
txn.rawInsert( txn.rawInsert(
"INSERT OR IGNORE INTO User VALUES(?, ?, '', '', ?, ?)", "INSERT OR IGNORE INTO Users VALUES(?, ?, '', '', ?, ?)",
[chat_id, user, "unknown", power_level]); [chat_id, user, "unknown", power_level]);
}); });
} }
@ -426,7 +428,7 @@ class Store {
/// Returns a User object by a given Matrix ID and a Room. /// Returns a User object by a given Matrix ID and a Room.
Future<User> getUser({String matrixID, Room room}) async { Future<User> getUser({String matrixID, Room room}) async {
List<Map<String, dynamic>> res = await db.rawQuery( List<Map<String, dynamic>> res = await db.rawQuery(
"SELECT * FROM User WHERE matrix_id=? AND chat_id=?", "SELECT * FROM Users WHERE matrix_id=? AND chat_id=?",
[matrixID, room.id]); [matrixID, room.id]);
if (res.length != 1) return null; if (res.length != 1) return null;
return User.fromJson(res[0], room); return User.fromJson(res[0], room);
@ -435,7 +437,7 @@ class Store {
/// Loads all Users in the database to provide a contact list. /// Loads all Users in the database to provide a contact list.
Future<List<User>> loadContacts() async { Future<List<User>> loadContacts() async {
List<Map<String, dynamic>> res = await db.rawQuery( List<Map<String, dynamic>> res = await db.rawQuery(
"SELECT * FROM User WHERE matrix_id!=? GROUP BY matrix_id ORDER BY displayname", "SELECT * FROM Users WHERE matrix_id!=? GROUP BY matrix_id ORDER BY displayname",
[client.userID]); [client.userID]);
List<User> userList = []; List<User> userList = [];
for (int i = 0; i < res.length; i++) for (int i = 0; i < res.length; i++)
@ -447,7 +449,7 @@ class Store {
Future<List<User>> loadParticipants(Room room) async { Future<List<User>> loadParticipants(Room room) async {
List<Map<String, dynamic>> res = await db.rawQuery( List<Map<String, dynamic>> res = await db.rawQuery(
"SELECT * " + "SELECT * " +
" FROM User " + " FROM Users " +
" WHERE chat_id=? " + " WHERE chat_id=? " +
" AND membership='join'", " AND membership='join'",
[room.id]); [room.id]);
@ -464,7 +466,7 @@ class Store {
/// Returns a list of events for the given room and sets all participants. /// Returns a list of events for the given room and sets all participants.
Future<List<Event>> getEventList(Room room) async { Future<List<Event>> getEventList(Room room) async {
List<Map<String, dynamic>> memberRes = await db.rawQuery( List<Map<String, dynamic>> memberRes = await db.rawQuery(
"SELECT * " + " FROM User " + " WHERE User.chat_id=?", [room.id]); "SELECT * " + " FROM Users " + " WHERE Users.chat_id=?", [room.id]);
Map<String, User> userMap = {}; Map<String, User> userMap = {};
for (num i = 0; i < memberRes.length; i++) for (num i = 0; i < memberRes.length; i++)
userMap[memberRes[i]["matrix_id"]] = User.fromJson(memberRes[i], room); userMap[memberRes[i]["matrix_id"]] = User.fromJson(memberRes[i], room);
@ -528,10 +530,10 @@ class Store {
Future<String> getAvatarFromSingleChat(String roomID) async { Future<String> getAvatarFromSingleChat(String roomID) async {
String avatarStr = ""; String avatarStr = "";
List<Map<String, dynamic>> res = await db.rawQuery( List<Map<String, dynamic>> res = await db.rawQuery(
"SELECT avatar_url FROM User " + "SELECT avatar_url FROM Users " +
" WHERE User.chat_id=? " + " WHERE Users.chat_id=? " +
" AND (User.membership='join' OR User.membership='invite') " + " AND (Users.membership='join' OR Users.membership='invite') " +
" AND User.matrix_id!=? ", " AND Users.matrix_id!=? ",
[roomID, client.userID]); [roomID, client.userID]);
if (res.length == 1) avatarStr = res[0]["avatar_url"]; if (res.length == 1) avatarStr = res[0]["avatar_url"];
return avatarStr; return avatarStr;
@ -543,10 +545,10 @@ class Store {
Future<String> getChatNameFromMemberNames(String roomID) async { Future<String> getChatNameFromMemberNames(String roomID) async {
String displayname = 'Empty chat'; String displayname = 'Empty chat';
List<Map<String, dynamic>> rs = await db.rawQuery( List<Map<String, dynamic>> rs = await db.rawQuery(
"SELECT User.displayname, User.matrix_id, User.membership FROM User " + "SELECT Users.displayname, Users.matrix_id, Users.membership FROM Users " +
" WHERE User.chat_id=? " + " WHERE Users.chat_id=? " +
" AND (User.membership='join' OR User.membership='invite') " + " AND (Users.membership='join' OR Users.membership='invite') " +
" AND User.matrix_id!=? ", " AND Users.matrix_id!=? ",
[roomID, client.userID]); [roomID, client.userID]);
if (rs.length > 0) { if (rs.length > 0) {
displayname = ""; displayname = "";
@ -576,7 +578,7 @@ class Store {
/// the room or the own user wasn't found. /// the room or the own user wasn't found.
Future<int> getPowerLevel(String roomID) async { Future<int> getPowerLevel(String roomID) async {
List<Map<String, dynamic>> res = await db.rawQuery( List<Map<String, dynamic>> res = await db.rawQuery(
"SELECT power_level FROM User WHERE matrix_id=? AND chat_id=?", "SELECT power_level FROM Users WHERE matrix_id=? AND chat_id=?",
[roomID, client.userID]); [roomID, client.userID]);
if (res.length != 1) return null; if (res.length != 1) return null;
return res[0]["power_level"]; return res[0]["power_level"];
@ -585,7 +587,7 @@ class Store {
/// Returns the power levels from all users for the given [roomID]. /// Returns the power levels from all users for the given [roomID].
Future<Map<String, int>> getPowerLevels(String roomID) async { Future<Map<String, int>> getPowerLevels(String roomID) async {
List<Map<String, dynamic>> res = await db.rawQuery( List<Map<String, dynamic>> res = await db.rawQuery(
"SELECT matrix_id, power_level FROM User WHERE chat_id=?", "SELECT matrix_id, power_level FROM Users WHERE chat_id=?",
[roomID, client.userID]); [roomID, client.userID]);
Map<String, int> powerMap = {}; Map<String, int> powerMap = {};
for (int i = 0; i < res.length; i++) for (int i = 0; i < res.length; i++)
@ -686,7 +688,7 @@ class Store {
'UNIQUE(id))'; 'UNIQUE(id))';
/// The database sheme for the User class. /// The database sheme for the User class.
static final String UserScheme = 'CREATE TABLE IF NOT EXISTS User(' + static final String UserScheme = 'CREATE TABLE IF NOT EXISTS Users(' +
'chat_id TEXT, ' + // The chat id of this membership 'chat_id TEXT, ' + // The chat id of this membership
'matrix_id TEXT, ' + // The matrix id of this user 'matrix_id TEXT, ' + // The matrix id of this user
'displayname TEXT, ' + 'displayname TEXT, ' +

View file

@ -22,6 +22,7 @@
*/ */
import 'dart:async'; import 'dart:async';
import 'Event.dart'; import 'Event.dart';
import 'Room.dart'; import 'Room.dart';
import 'User.dart'; import 'User.dart';
@ -94,7 +95,9 @@ class Timeline {
} }
sortAndUpdate(); sortAndUpdate();
} catch (e) { } catch (e) {
print("[WARNING] (_handleEventUpdate) ${e.toString()}"); if (room.client.debug) {
print("[WARNING] (_handleEventUpdate) ${e.toString()}");
}
} }
} }

View file

@ -21,9 +21,13 @@
* along with famedlysdk. If not, see <http://www.gnu.org/licenses/>. * along with famedlysdk. If not, see <http://www.gnu.org/licenses/>.
*/ */
import 'package:famedlysdk/src/Room.dart';
import 'package:famedlysdk/src/responses/ErrorResponse.dart'; import 'package:famedlysdk/src/responses/ErrorResponse.dart';
import 'package:famedlysdk/src/utils/MxContent.dart'; import 'package:famedlysdk/src/utils/MxContent.dart';
import 'package:famedlysdk/src/Room.dart';
import 'Connection.dart';
enum Membership { join, invite, leave, ban }
/// Represents a Matrix User which may be a participant in a Matrix Room. /// Represents a Matrix User which may be a participant in a Matrix Room.
class User { class User {
@ -38,7 +42,7 @@ class User {
/// invite /// invite
/// leave /// leave
/// ban /// ban
String membership; Membership membership;
/// The avatar if the user has one. /// The avatar if the user has one.
MxContent avatarUrl; MxContent avatarUrl;
@ -53,7 +57,7 @@ class User {
final Room room; final Room room;
@Deprecated("Use membership instead!") @Deprecated("Use membership instead!")
String get status => membership; String get status => membership.toString().split('.').last;
@Deprecated("Use ID instead!") @Deprecated("Use ID instead!")
String get mxid => id; String get mxid => id;
@ -81,7 +85,12 @@ class User {
return User(json['matrix_id'] ?? json['sender'], return User(json['matrix_id'] ?? json['sender'],
displayName: json['displayname'], displayName: json['displayname'],
avatarUrl: MxContent(json['avatar_url']), avatarUrl: MxContent(json['avatar_url']),
membership: json['membership'], membership: Membership.values.firstWhere((e) {
if (json["membership"] != null) {
return e.toString() == 'Membership.' + json['membership'];
}
return false;
}, orElse: () => null),
powerLevel: json['power_level'], powerLevel: json['power_level'],
room: room); room: room);
} }
@ -132,12 +141,14 @@ class User {
if (roomID != null) return roomID; if (roomID != null) return roomID;
// Start a new direct chat // Start a new direct chat
final dynamic resp = await room.client.connection final dynamic resp = await room.client.connection.jsonRequest(
.jsonRequest(type: "POST", action: "/client/r0/createRoom", data: { type: HTTPType.POST,
"invite": [id], action: "/client/r0/createRoom",
"is_direct": true, data: {
"preset": "trusted_private_chat" "invite": [id],
}); "is_direct": true,
"preset": "trusted_private_chat"
});
if (resp is ErrorResponse) { if (resp is ErrorResponse) {
room.client.connection.onError.add(resp); room.client.connection.onError.add(resp);

View file

@ -21,6 +21,8 @@
* along with famedlysdk. If not, see <http://www.gnu.org/licenses/>. * along with famedlysdk. If not, see <http://www.gnu.org/licenses/>.
*/ */
import '../User.dart';
/// Represents a new room or an update for an /// Represents a new room or an update for an
/// already known room. /// already known room.
class RoomUpdate { class RoomUpdate {
@ -28,7 +30,7 @@ class RoomUpdate {
final String id; final String id;
/// The current membership state of the user in this room. /// The current membership state of the user in this room.
final String membership; final Membership membership;
/// Represents the number of unead notifications. This probably doesn't fit the number /// Represents the number of unead notifications. This probably doesn't fit the number
/// of unread messages. /// of unread messages.

View file

@ -21,16 +21,18 @@
* along with famedlysdk. If not, see <http://www.gnu.org/licenses/>. * along with famedlysdk. If not, see <http://www.gnu.org/licenses/>.
*/ */
import 'package:famedlysdk/src/responses/PushrulesResponse.dart'; import 'dart:async';
import 'package:flutter_test/flutter_test.dart';
import 'package:famedlysdk/src/Client.dart'; import 'package:famedlysdk/src/Client.dart';
import 'package:famedlysdk/src/Connection.dart'; import 'package:famedlysdk/src/Connection.dart';
import 'package:famedlysdk/src/User.dart'; import 'package:famedlysdk/src/User.dart';
import 'package:famedlysdk/src/responses/ErrorResponse.dart';
import 'package:famedlysdk/src/responses/PushrulesResponse.dart';
import 'package:famedlysdk/src/sync/EventUpdate.dart'; import 'package:famedlysdk/src/sync/EventUpdate.dart';
import 'package:famedlysdk/src/sync/RoomUpdate.dart'; import 'package:famedlysdk/src/sync/RoomUpdate.dart';
import 'package:famedlysdk/src/sync/UserUpdate.dart'; import 'package:famedlysdk/src/sync/UserUpdate.dart';
import 'package:famedlysdk/src/responses/ErrorResponse.dart'; import 'package:flutter_test/flutter_test.dart';
import 'dart:async';
import 'FakeMatrixApi.dart'; import 'FakeMatrixApi.dart';
void main() { void main() {
@ -70,7 +72,7 @@ void main() {
expect(checkError.errcode, "NO_RESPONSE"); expect(checkError.errcode, "NO_RESPONSE");
final resp = await matrix.connection final resp = await matrix.connection
.jsonRequest(type: "POST", action: "/client/r0/login", data: { .jsonRequest(type: HTTPType.POST, action: "/client/r0/login", data: {
"type": "m.login.password", "type": "m.login.password",
"user": "test", "user": "test",
"password": "1234", "password": "1234",
@ -108,13 +110,13 @@ void main() {
test('Try to get ErrorResponse', () async { test('Try to get ErrorResponse', () async {
final resp = await matrix.connection final resp = await matrix.connection
.jsonRequest(type: "PUT", action: "/non/existing/path"); .jsonRequest(type: HTTPType.PUT, action: "/non/existing/path");
expect(resp is ErrorResponse, true); expect(resp is ErrorResponse, true);
}); });
test('Logout', () async { test('Logout', () async {
final dynamic resp = await matrix.connection final dynamic resp = await matrix.connection
.jsonRequest(type: "POST", action: "/client/r0/logout"); .jsonRequest(type: HTTPType.POST, action: "/client/r0/logout");
expect(resp is ErrorResponse, false); expect(resp is ErrorResponse, false);
Future<LoginState> loginStateFuture = Future<LoginState> loginStateFuture =
@ -143,21 +145,21 @@ void main() {
expect(roomUpdateList.length, 3); expect(roomUpdateList.length, 3);
expect(roomUpdateList[0].id == "!726s6s6q:example.com", true); expect(roomUpdateList[0].id == "!726s6s6q:example.com", true);
expect(roomUpdateList[0].membership == "join", true); expect(roomUpdateList[0].membership == Membership.join, true);
expect(roomUpdateList[0].prev_batch == "t34-23535_0_0", true); expect(roomUpdateList[0].prev_batch == "t34-23535_0_0", true);
expect(roomUpdateList[0].limitedTimeline == true, true); expect(roomUpdateList[0].limitedTimeline == true, true);
expect(roomUpdateList[0].notification_count == 2, true); expect(roomUpdateList[0].notification_count == 2, true);
expect(roomUpdateList[0].highlight_count == 2, true); expect(roomUpdateList[0].highlight_count == 2, true);
expect(roomUpdateList[1].id == "!696r7674:example.com", true); expect(roomUpdateList[1].id == "!696r7674:example.com", true);
expect(roomUpdateList[1].membership == "invite", true); expect(roomUpdateList[1].membership == Membership.invite, true);
expect(roomUpdateList[1].prev_batch == "", true); expect(roomUpdateList[1].prev_batch == "", true);
expect(roomUpdateList[1].limitedTimeline == false, true); expect(roomUpdateList[1].limitedTimeline == false, true);
expect(roomUpdateList[1].notification_count == 0, true); expect(roomUpdateList[1].notification_count == 0, true);
expect(roomUpdateList[1].highlight_count == 0, true); expect(roomUpdateList[1].highlight_count == 0, true);
expect(roomUpdateList[2].id == "!5345234234:example.com", true); expect(roomUpdateList[2].id == "!5345234234:example.com", true);
expect(roomUpdateList[2].membership == "leave", true); expect(roomUpdateList[2].membership == Membership.leave, true);
expect(roomUpdateList[2].prev_batch == "", true); expect(roomUpdateList[2].prev_batch == "", true);
expect(roomUpdateList[2].limitedTimeline == false, true); expect(roomUpdateList[2].limitedTimeline == false, true);
expect(roomUpdateList[2].notification_count == 0, true); expect(roomUpdateList[2].notification_count == 0, true);
@ -250,7 +252,7 @@ void main() {
Future<LoginState> loginStateFuture = Future<LoginState> loginStateFuture =
matrix.connection.onLoginStateChanged.stream.first; matrix.connection.onLoginStateChanged.stream.first;
await matrix.connection await matrix.connection
.jsonRequest(type: "DELETE", action: "/unknown/token"); .jsonRequest(type: HTTPType.DELETE, action: "/unknown/token");
LoginState state = await loginStateFuture; LoginState state = await loginStateFuture;
expect(state, LoginState.loggedOut); expect(state, LoginState.loggedOut);

View file

@ -21,8 +21,9 @@
* along with famedlysdk. If not, see <http://www.gnu.org/licenses/>. * along with famedlysdk. If not, see <http://www.gnu.org/licenses/>.
*/ */
import 'package:flutter_test/flutter_test.dart';
import 'package:famedlysdk/src/Event.dart'; import 'package:famedlysdk/src/Event.dart';
import 'package:famedlysdk/src/User.dart';
import 'package:flutter_test/flutter_test.dart';
void main() { void main() {
/// All Tests related to the Event /// All Tests related to the Event
@ -33,7 +34,7 @@ void main() {
final String senderID = "@alice:server.abc"; final String senderID = "@alice:server.abc";
final String senderDisplayname = "Alice"; final String senderDisplayname = "Alice";
final String empty = ""; final String empty = "";
final String membership = "join"; final Membership membership = Membership.join;
final String type = "m.room.message"; final String type = "m.room.message";
final String msgtype = "m.text"; final String msgtype = "m.text";
final String body = "Hello World"; final String body = "Hello World";
@ -47,7 +48,7 @@ void main() {
"matrix_id": senderID, "matrix_id": senderID,
"displayname": senderDisplayname, "displayname": senderDisplayname,
"avatar_url": empty, "avatar_url": empty,
"membership": membership, "membership": membership.toString().split('.').last,
"origin_server_ts": timestamp, "origin_server_ts": timestamp,
"state_key": empty, "state_key": empty,
"type": type, "type": type,

View file

@ -21,12 +21,13 @@
* along with famedlysdk. If not, see <http://www.gnu.org/licenses/>. * along with famedlysdk. If not, see <http://www.gnu.org/licenses/>.
*/ */
import 'package:flutter_test/flutter_test.dart';
import 'package:famedlysdk/src/Client.dart'; import 'package:famedlysdk/src/Client.dart';
import 'package:famedlysdk/src/RoomList.dart'; import 'package:famedlysdk/src/RoomList.dart';
import 'package:famedlysdk/src/User.dart';
import 'package:famedlysdk/src/sync/EventUpdate.dart'; import 'package:famedlysdk/src/sync/EventUpdate.dart';
import 'package:famedlysdk/src/sync/RoomUpdate.dart'; import 'package:famedlysdk/src/sync/RoomUpdate.dart';
import 'package:famedlysdk/src/utils/ChatTime.dart'; import 'package:famedlysdk/src/utils/ChatTime.dart';
import 'package:flutter_test/flutter_test.dart';
void main() { void main() {
/// All Tests related to the MxContent /// All Tests related to the MxContent
@ -59,7 +60,7 @@ void main() {
client.connection.onRoomUpdate.add(RoomUpdate( client.connection.onRoomUpdate.add(RoomUpdate(
id: roomID, id: roomID,
membership: "join", membership: Membership.join,
notification_count: 2, notification_count: 2,
highlight_count: 1, highlight_count: 1,
limitedTimeline: false, limitedTimeline: false,
@ -74,7 +75,7 @@ void main() {
expect(roomList.rooms.length, 1); expect(roomList.rooms.length, 1);
expect(roomList.rooms[0].id, roomID); expect(roomList.rooms[0].id, roomID);
expect(roomList.rooms[0].membership, "join"); expect(roomList.rooms[0].membership, Membership.join);
expect(roomList.rooms[0].notificationCount, 2); expect(roomList.rooms[0].notificationCount, 2);
expect(roomList.rooms[0].highlightCount, 1); expect(roomList.rooms[0].highlightCount, 1);
expect(roomList.rooms[0].prev_batch, "1234"); expect(roomList.rooms[0].prev_batch, "1234");
@ -104,7 +105,7 @@ void main() {
client.connection.onRoomUpdate.add(RoomUpdate( client.connection.onRoomUpdate.add(RoomUpdate(
id: "1", id: "1",
membership: "join", membership: Membership.join,
notification_count: 2, notification_count: 2,
highlight_count: 1, highlight_count: 1,
limitedTimeline: false, limitedTimeline: false,
@ -112,7 +113,7 @@ void main() {
)); ));
client.connection.onRoomUpdate.add(RoomUpdate( client.connection.onRoomUpdate.add(RoomUpdate(
id: "2", id: "2",
membership: "join", membership: Membership.join,
notification_count: 2, notification_count: 2,
highlight_count: 1, highlight_count: 1,
limitedTimeline: false, limitedTimeline: false,
@ -193,7 +194,7 @@ void main() {
client.connection.onRoomUpdate.add(RoomUpdate( client.connection.onRoomUpdate.add(RoomUpdate(
id: "1", id: "1",
membership: "join", membership: Membership.join,
notification_count: 2, notification_count: 2,
highlight_count: 1, highlight_count: 1,
limitedTimeline: false, limitedTimeline: false,
@ -201,7 +202,7 @@ void main() {
)); ));
client.connection.onRoomUpdate.add(RoomUpdate( client.connection.onRoomUpdate.add(RoomUpdate(
id: "2", id: "2",
membership: "leave", membership: Membership.leave,
notification_count: 2, notification_count: 2,
highlight_count: 1, highlight_count: 1,
limitedTimeline: false, limitedTimeline: false,

View file

@ -21,11 +21,12 @@
* along with famedlysdk. If not, see <http://www.gnu.org/licenses/>. * along with famedlysdk. If not, see <http://www.gnu.org/licenses/>.
*/ */
import 'package:flutter_test/flutter_test.dart';
import 'package:famedlysdk/src/Room.dart';
import 'package:famedlysdk/src/Client.dart'; import 'package:famedlysdk/src/Client.dart';
import 'package:famedlysdk/src/Event.dart'; import 'package:famedlysdk/src/Event.dart';
import 'package:famedlysdk/src/Room.dart';
import 'package:famedlysdk/src/User.dart'; import 'package:famedlysdk/src/User.dart';
import 'package:flutter_test/flutter_test.dart';
import 'FakeMatrixApi.dart'; import 'FakeMatrixApi.dart';
void main() { void main() {
@ -50,7 +51,7 @@ void main() {
test("Create from json", () async { test("Create from json", () async {
final String id = "!localpart:server.abc"; final String id = "!localpart:server.abc";
final String name = "My Room"; final String name = "My Room";
final String membership = "join"; final Membership membership = Membership.join;
final String topic = "This is my own room"; final String topic = "This is my own room";
final int unread = DateTime.now().millisecondsSinceEpoch; final int unread = DateTime.now().millisecondsSinceEpoch;
final int notificationCount = 2; final int notificationCount = 2;
@ -69,7 +70,7 @@ void main() {
final Map<String, dynamic> jsonObj = { final Map<String, dynamic> jsonObj = {
"id": id, "id": id,
"membership": membership, "membership": membership.toString().split('.').last,
"topic": name, "topic": name,
"description": topic, "description": topic,
"avatar_url": "", "avatar_url": "",
@ -137,7 +138,7 @@ void main() {
User user = participants[0]; User user = participants[0];
expect(user.id, "@alice:example.org"); expect(user.id, "@alice:example.org");
expect(user.displayName, "Alice Margatroid"); expect(user.displayName, "Alice Margatroid");
expect(user.membership, "join"); expect(user.membership, Membership.join);
expect(user.avatarUrl.mxc, "mxc://example.org/SEsfnsuifSDFSSEF"); expect(user.avatarUrl.mxc, "mxc://example.org/SEsfnsuifSDFSSEF");
expect(user.room.id, "!localpart:server.abc"); expect(user.room.id, "!localpart:server.abc");
}); });

View file

@ -21,15 +21,15 @@
* along with famedlysdk. If not, see <http://www.gnu.org/licenses/>. * along with famedlysdk. If not, see <http://www.gnu.org/licenses/>.
*/ */
import 'package:flutter_test/flutter_test.dart';
import 'package:famedlysdk/src/User.dart'; import 'package:famedlysdk/src/User.dart';
import 'package:flutter_test/flutter_test.dart';
void main() { void main() {
/// All Tests related to the Event /// All Tests related to the Event
group("User", () { group("User", () {
test("Create from json", () async { test("Create from json", () async {
final String id = "@alice:server.abc"; final String id = "@alice:server.abc";
final String membership = "join"; final Membership membership = Membership.join;
final String displayName = "Alice"; final String displayName = "Alice";
final String avatarUrl = ""; final String avatarUrl = "";
final int powerLevel = 50; final int powerLevel = 50;
@ -38,7 +38,7 @@ void main() {
"matrix_id": id, "matrix_id": id,
"displayname": displayName, "displayname": displayName,
"avatar_url": avatarUrl, "avatar_url": avatarUrl,
"membership": membership, "membership": membership.toString().split('.').last,
"power_level": powerLevel, "power_level": powerLevel,
}; };