Krille/make client extend matrixapi
This commit is contained in:
parent
574fe27101
commit
fb9b505988
|
@ -167,7 +167,7 @@ class CrossSigning {
|
|||
}
|
||||
if (signedKeys.isNotEmpty) {
|
||||
// post our new keys!
|
||||
await client.api.uploadKeySignatures(signedKeys);
|
||||
await client.uploadKeySignatures(signedKeys);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ class KeyManager {
|
|||
encryption.ssss.setValidator(MEGOLM_KEY, (String secret) async {
|
||||
final keyObj = olm.PkDecryption();
|
||||
try {
|
||||
final info = await client.api.getRoomKeysBackup();
|
||||
final info = await client.getRoomKeysBackup();
|
||||
if (info.algorithm != RoomKeysAlgorithmType.v1Curve25519AesSha2) {
|
||||
return false;
|
||||
}
|
||||
|
@ -288,7 +288,7 @@ class KeyManager {
|
|||
key: client.userID,
|
||||
);
|
||||
try {
|
||||
await client.sendToDevice(deviceKeys, 'm.room_key', rawSession);
|
||||
await client.sendToDeviceEncrypted(deviceKeys, 'm.room_key', rawSession);
|
||||
await storeOutboundGroupSession(roomId, sess);
|
||||
_outboundGroupSessions[roomId] = sess;
|
||||
} catch (e, s) {
|
||||
|
@ -339,7 +339,7 @@ class KeyManager {
|
|||
final privateKey =
|
||||
base64.decode(await encryption.ssss.getCached(MEGOLM_KEY));
|
||||
final decryption = olm.PkDecryption();
|
||||
final info = await client.api.getRoomKeysBackup();
|
||||
final info = await client.getRoomKeysBackup();
|
||||
String backupPubKey;
|
||||
try {
|
||||
backupPubKey = decryption.init_with_private_key(privateKey);
|
||||
|
@ -387,9 +387,9 @@ class KeyManager {
|
|||
}
|
||||
|
||||
Future<void> loadSingleKey(String roomId, String sessionId) async {
|
||||
final info = await client.api.getRoomKeysBackup();
|
||||
final info = await client.getRoomKeysBackup();
|
||||
final ret =
|
||||
await client.api.getRoomKeysSingleKey(roomId, sessionId, info.version);
|
||||
await client.getRoomKeysSingleKey(roomId, sessionId, info.version);
|
||||
final keys = RoomKeys.fromJson({
|
||||
'rooms': {
|
||||
roomId: {
|
||||
|
@ -434,22 +434,22 @@ class KeyManager {
|
|||
sessionId: sessionId,
|
||||
senderKey: senderKey,
|
||||
);
|
||||
await client.sendToDevice(
|
||||
[],
|
||||
'm.room_key_request',
|
||||
{
|
||||
'action': 'request',
|
||||
'body': {
|
||||
'algorithm': 'm.megolm.v1.aes-sha2',
|
||||
'room_id': room.id,
|
||||
'sender_key': senderKey,
|
||||
'session_id': sessionId,
|
||||
},
|
||||
'request_id': requestId,
|
||||
'requesting_device_id': client.deviceID,
|
||||
final userList = await room.requestParticipants();
|
||||
await client.sendToDevicesOfUserIds(
|
||||
userList.map<String>((u) => u.id).toSet(),
|
||||
'm.room_key_request',
|
||||
{
|
||||
'action': 'request',
|
||||
'body': {
|
||||
'algorithm': 'm.megolm.v1.aes-sha2',
|
||||
'room_id': room.id,
|
||||
'sender_key': senderKey,
|
||||
'session_id': sessionId,
|
||||
},
|
||||
encrypted: false,
|
||||
toUsers: await room.requestParticipants());
|
||||
'request_id': requestId,
|
||||
'requesting_device_id': client.deviceID,
|
||||
},
|
||||
);
|
||||
outgoingShareRequests[request.requestId] = request;
|
||||
} catch (e, s) {
|
||||
Logs.error(
|
||||
|
@ -568,15 +568,24 @@ class KeyManager {
|
|||
if (request.devices.isEmpty) {
|
||||
return; // no need to send any cancellation
|
||||
}
|
||||
// Send with send-to-device messaging
|
||||
final sendToDeviceMessage = {
|
||||
'action': 'request_cancellation',
|
||||
'request_id': request.requestId,
|
||||
'requesting_device_id': client.deviceID,
|
||||
};
|
||||
var data = <String, Map<String, Map<String, dynamic>>>{};
|
||||
for (final device in request.devices) {
|
||||
if (!data.containsKey(device.userId)) {
|
||||
data[device.userId] = {};
|
||||
}
|
||||
data[device.userId][device.deviceId] = sendToDeviceMessage;
|
||||
}
|
||||
await client.sendToDevice(
|
||||
request.devices,
|
||||
'm.room_key_request',
|
||||
{
|
||||
'action': 'request_cancellation',
|
||||
'request_id': request.requestId,
|
||||
'requesting_device_id': client.deviceID,
|
||||
},
|
||||
encrypted: false);
|
||||
'm.room_key_request',
|
||||
client.generateUniqueTransactionId(),
|
||||
data,
|
||||
);
|
||||
} else if (event.type == 'm.room_key') {
|
||||
if (event.encryptedContent == null) {
|
||||
return; // the event wasn't encrypted, this is a security risk;
|
||||
|
@ -675,7 +684,7 @@ class RoomKeyRequest extends ToDeviceEvent {
|
|||
message['session_key'] = session.inboundGroupSession
|
||||
.export_session(session.inboundGroupSession.first_known_index());
|
||||
// send the actual reply of the key back to the requester
|
||||
await keyManager.client.sendToDevice(
|
||||
await keyManager.client.sendToDeviceEncrypted(
|
||||
[requestingDevice],
|
||||
'm.forwarded_room_key',
|
||||
message,
|
||||
|
|
|
@ -183,7 +183,7 @@ class OlmManager {
|
|||
signJson(keysContent['device_keys'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
final response = await client.api.uploadDeviceKeys(
|
||||
final response = await client.uploadDeviceKeys(
|
||||
deviceKeys: uploadDeviceKeys
|
||||
? MatrixDeviceKeys.fromJson(keysContent['device_keys'])
|
||||
: null,
|
||||
|
@ -335,7 +335,7 @@ class OlmManager {
|
|||
return;
|
||||
}
|
||||
await startOutgoingOlmSessions([device]);
|
||||
await client.sendToDevice([device], 'm.dummy', {});
|
||||
await client.sendToDeviceEncrypted([device], 'm.dummy', {});
|
||||
}
|
||||
|
||||
Future<ToDeviceEvent> decryptToDeviceEvent(ToDeviceEvent event) async {
|
||||
|
@ -383,7 +383,7 @@ class OlmManager {
|
|||
}
|
||||
|
||||
final response =
|
||||
await client.api.requestOneTimeKeys(requestingKeysFrom, timeout: 10000);
|
||||
await client.requestOneTimeKeys(requestingKeysFrom, timeout: 10000);
|
||||
|
||||
for (var userKeysEntry in response.oneTimeKeys.entries) {
|
||||
final userId = userKeysEntry.key;
|
||||
|
|
|
@ -222,7 +222,7 @@ class SSSS {
|
|||
'mac': encrypted.mac,
|
||||
};
|
||||
// store the thing in your account data
|
||||
await client.api.setAccountData(client.userID, type, content);
|
||||
await client.setAccountData(client.userID, type, content);
|
||||
if (CACHE_TYPES.contains(type) && client.database != null) {
|
||||
// cache the thing
|
||||
await client.database
|
||||
|
@ -271,7 +271,7 @@ class SSSS {
|
|||
devices: devices,
|
||||
);
|
||||
pendingShareRequests[requestId] = request;
|
||||
await client.sendToDevice(devices, 'm.secret.request', {
|
||||
await client.sendToDeviceEncrypted(devices, 'm.secret.request', {
|
||||
'action': 'request',
|
||||
'requesting_device_id': client.deviceID,
|
||||
'request_id': requestId,
|
||||
|
@ -308,7 +308,7 @@ class SSSS {
|
|||
}
|
||||
// okay, all checks out...time to share this secret!
|
||||
Logs.info('[SSSS] Replying with secret for ${type}');
|
||||
await client.sendToDevice(
|
||||
await client.sendToDeviceEncrypted(
|
||||
[device],
|
||||
'm.secret.send',
|
||||
{
|
||||
|
|
|
@ -571,7 +571,7 @@ class KeyVerification {
|
|||
} else {
|
||||
Logs.info(
|
||||
'[Key Verification] Sending to ${userId} device ${deviceId}...');
|
||||
await client.sendToDevice(
|
||||
await client.sendToDeviceEncrypted(
|
||||
[client.userDeviceKeys[userId].deviceKeys[deviceId]], type, payload);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1329,8 +1329,11 @@ class MatrixApi {
|
|||
|
||||
/// This endpoint is used to send send-to-device events to a set of client devices.
|
||||
/// https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-sendtodevice-eventtype-txnid
|
||||
Future<void> sendToDevice(String eventType, String txnId,
|
||||
Map<String, Map<String, Map<String, dynamic>>> messages) async {
|
||||
Future<void> sendToDevice(
|
||||
String eventType,
|
||||
String txnId,
|
||||
Map<String, Map<String, Map<String, dynamic>>> messages,
|
||||
) async {
|
||||
await request(
|
||||
RequestType.PUT,
|
||||
'/client/r0/sendToDevice/${Uri.encodeComponent(eventType)}/${Uri.encodeComponent(txnId)}',
|
||||
|
|
|
@ -22,7 +22,6 @@ import 'dart:core';
|
|||
|
||||
import 'package:famedlysdk/encryption.dart';
|
||||
import 'package:famedlysdk/famedlysdk.dart';
|
||||
import 'package:famedlysdk/matrix_api.dart';
|
||||
import 'package:famedlysdk/src/room.dart';
|
||||
import 'package:famedlysdk/src/utils/device_keys_list.dart';
|
||||
import 'package:famedlysdk/src/utils/logs.dart';
|
||||
|
@ -45,7 +44,7 @@ enum LoginState { logged, loggedOut }
|
|||
/// Represents a Matrix client to communicate with a
|
||||
/// [Matrix](https://matrix.org) homeserver and is the entry point for this
|
||||
/// SDK.
|
||||
class Client {
|
||||
class Client extends MatrixApi {
|
||||
int _id;
|
||||
int get id => _id;
|
||||
|
||||
|
@ -53,7 +52,8 @@ class Client {
|
|||
|
||||
bool enableE2eeRecovery;
|
||||
|
||||
MatrixApi api;
|
||||
@deprecated
|
||||
MatrixApi get api => this;
|
||||
|
||||
Encryption encryption;
|
||||
|
||||
|
@ -103,7 +103,7 @@ class Client {
|
|||
EventTypes.RoomCanonicalAlias,
|
||||
EventTypes.RoomTombstone,
|
||||
]);
|
||||
api = MatrixApi(httpClient: httpClient);
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
/// The required name for this client.
|
||||
|
@ -125,7 +125,7 @@ class Client {
|
|||
String _deviceName;
|
||||
|
||||
/// Returns the current login state.
|
||||
bool isLogged() => api.accessToken != null;
|
||||
bool isLogged() => accessToken != null;
|
||||
|
||||
/// A list of all rooms the user is participating or invited.
|
||||
List<Room> get rooms => _rooms;
|
||||
|
@ -160,21 +160,6 @@ class Client {
|
|||
|
||||
int _transactionCounter = 0;
|
||||
|
||||
@Deprecated('Use [api.request()] instead')
|
||||
Future<Map<String, dynamic>> jsonRequest(
|
||||
{RequestType type,
|
||||
String action,
|
||||
dynamic data = '',
|
||||
int timeout,
|
||||
String contentType = 'application/json'}) =>
|
||||
api.request(
|
||||
type,
|
||||
action,
|
||||
data: data,
|
||||
timeout: timeout,
|
||||
contentType: contentType,
|
||||
);
|
||||
|
||||
String generateUniqueTransactionId() {
|
||||
_transactionCounter++;
|
||||
return '${clientName}-${_transactionCounter}-${DateTime.now().millisecondsSinceEpoch}';
|
||||
|
@ -243,7 +228,7 @@ class Client {
|
|||
Future<bool> checkServer(dynamic serverUrl) async {
|
||||
try {
|
||||
if (serverUrl is Uri) {
|
||||
api.homeserver = serverUrl;
|
||||
homeserver = serverUrl;
|
||||
} else {
|
||||
// URLs allow to have whitespace surrounding them, see https://www.w3.org/TR/2011/WD-html5-20110525/urls.html
|
||||
// As we want to strip a trailing slash, though, we have to trim the url ourself
|
||||
|
@ -253,9 +238,9 @@ class Client {
|
|||
if (serverUrl.endsWith('/')) {
|
||||
serverUrl = serverUrl.substring(0, serverUrl.length - 1);
|
||||
}
|
||||
api.homeserver = Uri.parse(serverUrl);
|
||||
homeserver = Uri.parse(serverUrl);
|
||||
}
|
||||
final versions = await api.requestSupportedVersions();
|
||||
final versions = await requestSupportedVersions();
|
||||
|
||||
for (var i = 0; i < versions.versions.length; i++) {
|
||||
if (versions.versions[i] == 'r0.5.0' ||
|
||||
|
@ -266,7 +251,7 @@ class Client {
|
|||
}
|
||||
}
|
||||
|
||||
final loginTypes = await api.requestLoginTypes();
|
||||
final loginTypes = await requestLoginTypes();
|
||||
if (loginTypes.flows.indexWhere((f) => f.type == 'm.login.password') ==
|
||||
-1) {
|
||||
return false;
|
||||
|
@ -274,7 +259,7 @@ class Client {
|
|||
|
||||
return true;
|
||||
} catch (_) {
|
||||
api.homeserver = null;
|
||||
homeserver = null;
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
@ -282,16 +267,17 @@ class Client {
|
|||
/// Checks to see if a username is available, and valid, for the server.
|
||||
/// Returns the fully-qualified Matrix user ID (MXID) that has been registered.
|
||||
/// You have to call [checkServer] first to set a homeserver.
|
||||
Future<void> register({
|
||||
String kind,
|
||||
@override
|
||||
Future<LoginResponse> register({
|
||||
String username,
|
||||
String password,
|
||||
Map<String, dynamic> auth,
|
||||
String deviceId,
|
||||
String initialDeviceDisplayName,
|
||||
bool inhibitLogin,
|
||||
Map<String, dynamic> auth,
|
||||
String kind,
|
||||
}) async {
|
||||
final response = await api.register(
|
||||
final response = await super.register(
|
||||
username: username,
|
||||
password: password,
|
||||
auth: auth,
|
||||
|
@ -309,66 +295,62 @@ class Client {
|
|||
await connect(
|
||||
newToken: response.accessToken,
|
||||
newUserID: response.userId,
|
||||
newHomeserver: api.homeserver,
|
||||
newHomeserver: homeserver,
|
||||
newDeviceName: initialDeviceDisplayName ?? '',
|
||||
newDeviceID: response.deviceId);
|
||||
return;
|
||||
return response;
|
||||
}
|
||||
|
||||
/// Handles the login and allows the client to call all APIs which require
|
||||
/// authentication. Returns false if the login was not successful. Throws
|
||||
/// MatrixException if login was not successful.
|
||||
/// You have to call [checkServer] first to set a homeserver.
|
||||
Future<bool> login(
|
||||
String username,
|
||||
String password, {
|
||||
String initialDeviceDisplayName,
|
||||
@override
|
||||
Future<LoginResponse> login({
|
||||
String type = 'm.login.password',
|
||||
String userIdentifierType = 'm.id.user',
|
||||
String user,
|
||||
String medium,
|
||||
String address,
|
||||
String password,
|
||||
String token,
|
||||
String deviceId,
|
||||
String initialDeviceDisplayName,
|
||||
}) async {
|
||||
var data = <String, dynamic>{
|
||||
'type': 'm.login.password',
|
||||
'user': username,
|
||||
'identifier': {
|
||||
'type': 'm.id.user',
|
||||
'user': username,
|
||||
},
|
||||
'password': password,
|
||||
};
|
||||
if (deviceId != null) data['device_id'] = deviceId;
|
||||
if (initialDeviceDisplayName != null) {
|
||||
data['initial_device_display_name'] = initialDeviceDisplayName;
|
||||
}
|
||||
|
||||
final loginResp = await api.login(
|
||||
type: 'm.login.password',
|
||||
userIdentifierType: 'm.id.user',
|
||||
user: username,
|
||||
final loginResp = await super.login(
|
||||
type: type,
|
||||
userIdentifierType: userIdentifierType,
|
||||
user: user,
|
||||
password: password,
|
||||
deviceId: deviceId,
|
||||
initialDeviceDisplayName: initialDeviceDisplayName,
|
||||
medium: medium,
|
||||
address: address,
|
||||
token: token,
|
||||
);
|
||||
|
||||
// Connect if there is an access token in the response.
|
||||
if (loginResp.accessToken == null ||
|
||||
loginResp.deviceId == null ||
|
||||
loginResp.userId == null) {
|
||||
throw 'Registered but token, device ID or user ID is null.';
|
||||
throw Exception('Registered but token, device ID or user ID is null.');
|
||||
}
|
||||
await connect(
|
||||
newToken: loginResp.accessToken,
|
||||
newUserID: loginResp.userId,
|
||||
newHomeserver: api.homeserver,
|
||||
newHomeserver: homeserver,
|
||||
newDeviceName: initialDeviceDisplayName ?? '',
|
||||
newDeviceID: loginResp.deviceId,
|
||||
);
|
||||
return true;
|
||||
return loginResp;
|
||||
}
|
||||
|
||||
/// Sends a logout command to the homeserver and clears all local data,
|
||||
/// including all persistent data from the store.
|
||||
@override
|
||||
Future<void> logout() async {
|
||||
try {
|
||||
await api.logout();
|
||||
await super.logout();
|
||||
} catch (e, s) {
|
||||
Logs.error(e, s);
|
||||
rethrow;
|
||||
|
@ -421,19 +403,19 @@ class Client {
|
|||
if (cache && _profileCache.containsKey(userId)) {
|
||||
return _profileCache[userId];
|
||||
}
|
||||
final profile = await api.requestProfile(userId);
|
||||
final profile = await requestProfile(userId);
|
||||
_profileCache[userId] = profile;
|
||||
return profile;
|
||||
}
|
||||
|
||||
Future<List<Room>> get archive async {
|
||||
var archiveList = <Room>[];
|
||||
final sync = await api.sync(
|
||||
final syncResp = await sync(
|
||||
filter: '{"room":{"include_leave":true,"timeline":{"limit":10}}}',
|
||||
timeout: 0,
|
||||
);
|
||||
if (sync.rooms.leave is Map<String, dynamic>) {
|
||||
for (var entry in sync.rooms.leave.entries) {
|
||||
if (syncResp.rooms.leave is Map<String, dynamic>) {
|
||||
for (var entry in syncResp.rooms.leave.entries) {
|
||||
final id = entry.key;
|
||||
final room = entry.value;
|
||||
var leftRoom = Room(
|
||||
|
@ -460,14 +442,10 @@ class Client {
|
|||
return archiveList;
|
||||
}
|
||||
|
||||
/// Changes the user's displayname.
|
||||
Future<void> setDisplayname(String displayname) =>
|
||||
api.setDisplayname(userID, displayname);
|
||||
|
||||
/// Uploads a new user avatar for this user.
|
||||
Future<void> setAvatar(MatrixFile file) async {
|
||||
final uploadResp = await api.upload(file.bytes, file.name);
|
||||
await api.setAvatarUrl(userID, Uri.parse(uploadResp));
|
||||
final uploadResp = await upload(file.bytes, file.name);
|
||||
await setAvatarUrl(userID, Uri.parse(uploadResp));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -550,10 +528,6 @@ class Client {
|
|||
final StreamController<KeyVerification> onKeyVerificationRequest =
|
||||
StreamController.broadcast();
|
||||
|
||||
/// Matrix synchronisation is done with https long polling. This needs a
|
||||
/// timeout which is usually 30 seconds.
|
||||
int syncTimeoutSec = 30;
|
||||
|
||||
/// How long should the app wait until it retrys the synchronisation after
|
||||
/// an error?
|
||||
int syncErrorTimeoutSec = 3;
|
||||
|
@ -575,7 +549,7 @@ class Client {
|
|||
/// "type": "m.login.password",
|
||||
/// "user": "test",
|
||||
/// "password": "1234",
|
||||
/// "initial_device_display_name": "Fluffy Matrix Client"
|
||||
/// "initial_device_display_name": "Matrix Client"
|
||||
/// });
|
||||
/// ```
|
||||
///
|
||||
|
@ -604,8 +578,8 @@ class Client {
|
|||
final account = await database.getClient(clientName);
|
||||
if (account != null) {
|
||||
_id = account.clientId;
|
||||
api.homeserver = Uri.parse(account.homeserverUrl);
|
||||
api.accessToken = account.token;
|
||||
homeserver = Uri.parse(account.homeserverUrl);
|
||||
accessToken = account.token;
|
||||
_userID = account.userId;
|
||||
_deviceID = account.deviceId;
|
||||
_deviceName = account.deviceName;
|
||||
|
@ -613,15 +587,15 @@ class Client {
|
|||
olmAccount = account.olmAccount;
|
||||
}
|
||||
}
|
||||
api.accessToken = newToken ?? api.accessToken;
|
||||
api.homeserver = newHomeserver ?? api.homeserver;
|
||||
accessToken = newToken ?? accessToken;
|
||||
homeserver = newHomeserver ?? homeserver;
|
||||
_userID = newUserID ?? _userID;
|
||||
_deviceID = newDeviceID ?? _deviceID;
|
||||
_deviceName = newDeviceName ?? _deviceName;
|
||||
prevBatch = newPrevBatch ?? prevBatch;
|
||||
olmAccount = newOlmAccount ?? olmAccount;
|
||||
|
||||
if (api.accessToken == null || api.homeserver == null || _userID == null) {
|
||||
if (accessToken == null || homeserver == null || _userID == null) {
|
||||
// we aren't logged in
|
||||
encryption?.dispose();
|
||||
encryption = null;
|
||||
|
@ -636,8 +610,8 @@ class Client {
|
|||
if (database != null) {
|
||||
if (id != null) {
|
||||
await database.updateClient(
|
||||
api.homeserver.toString(),
|
||||
api.accessToken,
|
||||
homeserver.toString(),
|
||||
accessToken,
|
||||
_userID,
|
||||
_deviceID,
|
||||
_deviceName,
|
||||
|
@ -648,8 +622,8 @@ class Client {
|
|||
} else {
|
||||
_id = await database.insertClient(
|
||||
clientName,
|
||||
api.homeserver.toString(),
|
||||
api.accessToken,
|
||||
homeserver.toString(),
|
||||
accessToken,
|
||||
_userID,
|
||||
_deviceID,
|
||||
_deviceName,
|
||||
|
@ -666,7 +640,7 @@ class Client {
|
|||
|
||||
onLoginStateChanged.add(LoginState.logged);
|
||||
Logs.success(
|
||||
'Successfully connected as ${userID.localpart} with ${api.homeserver.toString()}',
|
||||
'Successfully connected as ${userID.localpart} with ${homeserver.toString()}',
|
||||
);
|
||||
|
||||
return _sync();
|
||||
|
@ -680,8 +654,8 @@ class Client {
|
|||
/// Resets all settings and stops the synchronisation.
|
||||
void clear() {
|
||||
database?.clear(id);
|
||||
_id = api.accessToken =
|
||||
api.homeserver = _userID = _deviceID = _deviceName = prevBatch = null;
|
||||
_id = accessToken =
|
||||
homeserver = _userID = _deviceID = _deviceName = prevBatch = null;
|
||||
_rooms = [];
|
||||
encryption?.dispose();
|
||||
encryption = null;
|
||||
|
@ -694,13 +668,11 @@ class Client {
|
|||
Future<void> _sync() async {
|
||||
if (isLogged() == false || _disposed) return;
|
||||
try {
|
||||
_syncRequest = api
|
||||
.sync(
|
||||
_syncRequest = sync(
|
||||
filter: syncFilters,
|
||||
since: prevBatch,
|
||||
timeout: prevBatch != null ? 30000 : null,
|
||||
)
|
||||
.catchError((e) {
|
||||
).catchError((e) {
|
||||
_lastSyncError = e;
|
||||
return null;
|
||||
});
|
||||
|
@ -1197,8 +1169,7 @@ class Client {
|
|||
|
||||
if (outdatedLists.isNotEmpty) {
|
||||
// Request the missing device key lists from the server.
|
||||
final response =
|
||||
await api.requestDeviceKeys(outdatedLists, timeout: 10000);
|
||||
final response = await requestDeviceKeys(outdatedLists, timeout: 10000);
|
||||
|
||||
for (final rawDeviceKeyListEntry in response.deviceKeys.entries) {
|
||||
final userId = rawDeviceKeyListEntry.key;
|
||||
|
@ -1347,17 +1318,35 @@ class Client {
|
|||
}
|
||||
}
|
||||
|
||||
/// Send an (unencrypted) to device [message] of a specific [eventType] to all
|
||||
/// devices of a set of [users].
|
||||
Future<void> sendToDevicesOfUserIds(
|
||||
Set<String> users,
|
||||
String eventType,
|
||||
Map<String, dynamic> message, {
|
||||
String messageId,
|
||||
}) async {
|
||||
// Send with send-to-device messaging
|
||||
var data = <String, Map<String, Map<String, dynamic>>>{};
|
||||
for (var user in users) {
|
||||
data[user] = {};
|
||||
data[user]['*'] = message;
|
||||
}
|
||||
await sendToDevice(
|
||||
eventType, messageId ?? generateUniqueTransactionId(), data);
|
||||
return;
|
||||
}
|
||||
|
||||
/// Sends an encrypted [message] of this [type] to these [deviceKeys]. To send
|
||||
/// the request to all devices of the current user, pass an empty list to [deviceKeys].
|
||||
Future<void> sendToDevice(
|
||||
Future<void> sendToDeviceEncrypted(
|
||||
List<DeviceKeys> deviceKeys,
|
||||
String type,
|
||||
String eventType,
|
||||
Map<String, dynamic> message, {
|
||||
bool encrypted = true,
|
||||
List<User> toUsers,
|
||||
String messageId,
|
||||
bool onlyVerified = false,
|
||||
}) async {
|
||||
if (encrypted && !encryptionEnabled) return;
|
||||
if (!encryptionEnabled) return;
|
||||
// Don't send this message to blocked devices, and if specified onlyVerified
|
||||
// then only send it to verified devices
|
||||
if (deviceKeys.isNotEmpty) {
|
||||
|
@ -1368,36 +1357,13 @@ class Client {
|
|||
if (deviceKeys.isEmpty) return;
|
||||
}
|
||||
|
||||
var sendToDeviceMessage = message;
|
||||
|
||||
// Send with send-to-device messaging
|
||||
var data = <String, Map<String, Map<String, dynamic>>>{};
|
||||
if (deviceKeys.isEmpty) {
|
||||
if (toUsers == null) {
|
||||
data[userID] = {};
|
||||
data[userID]['*'] = sendToDeviceMessage;
|
||||
} else {
|
||||
for (var user in toUsers) {
|
||||
data[user.id] = {};
|
||||
data[user.id]['*'] = sendToDeviceMessage;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (encrypted) {
|
||||
data =
|
||||
await encryption.encryptToDeviceMessage(deviceKeys, type, message);
|
||||
} else {
|
||||
for (final device in deviceKeys) {
|
||||
if (!data.containsKey(device.userId)) {
|
||||
data[device.userId] = {};
|
||||
}
|
||||
data[device.userId][device.deviceId] = sendToDeviceMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (encrypted) type = EventTypes.Encrypted;
|
||||
final messageID = generateUniqueTransactionId();
|
||||
await api.sendToDevice(type, messageID, data);
|
||||
data =
|
||||
await encryption.encryptToDeviceMessage(deviceKeys, eventType, message);
|
||||
eventType = EventTypes.Encrypted;
|
||||
await sendToDevice(
|
||||
eventType, messageId ?? generateUniqueTransactionId(), data);
|
||||
}
|
||||
|
||||
/// Whether all push notifications are muted using the [.m.rule.master]
|
||||
|
@ -1422,7 +1388,7 @@ class Client {
|
|||
}
|
||||
|
||||
Future<void> setMuteAllPushNotifications(bool muted) async {
|
||||
await api.enablePushRule(
|
||||
await enablePushRule(
|
||||
'global',
|
||||
PushRuleKind.override,
|
||||
'.m.rule.master',
|
||||
|
@ -1432,6 +1398,7 @@ class Client {
|
|||
}
|
||||
|
||||
/// Changes the password. You should either set oldPasswort or another authentication flow.
|
||||
@override
|
||||
Future<void> changePassword(String newPassword,
|
||||
{String oldPassword, Map<String, dynamic> auth}) async {
|
||||
try {
|
||||
|
@ -1442,7 +1409,7 @@ class Client {
|
|||
'password': oldPassword,
|
||||
};
|
||||
}
|
||||
await api.changePassword(newPassword, auth: auth);
|
||||
await super.changePassword(newPassword, auth: auth);
|
||||
} on MatrixException catch (matrixException) {
|
||||
if (!matrixException.requireAdditionalAuthentication) {
|
||||
rethrow;
|
||||
|
|
|
@ -374,21 +374,21 @@ class Room {
|
|||
|
||||
/// Call the Matrix API to change the name of this room. Returns the event ID of the
|
||||
/// new m.room.name event.
|
||||
Future<String> setName(String newName) => client.api.sendState(
|
||||
Future<String> setName(String newName) => client.sendState(
|
||||
id,
|
||||
EventTypes.RoomName,
|
||||
{'name': newName},
|
||||
);
|
||||
|
||||
/// Call the Matrix API to change the topic of this room.
|
||||
Future<String> setDescription(String newName) => client.api.sendState(
|
||||
Future<String> setDescription(String newName) => client.sendState(
|
||||
id,
|
||||
EventTypes.RoomTopic,
|
||||
{'topic': newName},
|
||||
);
|
||||
|
||||
/// Add a tag to the room.
|
||||
Future<void> addTag(String tag, {double order}) => client.api.addRoomTag(
|
||||
Future<void> addTag(String tag, {double order}) => client.addRoomTag(
|
||||
client.userID,
|
||||
id,
|
||||
tag,
|
||||
|
@ -396,7 +396,7 @@ class Room {
|
|||
);
|
||||
|
||||
/// Removes a tag from the room.
|
||||
Future<void> removeTag(String tag) => client.api.removeRoomTag(
|
||||
Future<void> removeTag(String tag) => client.removeRoomTag(
|
||||
client.userID,
|
||||
id,
|
||||
tag,
|
||||
|
@ -423,7 +423,7 @@ class Room {
|
|||
|
||||
/// Call the Matrix API to change the pinned events of this room.
|
||||
Future<String> setPinnedEvents(List<String> pinnedEventIds) =>
|
||||
client.api.sendState(
|
||||
client.sendState(
|
||||
id,
|
||||
EventTypes.RoomPinnedEvents,
|
||||
{'pinned': pinnedEventIds},
|
||||
|
@ -565,13 +565,13 @@ class Room {
|
|||
uploadThumbnail = encryptedThumbnail.toMatrixFile();
|
||||
}
|
||||
}
|
||||
final uploadResp = await client.api.upload(
|
||||
final uploadResp = await client.upload(
|
||||
uploadFile.bytes,
|
||||
uploadFile.name,
|
||||
contentType: uploadFile.mimeType,
|
||||
);
|
||||
final thumbnailUploadResp = uploadThumbnail != null
|
||||
? await client.api.upload(
|
||||
? await client.upload(
|
||||
uploadThumbnail.bytes,
|
||||
uploadThumbnail.name,
|
||||
contentType: uploadThumbnail.mimeType,
|
||||
|
@ -705,7 +705,7 @@ class Room {
|
|||
? await client.encryption
|
||||
.encryptGroupMessagePayload(id, content, type: type)
|
||||
: content;
|
||||
final res = await client.api.sendMessage(
|
||||
final res = await client.sendMessage(
|
||||
id,
|
||||
sendType,
|
||||
messageID,
|
||||
|
@ -731,7 +731,7 @@ class Room {
|
|||
/// automatically be set.
|
||||
Future<void> join() async {
|
||||
try {
|
||||
await client.api.joinRoom(id);
|
||||
await client.joinRoom(id);
|
||||
final invitation = getState(EventTypes.RoomMember, client.userID);
|
||||
if (invitation != null &&
|
||||
invitation.content['is_direct'] is bool &&
|
||||
|
@ -757,25 +757,25 @@ class Room {
|
|||
/// chat, this will be removed too.
|
||||
Future<void> leave() async {
|
||||
if (directChatMatrixID != '') await removeFromDirectChat();
|
||||
await client.api.leaveRoom(id);
|
||||
await client.leaveRoom(id);
|
||||
return;
|
||||
}
|
||||
|
||||
/// Call the Matrix API to forget this room if you already left it.
|
||||
Future<void> forget() async {
|
||||
await client.database?.forgetRoom(client.id, id);
|
||||
await client.api.forgetRoom(id);
|
||||
await client.forgetRoom(id);
|
||||
return;
|
||||
}
|
||||
|
||||
/// Call the Matrix API to kick a user from this room.
|
||||
Future<void> kick(String userID) => client.api.kickFromRoom(id, userID);
|
||||
Future<void> kick(String userID) => client.kickFromRoom(id, userID);
|
||||
|
||||
/// Call the Matrix API to ban a user from this room.
|
||||
Future<void> ban(String userID) => client.api.banFromRoom(id, userID);
|
||||
Future<void> ban(String userID) => client.banFromRoom(id, userID);
|
||||
|
||||
/// Call the Matrix API to unban a banned user from this room.
|
||||
Future<void> unban(String userID) => client.api.unbanInRoom(id, userID);
|
||||
Future<void> unban(String userID) => client.unbanInRoom(id, userID);
|
||||
|
||||
/// Set the power level of the user with the [userID] to the value [power].
|
||||
/// Returns the event ID of the new state event. If there is no known
|
||||
|
@ -787,7 +787,7 @@ class Room {
|
|||
if (powerMap['users'] == null) powerMap['users'] = {};
|
||||
powerMap['users'][userID] = power;
|
||||
|
||||
return await client.api.sendState(
|
||||
return await client.sendState(
|
||||
id,
|
||||
EventTypes.RoomPowerLevels,
|
||||
powerMap,
|
||||
|
@ -795,14 +795,14 @@ class Room {
|
|||
}
|
||||
|
||||
/// Call the Matrix API to invite a user to this room.
|
||||
Future<void> invite(String userID) => client.api.inviteToRoom(id, userID);
|
||||
Future<void> invite(String userID) => client.inviteToRoom(id, userID);
|
||||
|
||||
/// Request more previous events from the server. [historyCount] defines how much events should
|
||||
/// be received maximum. When the request is answered, [onHistoryReceived] will be triggered **before**
|
||||
/// the historical events will be published in the onEvent stream.
|
||||
Future<void> requestHistory(
|
||||
{int historyCount = DefaultHistoryCount, onHistoryReceived}) async {
|
||||
final resp = await client.api.requestMessages(
|
||||
final resp = await client.requestMessages(
|
||||
id,
|
||||
prev_batch,
|
||||
Direction.b,
|
||||
|
@ -853,7 +853,7 @@ class Room {
|
|||
directChats[userID] = [id];
|
||||
}
|
||||
|
||||
await client.api.setAccountData(
|
||||
await client.setAccountData(
|
||||
client.userID,
|
||||
'm.direct',
|
||||
directChats,
|
||||
|
@ -871,7 +871,7 @@ class Room {
|
|||
return;
|
||||
} // Nothing to do here
|
||||
|
||||
await client.api.setRoomAccountData(
|
||||
await client.setRoomAccountData(
|
||||
client.userID,
|
||||
id,
|
||||
'm.direct',
|
||||
|
@ -884,7 +884,7 @@ class Room {
|
|||
Future<void> sendReadReceipt(String eventID) async {
|
||||
notificationCount = 0;
|
||||
await client.database?.resetNotificationCount(client.id, id);
|
||||
await client.api.sendReadMarker(
|
||||
await client.sendReadMarker(
|
||||
id,
|
||||
eventID,
|
||||
readReceiptLocationEventId: eventID,
|
||||
|
@ -1017,7 +1017,7 @@ class Room {
|
|||
}
|
||||
}
|
||||
if (participantListComplete) return getParticipants();
|
||||
final matrixEvents = await client.api.requestMembers(id);
|
||||
final matrixEvents = await client.requestMembers(id);
|
||||
final users =
|
||||
matrixEvents.map((e) => Event.fromMatrixEvent(e, this).asUser).toList();
|
||||
for (final user in users) {
|
||||
|
@ -1080,7 +1080,7 @@ class Room {
|
|||
if (mxID == null || !_requestingMatrixIds.add(mxID)) return null;
|
||||
Map<String, dynamic> resp;
|
||||
try {
|
||||
resp = await client.api.requestStateContent(
|
||||
resp = await client.requestStateContent(
|
||||
id,
|
||||
EventTypes.RoomMember,
|
||||
mxID,
|
||||
|
@ -1093,7 +1093,7 @@ class Room {
|
|||
}
|
||||
if (resp == null && requestProfile) {
|
||||
try {
|
||||
final profile = await client.api.requestProfile(mxID);
|
||||
final profile = await client.requestProfile(mxID);
|
||||
resp = {
|
||||
'displayname': profile.displayname,
|
||||
'avatar_url': profile.avatarUrl,
|
||||
|
@ -1135,7 +1135,7 @@ class Room {
|
|||
|
||||
/// Searches for the event on the server. Returns null if not found.
|
||||
Future<Event> getEventById(String eventID) async {
|
||||
final matrixEvent = await client.api.requestEvent(id, eventID);
|
||||
final matrixEvent = await client.requestEvent(id, eventID);
|
||||
return Event.fromMatrixEvent(matrixEvent, this);
|
||||
}
|
||||
|
||||
|
@ -1169,8 +1169,8 @@ class Room {
|
|||
/// Uploads a new user avatar for this room. Returns the event ID of the new
|
||||
/// m.room.avatar event.
|
||||
Future<String> setAvatar(MatrixFile file) async {
|
||||
final uploadResp = await client.api.upload(file.bytes, file.name);
|
||||
return await client.api.sendState(
|
||||
final uploadResp = await client.upload(file.bytes, file.name);
|
||||
return await client.sendState(
|
||||
id,
|
||||
EventTypes.RoomAvatar,
|
||||
{'url': uploadResp},
|
||||
|
@ -1267,23 +1267,23 @@ class Room {
|
|||
// All push notifications should be sent to the user
|
||||
case PushRuleState.notify:
|
||||
if (pushRuleState == PushRuleState.dont_notify) {
|
||||
await client.api.deletePushRule('global', PushRuleKind.override, id);
|
||||
await client.deletePushRule('global', PushRuleKind.override, id);
|
||||
} else if (pushRuleState == PushRuleState.mentions_only) {
|
||||
await client.api.deletePushRule('global', PushRuleKind.room, id);
|
||||
await client.deletePushRule('global', PushRuleKind.room, id);
|
||||
}
|
||||
break;
|
||||
// Only when someone mentions the user, a push notification should be sent
|
||||
case PushRuleState.mentions_only:
|
||||
if (pushRuleState == PushRuleState.dont_notify) {
|
||||
await client.api.deletePushRule('global', PushRuleKind.override, id);
|
||||
await client.api.setPushRule(
|
||||
await client.deletePushRule('global', PushRuleKind.override, id);
|
||||
await client.setPushRule(
|
||||
'global',
|
||||
PushRuleKind.room,
|
||||
id,
|
||||
[PushRuleAction.dont_notify],
|
||||
);
|
||||
} else if (pushRuleState == PushRuleState.notify) {
|
||||
await client.api.setPushRule(
|
||||
await client.setPushRule(
|
||||
'global',
|
||||
PushRuleKind.room,
|
||||
id,
|
||||
|
@ -1294,9 +1294,9 @@ class Room {
|
|||
// No push notification should be ever sent for this room.
|
||||
case PushRuleState.dont_notify:
|
||||
if (pushRuleState == PushRuleState.mentions_only) {
|
||||
await client.api.deletePushRule('global', PushRuleKind.room, id);
|
||||
await client.deletePushRule('global', PushRuleKind.room, id);
|
||||
}
|
||||
await client.api.setPushRule(
|
||||
await client.setPushRule(
|
||||
'global',
|
||||
PushRuleKind.override,
|
||||
id,
|
||||
|
@ -1322,7 +1322,7 @@ class Room {
|
|||
}
|
||||
var data = <String, dynamic>{};
|
||||
if (reason != null) data['reason'] = reason;
|
||||
return await client.api.redact(
|
||||
return await client.redact(
|
||||
id,
|
||||
eventId,
|
||||
messageID,
|
||||
|
@ -1335,7 +1335,7 @@ class Room {
|
|||
'typing': isTyping,
|
||||
};
|
||||
if (timeout != null) data['timeout'] = timeout;
|
||||
return client.api.sendTypingNotification(client.userID, id, isTyping);
|
||||
return client.sendTypingNotification(client.userID, id, isTyping);
|
||||
}
|
||||
|
||||
/// This is sent by the caller when they wish to establish a call.
|
||||
|
@ -1349,7 +1349,7 @@ class Room {
|
|||
{String type = 'offer', int version = 0, String txid}) async {
|
||||
txid ??= 'txid${DateTime.now().millisecondsSinceEpoch}';
|
||||
|
||||
return await client.api.sendMessage(
|
||||
return await client.sendMessage(
|
||||
id,
|
||||
EventTypes.CallInvite,
|
||||
txid,
|
||||
|
@ -1387,7 +1387,7 @@ class Room {
|
|||
String txid,
|
||||
}) async {
|
||||
txid ??= 'txid${DateTime.now().millisecondsSinceEpoch}';
|
||||
return await client.api.sendMessage(
|
||||
return await client.sendMessage(
|
||||
id,
|
||||
EventTypes.CallCandidates,
|
||||
txid,
|
||||
|
@ -1407,7 +1407,7 @@ class Room {
|
|||
Future<String> answerCall(String callId, String sdp,
|
||||
{String type = 'answer', int version = 0, String txid}) async {
|
||||
txid ??= 'txid${DateTime.now().millisecondsSinceEpoch}';
|
||||
return await client.api.sendMessage(
|
||||
return await client.sendMessage(
|
||||
id,
|
||||
EventTypes.CallAnswer,
|
||||
txid,
|
||||
|
@ -1425,7 +1425,7 @@ class Room {
|
|||
Future<String> hangupCall(String callId,
|
||||
{int version = 0, String txid}) async {
|
||||
txid ??= 'txid${DateTime.now().millisecondsSinceEpoch}';
|
||||
return await client.api.sendMessage(
|
||||
return await client.sendMessage(
|
||||
id,
|
||||
EventTypes.CallHangup,
|
||||
txid,
|
||||
|
@ -1461,7 +1461,7 @@ class Room {
|
|||
|
||||
/// Changes the join rules. You should check first if the user is able to change it.
|
||||
Future<void> setJoinRules(JoinRules joinRules) async {
|
||||
await client.api.sendState(
|
||||
await client.sendState(
|
||||
id,
|
||||
EventTypes.RoomJoinRules,
|
||||
{
|
||||
|
@ -1486,7 +1486,7 @@ class Room {
|
|||
|
||||
/// Changes the guest access. You should check first if the user is able to change it.
|
||||
Future<void> setGuestAccess(GuestAccess guestAccess) async {
|
||||
await client.api.sendState(
|
||||
await client.sendState(
|
||||
id,
|
||||
EventTypes.GuestAccess,
|
||||
{
|
||||
|
@ -1512,7 +1512,7 @@ class Room {
|
|||
|
||||
/// Changes the history visibility. You should check first if the user is able to change it.
|
||||
Future<void> setHistoryVisibility(HistoryVisibility historyVisibility) async {
|
||||
await client.api.sendState(
|
||||
await client.sendState(
|
||||
id,
|
||||
EventTypes.HistoryVisibility,
|
||||
{
|
||||
|
@ -1539,7 +1539,7 @@ class Room {
|
|||
Future<void> enableEncryption({int algorithmIndex = 0}) async {
|
||||
if (encrypted) throw ('Encryption is already enabled!');
|
||||
final algorithm = Client.supportedGroupEncryptionAlgorithms[algorithmIndex];
|
||||
await client.api.sendState(
|
||||
await client.sendState(
|
||||
id,
|
||||
EventTypes.Encryption,
|
||||
{
|
||||
|
|
|
@ -146,7 +146,7 @@ class User extends Event {
|
|||
if (roomID != null) return roomID;
|
||||
|
||||
// Start a new direct chat
|
||||
final newRoomID = await room.client.api.createRoom(
|
||||
final newRoomID = await room.client.createRoom(
|
||||
invite: [id],
|
||||
isDirect: true,
|
||||
preset: CreateRoomPreset.trusted_private_chat,
|
||||
|
|
|
@ -22,8 +22,8 @@ import 'dart:core';
|
|||
extension MxcUriExtension on Uri {
|
||||
/// Returns a download Link to this content.
|
||||
String getDownloadLink(Client matrix) => isScheme('mxc')
|
||||
? matrix.api.homeserver != null
|
||||
? '${matrix.api.homeserver.toString()}/_matrix/media/r0/download/$host$path'
|
||||
? matrix.homeserver != null
|
||||
? '${matrix.homeserver.toString()}/_matrix/media/r0/download/$host$path'
|
||||
: ''
|
||||
: toString();
|
||||
|
||||
|
@ -36,8 +36,8 @@ extension MxcUriExtension on Uri {
|
|||
final methodStr = method.toString().split('.').last;
|
||||
width = width.round();
|
||||
height = height.round();
|
||||
return matrix.api.homeserver != null
|
||||
? '${matrix.api.homeserver.toString()}/_matrix/media/r0/thumbnail/$host$path?width=$width&height=$height&method=$methodStr'
|
||||
return matrix.homeserver != null
|
||||
? '${matrix.homeserver.toString()}/_matrix/media/r0/thumbnail/$host$path?width=$width&height=$height&method=$methodStr'
|
||||
: '';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ void main() {
|
|||
const fingerprintKey = 'gjL//fyaFHADt9KBADGag8g7F8Up78B/K1zXeiEPLJo';
|
||||
|
||||
/// All Tests related to the Login
|
||||
group('FluffyMatrix', () {
|
||||
group('Client', () {
|
||||
/// Check if all Elements get created
|
||||
|
||||
matrix = Client('testclient', httpClient: FakeMatrixApi());
|
||||
|
@ -74,7 +74,7 @@ void main() {
|
|||
accountDataCounter++;
|
||||
});
|
||||
|
||||
expect(matrix.api.homeserver, null);
|
||||
expect(matrix.homeserver, null);
|
||||
|
||||
try {
|
||||
await matrix.checkServer('https://fakeserver.wrongaddress');
|
||||
|
@ -82,17 +82,9 @@ void main() {
|
|||
expect(exception != null, true);
|
||||
}
|
||||
await matrix.checkServer('https://fakeserver.notexisting');
|
||||
expect(
|
||||
matrix.api.homeserver.toString(), 'https://fakeserver.notexisting');
|
||||
expect(matrix.homeserver.toString(), 'https://fakeserver.notexisting');
|
||||
|
||||
final resp = await matrix.api.login(
|
||||
type: 'm.login.password',
|
||||
user: 'test',
|
||||
password: '1234',
|
||||
initialDeviceDisplayName: 'Fluffy Matrix Client',
|
||||
);
|
||||
|
||||
final available = await matrix.api.usernameAvailable('testuser');
|
||||
final available = await matrix.usernameAvailable('testuser');
|
||||
expect(available, true);
|
||||
|
||||
var loginStateFuture = matrix.onLoginStateChanged.stream.first;
|
||||
|
@ -100,21 +92,16 @@ void main() {
|
|||
var syncFuture = matrix.onSync.stream.first;
|
||||
|
||||
matrix.connect(
|
||||
newToken: resp.accessToken,
|
||||
newUserID: resp.userId,
|
||||
newHomeserver: matrix.api.homeserver,
|
||||
newToken: 'abcd',
|
||||
newUserID: '@test:fakeServer.notExisting',
|
||||
newHomeserver: matrix.homeserver,
|
||||
newDeviceName: 'Text Matrix Client',
|
||||
newDeviceID: resp.deviceId,
|
||||
newDeviceID: 'GHTYAJCE',
|
||||
newOlmAccount: pickledOlmAccount,
|
||||
);
|
||||
|
||||
await Future.delayed(Duration(milliseconds: 50));
|
||||
|
||||
expect(matrix.api.accessToken == resp.accessToken, true);
|
||||
expect(matrix.deviceName == 'Text Matrix Client', true);
|
||||
expect(matrix.deviceID == resp.deviceId, true);
|
||||
expect(matrix.userID == resp.userId, true);
|
||||
|
||||
var loginState = await loginStateFuture;
|
||||
var firstSync = await firstSyncFuture;
|
||||
var sync = await syncFuture;
|
||||
|
@ -208,14 +195,11 @@ void main() {
|
|||
});
|
||||
|
||||
test('Logout', () async {
|
||||
await matrix.api.logout();
|
||||
|
||||
var loginStateFuture = matrix.onLoginStateChanged.stream.first;
|
||||
await matrix.logout();
|
||||
|
||||
matrix.clear();
|
||||
|
||||
expect(matrix.api.accessToken == null, true);
|
||||
expect(matrix.api.homeserver == null, true);
|
||||
expect(matrix.accessToken == null, true);
|
||||
expect(matrix.homeserver == null, true);
|
||||
expect(matrix.userID == null, true);
|
||||
expect(matrix.deviceID == null, true);
|
||||
expect(matrix.deviceName == null, true);
|
||||
|
@ -330,10 +314,10 @@ void main() {
|
|||
final checkResp =
|
||||
await matrix.checkServer('https://fakeServer.notExisting');
|
||||
|
||||
final loginResp = await matrix.login('test', '1234');
|
||||
final loginResp = await matrix.login(user: 'test', password: '1234');
|
||||
|
||||
expect(checkResp, true);
|
||||
expect(loginResp, true);
|
||||
expect(loginResp != null, true);
|
||||
});
|
||||
|
||||
test('setAvatar', () async {
|
||||
|
@ -386,8 +370,8 @@ void main() {
|
|||
}
|
||||
}
|
||||
}, matrix);
|
||||
test('sendToDevice', () async {
|
||||
await matrix.sendToDevice(
|
||||
test('sendToDeviceEncrypted', () async {
|
||||
await matrix.sendToDeviceEncrypted(
|
||||
[deviceKeys],
|
||||
'm.message',
|
||||
{
|
||||
|
@ -420,9 +404,9 @@ void main() {
|
|||
await Future.delayed(Duration(milliseconds: 100));
|
||||
|
||||
expect(client2.isLogged(), true);
|
||||
expect(client2.api.accessToken, client1.api.accessToken);
|
||||
expect(client2.accessToken, client1.accessToken);
|
||||
expect(client2.userID, client1.userID);
|
||||
expect(client2.api.homeserver, client1.api.homeserver);
|
||||
expect(client2.homeserver, client1.homeserver);
|
||||
expect(client2.deviceID, client1.deviceID);
|
||||
expect(client2.deviceName, client1.deviceName);
|
||||
if (client2.encryptionEnabled) {
|
||||
|
|
|
@ -54,7 +54,7 @@ void main() {
|
|||
otherClient.connect(
|
||||
newToken: 'abc',
|
||||
newUserID: '@othertest:fakeServer.notExisting',
|
||||
newHomeserver: otherClient.api.homeserver,
|
||||
newHomeserver: otherClient.homeserver,
|
||||
newDeviceName: 'Text Matrix Client',
|
||||
newDeviceID: 'FOXDEVICE',
|
||||
newOlmAccount: otherPickledOlmAccount,
|
||||
|
|
|
@ -89,7 +89,7 @@ void main() {
|
|||
client2.connect(
|
||||
newToken: 'abc',
|
||||
newUserID: '@othertest:fakeServer.notExisting',
|
||||
newHomeserver: client2.api.homeserver,
|
||||
newHomeserver: client2.homeserver,
|
||||
newDeviceName: 'Text Matrix Client',
|
||||
newDeviceID: 'FOXDEVICE',
|
||||
newOlmAccount: otherPickledOlmAccount,
|
||||
|
|
|
@ -246,7 +246,7 @@ void main() {
|
|||
test('sendAgain', () async {
|
||||
var matrix = Client('testclient', httpClient: FakeMatrixApi());
|
||||
await matrix.checkServer('https://fakeServer.notExisting');
|
||||
await matrix.login('test', '1234');
|
||||
await matrix.login(user: 'test', password: '1234');
|
||||
|
||||
var event = Event.fromJson(
|
||||
jsonObj, Room(id: '!1234:example.com', client: matrix));
|
||||
|
@ -262,7 +262,7 @@ void main() {
|
|||
test('requestKey', () async {
|
||||
var matrix = Client('testclient', httpClient: FakeMatrixApi());
|
||||
await matrix.checkServer('https://fakeServer.notExisting');
|
||||
await matrix.login('test', '1234');
|
||||
await matrix.login(user: 'test', password: '1234');
|
||||
|
||||
var event = Event.fromJson(
|
||||
jsonObj, Room(id: '!1234:example.com', client: matrix));
|
||||
|
|
|
@ -32,18 +32,12 @@ Future<Client> getClient() async {
|
|||
final client = Client('testclient', httpClient: FakeMatrixApi());
|
||||
client.database = getDatabase();
|
||||
await client.checkServer('https://fakeServer.notExisting');
|
||||
final resp = await client.api.login(
|
||||
type: 'm.login.password',
|
||||
user: 'test',
|
||||
password: '1234',
|
||||
initialDeviceDisplayName: 'Fluffy Matrix Client',
|
||||
);
|
||||
client.connect(
|
||||
newToken: resp.accessToken,
|
||||
newUserID: resp.userId,
|
||||
newHomeserver: client.api.homeserver,
|
||||
newToken: 'abcd',
|
||||
newUserID: '@test:fakeServer.notExisting',
|
||||
newHomeserver: client.homeserver,
|
||||
newDeviceName: 'Text Matrix Client',
|
||||
newDeviceID: resp.deviceId,
|
||||
newDeviceID: 'GHTYAJCE',
|
||||
newOlmAccount: pickledOlmAccount,
|
||||
);
|
||||
await Future.delayed(Duration(milliseconds: 10));
|
||||
|
|
|
@ -82,6 +82,10 @@ class FakeMatrixApi extends MockClient {
|
|||
action.contains(
|
||||
'/client/r0/rooms/!1234%3AfakeServer.notExisting/send/')) {
|
||||
res = {'event_id': '\$event${FakeMatrixApi.eventCounter++}'};
|
||||
} else if (action.contains('/client/r0/sync')) {
|
||||
res = {
|
||||
'next_batch': DateTime.now().millisecondsSinceEpoch.toString
|
||||
};
|
||||
} else {
|
||||
res = {
|
||||
'errcode': 'M_UNRECOGNIZED',
|
||||
|
|
|
@ -33,13 +33,13 @@ void main() {
|
|||
expect(content.isScheme('mxc'), true);
|
||||
|
||||
expect(content.getDownloadLink(client),
|
||||
'${client.api.homeserver.toString()}/_matrix/media/r0/download/exampleserver.abc/abcdefghijklmn');
|
||||
'${client.homeserver.toString()}/_matrix/media/r0/download/exampleserver.abc/abcdefghijklmn');
|
||||
expect(content.getThumbnail(client, width: 50, height: 50),
|
||||
'${client.api.homeserver.toString()}/_matrix/media/r0/thumbnail/exampleserver.abc/abcdefghijklmn?width=50&height=50&method=crop');
|
||||
'${client.homeserver.toString()}/_matrix/media/r0/thumbnail/exampleserver.abc/abcdefghijklmn?width=50&height=50&method=crop');
|
||||
expect(
|
||||
content.getThumbnail(client,
|
||||
width: 50, height: 50, method: ThumbnailMethod.scale),
|
||||
'${client.api.homeserver.toString()}/_matrix/media/r0/thumbnail/exampleserver.abc/abcdefghijklmn?width=50&height=50&method=scale');
|
||||
'${client.homeserver.toString()}/_matrix/media/r0/thumbnail/exampleserver.abc/abcdefghijklmn?width=50&height=50&method=scale');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ void main() {
|
|||
});
|
||||
test('startDirectChat', () async {
|
||||
await client.checkServer('https://fakeserver.notexisting');
|
||||
await client.login('test', '1234');
|
||||
await client.login(user: 'test', password: '1234');
|
||||
await user1.startDirectChat();
|
||||
});
|
||||
test('getPresence', () async {
|
||||
|
|
|
@ -22,14 +22,14 @@ void test() async {
|
|||
var testClientA = Client('TestClientA');
|
||||
testClientA.database = getDatabase();
|
||||
await testClientA.checkServer(homeserver);
|
||||
await testClientA.login(testUserA, testPasswordA);
|
||||
await testClientA.login(user: testUserA, password: testPasswordA);
|
||||
assert(testClientA.encryptionEnabled);
|
||||
|
||||
Logs.success('++++ Login $testUserB ++++');
|
||||
var testClientB = Client('TestClientB');
|
||||
testClientB.database = getDatabase();
|
||||
await testClientB.checkServer(homeserver);
|
||||
await testClientB.login(testUserB, testPasswordA);
|
||||
await testClientB.login(user: testUserB, password: testPasswordA);
|
||||
assert(testClientB.encryptionEnabled);
|
||||
|
||||
Logs.success('++++ ($testUserA) Leave all rooms ++++');
|
||||
|
@ -72,7 +72,7 @@ void test() async {
|
|||
.userDeviceKeys[testUserB].deviceKeys[testClientB.deviceID].blocked);
|
||||
|
||||
Logs.success('++++ ($testUserA) Create room and invite $testUserB ++++');
|
||||
await testClientA.api.createRoom(invite: [testUserB]);
|
||||
await testClientA.createRoom(invite: [testUserB]);
|
||||
await Future.delayed(Duration(seconds: 1));
|
||||
var room = testClientA.rooms.first;
|
||||
assert(room != null);
|
||||
|
@ -217,7 +217,7 @@ void test() async {
|
|||
Logs.success('++++ Login $testUserB in another client ++++');
|
||||
var testClientC = Client('TestClientC', database: getDatabase());
|
||||
await testClientC.checkServer(homeserver);
|
||||
await testClientC.login(testUserB, testPasswordA);
|
||||
await testClientC.login(user: testUserB, password: testPasswordA);
|
||||
await Future.delayed(Duration(seconds: 3));
|
||||
|
||||
Logs.success(
|
||||
|
@ -346,8 +346,8 @@ void test() async {
|
|||
await Future.delayed(Duration(seconds: 1));
|
||||
await testClientA.dispose();
|
||||
await testClientB.dispose();
|
||||
await testClientA.api.logoutAll();
|
||||
await testClientB.api.logoutAll();
|
||||
await testClientA.logoutAll();
|
||||
await testClientB.logoutAll();
|
||||
testClientA = null;
|
||||
testClientB = null;
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue