refactor: Minor init refactoring
This commit is contained in:
parent
b67ab870fa
commit
0697d47cc2
|
|
@ -46,7 +46,9 @@ class Client extends MatrixApi {
|
|||
int _id;
|
||||
int get id => _id;
|
||||
|
||||
Database database;
|
||||
final FutureOr<Database> Function(Client) databaseBuilder;
|
||||
Database _database;
|
||||
Database get database => _database;
|
||||
|
||||
bool enableE2eeRecovery;
|
||||
|
||||
|
|
@ -87,7 +89,7 @@ class Client extends MatrixApi {
|
|||
/// in a room for the room list.
|
||||
Client(
|
||||
this.clientName, {
|
||||
this.database,
|
||||
this.databaseBuilder,
|
||||
this.enableE2eeRecovery = false,
|
||||
this.verificationMethods,
|
||||
http.Client httpClient,
|
||||
|
|
@ -324,7 +326,7 @@ class Client extends MatrixApi {
|
|||
response.userId == null) {
|
||||
throw 'Registered but token, device ID or user ID is null.';
|
||||
}
|
||||
await connect(
|
||||
await init(
|
||||
newToken: response.accessToken,
|
||||
newUserID: response.userId,
|
||||
newHomeserver: homeserver,
|
||||
|
|
@ -369,7 +371,7 @@ class Client extends MatrixApi {
|
|||
loginResp.userId == null) {
|
||||
throw Exception('Registered but token, device ID or user ID is null.');
|
||||
}
|
||||
await connect(
|
||||
await init(
|
||||
newToken: loginResp.accessToken,
|
||||
newUserID: loginResp.userId,
|
||||
newHomeserver: homeserver,
|
||||
|
|
@ -587,120 +589,159 @@ class Client extends MatrixApi {
|
|||
/// an error?
|
||||
int syncErrorTimeoutSec = 3;
|
||||
|
||||
/// Sets the user credentials and starts the synchronisation.
|
||||
///
|
||||
/// Before you can connect you need at least an [accessToken], a [homeserver],
|
||||
/// a [userID], a [deviceID], and a [deviceName].
|
||||
///
|
||||
/// You get this informations
|
||||
/// by logging in to your Matrix account, using the [login API](https://matrix.org/docs/spec/client_server/r0.4.0.html#post-matrix-client-r0-login).
|
||||
///
|
||||
/// To log in you can use [jsonRequest()] after you have set the [homeserver]
|
||||
/// to a valid url. For example:
|
||||
///
|
||||
/// ```
|
||||
/// final resp = await matrix
|
||||
/// .jsonRequest(type: RequestType.POST, action: "/client/r0/login", data: {
|
||||
/// "type": "m.login.password",
|
||||
/// "user": "test",
|
||||
/// "password": "1234",
|
||||
/// "initial_device_display_name": "Matrix Client"
|
||||
/// });
|
||||
/// ```
|
||||
///
|
||||
/// Returns:
|
||||
///
|
||||
/// ```
|
||||
/// {
|
||||
/// "user_id": "@cheeky_monkey:matrix.org",
|
||||
/// "access_token": "abc123",
|
||||
/// "device_id": "GHTYAJCE"
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Sends [LoginState.logged] to [onLoginStateChanged].
|
||||
@Deprecated('Use init() instead')
|
||||
void connect({
|
||||
String newToken,
|
||||
Uri newHomeserver,
|
||||
String newUserID,
|
||||
String newDeviceName,
|
||||
String newDeviceID,
|
||||
String newPrevBatch,
|
||||
String newOlmAccount,
|
||||
}) =>
|
||||
init(
|
||||
newToken: newToken,
|
||||
newHomeserver: newHomeserver,
|
||||
newUserID: newUserID,
|
||||
newDeviceName: newDeviceName,
|
||||
newDeviceID: newDeviceID,
|
||||
newOlmAccount: newOlmAccount,
|
||||
);
|
||||
|
||||
bool _initLock = false;
|
||||
|
||||
/// Sets the user credentials and starts the synchronisation.
|
||||
///
|
||||
/// Before you can connect you need at least an [accessToken], a [homeserver],
|
||||
/// a [userID], a [deviceID], and a [deviceName].
|
||||
///
|
||||
/// Usually you don't need to call this method by yourself because [login()], [register()]
|
||||
/// and even the constructor calls it.
|
||||
///
|
||||
/// Sends [LoginState.logged] to [onLoginStateChanged].
|
||||
///
|
||||
/// If one of [newToken], [newUserID], [newDeviceID], [newDeviceName] is set then
|
||||
/// all of them must be set! If you don't set them, this method will try to
|
||||
/// get them from the database.
|
||||
void init({
|
||||
String newToken,
|
||||
Uri newHomeserver,
|
||||
String newUserID,
|
||||
String newDeviceName,
|
||||
String newDeviceID,
|
||||
String newOlmAccount,
|
||||
}) async {
|
||||
String olmAccount;
|
||||
if (database != null) {
|
||||
final account = await database.getClient(clientName);
|
||||
if (account != null) {
|
||||
_id = account.clientId;
|
||||
homeserver = Uri.parse(account.homeserverUrl);
|
||||
accessToken = account.token;
|
||||
_userID = account.userId;
|
||||
_deviceID = account.deviceId;
|
||||
_deviceName = account.deviceName;
|
||||
prevBatch = account.prevBatch;
|
||||
olmAccount = account.olmAccount;
|
||||
if ((newToken != null ||
|
||||
newUserID != null ||
|
||||
newDeviceID != null ||
|
||||
newDeviceName != null) &&
|
||||
(newToken == null ||
|
||||
newUserID == null ||
|
||||
newDeviceID == null ||
|
||||
newDeviceName == null)) {
|
||||
throw Exception(
|
||||
'If one of [newToken, newUserID, newDeviceID, newDeviceName] is set then all of them must be set!');
|
||||
}
|
||||
|
||||
if (_initLock) throw Exception('[init()] has been called multiple times!');
|
||||
_initLock = true;
|
||||
try {
|
||||
Logs.info('Initialize client $clientName');
|
||||
if (isLogged()) {
|
||||
throw Exception('User is already logged in! Call [logout()] first!');
|
||||
}
|
||||
}
|
||||
accessToken = newToken ?? accessToken;
|
||||
homeserver = newHomeserver ?? homeserver;
|
||||
_userID = newUserID ?? _userID;
|
||||
_deviceID = newDeviceID ?? _deviceID;
|
||||
_deviceName = newDeviceName ?? _deviceName;
|
||||
prevBatch = newPrevBatch ?? prevBatch;
|
||||
olmAccount = newOlmAccount ?? olmAccount;
|
||||
|
||||
if (accessToken == null || homeserver == null || _userID == null) {
|
||||
// we aren't logged in
|
||||
encryption?.dispose();
|
||||
encryption = null;
|
||||
onLoginStateChanged.add(LoginState.loggedOut);
|
||||
return;
|
||||
}
|
||||
if (databaseBuilder != null) {
|
||||
_database ??= await databaseBuilder(this);
|
||||
}
|
||||
|
||||
encryption?.dispose();
|
||||
encryption =
|
||||
Encryption(client: this, enableE2eeRecovery: enableE2eeRecovery);
|
||||
await encryption.init(olmAccount);
|
||||
|
||||
if (database != null) {
|
||||
if (id != null) {
|
||||
await database.updateClient(
|
||||
homeserver.toString(),
|
||||
accessToken,
|
||||
_userID,
|
||||
_deviceID,
|
||||
_deviceName,
|
||||
prevBatch,
|
||||
encryption?.pickledOlmAccount,
|
||||
id,
|
||||
);
|
||||
String olmAccount;
|
||||
if (database != null) {
|
||||
final account = await database.getClient(clientName);
|
||||
if (account != null) {
|
||||
_id = account.clientId;
|
||||
homeserver = Uri.parse(account.homeserverUrl);
|
||||
accessToken = account.token;
|
||||
_userID = account.userId;
|
||||
_deviceID = account.deviceId;
|
||||
_deviceName = account.deviceName;
|
||||
prevBatch = account.prevBatch;
|
||||
olmAccount = account.olmAccount;
|
||||
}
|
||||
}
|
||||
if (newToken != null) {
|
||||
accessToken = newToken;
|
||||
homeserver = newHomeserver;
|
||||
_userID = newUserID;
|
||||
_deviceID = newDeviceID;
|
||||
_deviceName = newDeviceName;
|
||||
olmAccount = newOlmAccount;
|
||||
} else {
|
||||
_id = await database.insertClient(
|
||||
clientName,
|
||||
homeserver.toString(),
|
||||
accessToken,
|
||||
_userID,
|
||||
_deviceID,
|
||||
_deviceName,
|
||||
prevBatch,
|
||||
encryption?.pickledOlmAccount,
|
||||
);
|
||||
accessToken = newToken ?? accessToken;
|
||||
homeserver = newHomeserver ?? homeserver;
|
||||
_userID = newUserID ?? _userID;
|
||||
_deviceID = newDeviceID ?? _deviceID;
|
||||
_deviceName = newDeviceName ?? _deviceName;
|
||||
olmAccount = newOlmAccount ?? olmAccount;
|
||||
}
|
||||
_userDeviceKeys = await database.getUserDeviceKeys(this);
|
||||
_rooms = await database.getRoomList(this, onlyLeft: false);
|
||||
_sortRooms();
|
||||
accountData = await database.getAccountData(id);
|
||||
presences.clear();
|
||||
|
||||
if (accessToken == null || homeserver == null || _userID == null) {
|
||||
// we aren't logged in
|
||||
encryption?.dispose();
|
||||
encryption = null;
|
||||
onLoginStateChanged.add(LoginState.loggedOut);
|
||||
Logs.info('User is not logged in.');
|
||||
_initLock = false;
|
||||
return;
|
||||
}
|
||||
_initLock = false;
|
||||
|
||||
encryption?.dispose();
|
||||
encryption =
|
||||
Encryption(client: this, enableE2eeRecovery: enableE2eeRecovery);
|
||||
await encryption.init(olmAccount);
|
||||
|
||||
if (database != null) {
|
||||
if (id != null) {
|
||||
await database.updateClient(
|
||||
homeserver.toString(),
|
||||
accessToken,
|
||||
_userID,
|
||||
_deviceID,
|
||||
_deviceName,
|
||||
prevBatch,
|
||||
encryption?.pickledOlmAccount,
|
||||
id,
|
||||
);
|
||||
} else {
|
||||
_id = await database.insertClient(
|
||||
clientName,
|
||||
homeserver.toString(),
|
||||
accessToken,
|
||||
_userID,
|
||||
_deviceID,
|
||||
_deviceName,
|
||||
prevBatch,
|
||||
encryption?.pickledOlmAccount,
|
||||
);
|
||||
}
|
||||
_userDeviceKeys = await database.getUserDeviceKeys(this);
|
||||
_rooms = await database.getRoomList(this, onlyLeft: false);
|
||||
_sortRooms();
|
||||
accountData = await database.getAccountData(id);
|
||||
presences.clear();
|
||||
}
|
||||
|
||||
onLoginStateChanged.add(LoginState.logged);
|
||||
Logs.success(
|
||||
'Successfully connected as ${userID.localpart} with ${homeserver.toString()}',
|
||||
);
|
||||
return _sync();
|
||||
} catch (e, s) {
|
||||
Logs.error('Initialization failed: ${e.toString()}', s);
|
||||
clear();
|
||||
onLoginStateChanged.addError(e, s);
|
||||
rethrow;
|
||||
}
|
||||
|
||||
onLoginStateChanged.add(LoginState.logged);
|
||||
Logs.success(
|
||||
'Successfully connected as ${userID.localpart} with ${homeserver.toString()}',
|
||||
);
|
||||
|
||||
// Always do a _sync after login, even if backgroundSync is set to off
|
||||
return _sync();
|
||||
}
|
||||
|
||||
/// Used for testing only
|
||||
|
|
@ -1629,7 +1670,7 @@ sort order of ${prevState.sortOrder}. This should never happen...''');
|
|||
|
||||
/// Stops the synchronization and closes the database. After this
|
||||
/// you can safely make this Client instance null.
|
||||
Future<void> dispose({bool closeDatabase = false}) async {
|
||||
Future<void> dispose({bool closeDatabase = true}) async {
|
||||
_disposed = true;
|
||||
try {
|
||||
await _currentTransaction;
|
||||
|
|
@ -1639,11 +1680,13 @@ sort order of ${prevState.sortOrder}. This should never happen...''');
|
|||
encryption?.dispose();
|
||||
encryption = null;
|
||||
try {
|
||||
if (closeDatabase) await database?.close();
|
||||
if (closeDatabase && database != null) {
|
||||
await database.close().catchError((e, s) => Logs.warning(e, s));
|
||||
_database = null;
|
||||
}
|
||||
} catch (error, stacktrace) {
|
||||
Logs.warning('Failed to close database: ' + error.toString(), stacktrace);
|
||||
}
|
||||
database = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ void main() {
|
|||
var firstSyncFuture = matrix.onFirstSync.stream.first;
|
||||
var syncFuture = matrix.onSync.stream.first;
|
||||
|
||||
matrix.connect(
|
||||
matrix.init(
|
||||
newToken: 'abcd',
|
||||
newUserID: '@test:fakeServer.notExisting',
|
||||
newHomeserver: matrix.homeserver,
|
||||
|
|
@ -379,10 +379,14 @@ void main() {
|
|||
});
|
||||
});
|
||||
test('Test the fake store api', () async {
|
||||
var client1 = Client('testclient', httpClient: FakeMatrixApi());
|
||||
client1.database = getDatabase();
|
||||
final database = await getDatabase(null);
|
||||
var client1 = Client(
|
||||
'testclient',
|
||||
httpClient: FakeMatrixApi(),
|
||||
databaseBuilder: (_) => database,
|
||||
);
|
||||
|
||||
client1.connect(
|
||||
client1.init(
|
||||
newToken: 'abc123',
|
||||
newUserID: '@test:fakeServer.notExisting',
|
||||
newHomeserver: Uri.parse('https://fakeServer.notExisting'),
|
||||
|
|
@ -396,10 +400,13 @@ void main() {
|
|||
expect(client1.isLogged(), true);
|
||||
expect(client1.rooms.length, 2);
|
||||
|
||||
var client2 = Client('testclient', httpClient: FakeMatrixApi());
|
||||
client2.database = client1.database;
|
||||
var client2 = Client(
|
||||
'testclient',
|
||||
httpClient: FakeMatrixApi(),
|
||||
databaseBuilder: (_) => database,
|
||||
);
|
||||
|
||||
client2.connect();
|
||||
client2.init();
|
||||
await Future.delayed(Duration(milliseconds: 100));
|
||||
|
||||
expect(client2.isLogged(), true);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import 'package:test/test.dart';
|
|||
import 'package:olm/olm.dart' as olm;
|
||||
|
||||
import '../fake_client.dart';
|
||||
import '../fake_database.dart';
|
||||
import '../fake_matrix_api.dart';
|
||||
|
||||
void main() {
|
||||
|
|
@ -43,15 +44,15 @@ void main() {
|
|||
if (!olmEnabled) return;
|
||||
|
||||
Client client;
|
||||
var otherClient = Client('othertestclient', httpClient: FakeMatrixApi());
|
||||
var otherClient = Client('othertestclient',
|
||||
httpClient: FakeMatrixApi(), databaseBuilder: getDatabase);
|
||||
DeviceKeys device;
|
||||
Map<String, dynamic> payload;
|
||||
|
||||
test('setupClient', () async {
|
||||
client = await getClient();
|
||||
otherClient.database = client.database;
|
||||
await otherClient.checkHomeserver('https://fakeServer.notExisting');
|
||||
otherClient.connect(
|
||||
otherClient.init(
|
||||
newToken: 'abc',
|
||||
newUserID: '@othertest:fakeServer.notExisting',
|
||||
newHomeserver: otherClient.homeserver,
|
||||
|
|
|
|||
|
|
@ -83,10 +83,11 @@ void main() {
|
|||
|
||||
test('setupClient', () async {
|
||||
client1 = await getClient();
|
||||
client2 = Client('othertestclient', httpClient: FakeMatrixApi());
|
||||
client2.database = client1.database;
|
||||
client2 = Client('othertestclient',
|
||||
httpClient: FakeMatrixApi(),
|
||||
databaseBuilder: (_) => client1.database);
|
||||
await client2.checkHomeserver('https://fakeServer.notExisting');
|
||||
client2.connect(
|
||||
client2.init(
|
||||
newToken: 'abc',
|
||||
newUserID: '@othertest:fakeServer.notExisting',
|
||||
newHomeserver: client2.homeserver,
|
||||
|
|
|
|||
|
|
@ -29,10 +29,10 @@ const pickledOlmAccount =
|
|||
'N2v1MkIFGcl0mQpo2OCwSopxPQJ0wnl7oe7PKiT4141AijfdTIhRu+ceXzXKy3Kr00nLqXtRv7kid6hU4a+V0rfJWLL0Y51+3Rp/ORDVnQy+SSeo6Fn4FHcXrxifJEJ0djla5u98fBcJ8BSkhIDmtXRPi5/oJAvpiYn+8zMjFHobOeZUAxYR0VfQ9JzSYBsSovoQ7uFkNks1M4EDUvHtuyg3RxViwdNxs3718fyAqQ/VSwbXsY0Nl+qQbF+nlVGHenGqk5SuNl1P6e1PzZxcR0IfXA94Xij1Ob5gDv5YH4UCn9wRMG0abZsQP0YzpDM0FLaHSCyo9i5JD/vMlhH+nZWrgAzPPCTNGYewNV8/h3c+VyJh8ZTx/fVi6Yq46Fv+27Ga2ETRZ3Qn+Oyx6dLBjnBZ9iUvIhqpe2XqaGA1PopOz8iDnaZitw';
|
||||
|
||||
Future<Client> getClient() async {
|
||||
final client = Client('testclient', httpClient: FakeMatrixApi());
|
||||
client.database = getDatabase();
|
||||
final client = Client('testclient',
|
||||
httpClient: FakeMatrixApi(), databaseBuilder: getDatabase);
|
||||
await client.checkHomeserver('https://fakeServer.notExisting');
|
||||
client.connect(
|
||||
client.init(
|
||||
newToken: 'abcd',
|
||||
newUserID: '@test:fakeServer.notExisting',
|
||||
newHomeserver: client.homeserver,
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import 'package:famedlysdk/famedlysdk.dart';
|
|||
import 'package:moor/moor.dart';
|
||||
import 'package:moor/ffi.dart' as moor;
|
||||
|
||||
Database getDatabase() {
|
||||
Future<Database> getDatabase(Client _) async {
|
||||
moorRuntimeOptions.dontWarnAboutMultipleDatabases = true;
|
||||
return Database(moor.VmDatabase.memory());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@ import 'fake_database.dart';
|
|||
|
||||
void main() {
|
||||
group('Databse', () {
|
||||
final database = getDatabase();
|
||||
var clientId = -1;
|
||||
var room = Room(id: '!room:blubb');
|
||||
test('setupDatabase', () async {
|
||||
final database = await getDatabase(null);
|
||||
clientId = await database.insertClient(
|
||||
'testclient',
|
||||
'https://example.org',
|
||||
|
|
@ -38,6 +38,7 @@ void main() {
|
|||
null);
|
||||
});
|
||||
test('storeEventUpdate', () async {
|
||||
final database = await getDatabase(null);
|
||||
// store a simple update
|
||||
var update = EventUpdate(
|
||||
type: EventUpdateType.timeline,
|
||||
|
|
|
|||
|
|
@ -22,16 +22,14 @@ void test() async {
|
|||
Logs.success('[LibOlm] Enabled');
|
||||
|
||||
Logs.success('++++ Login Alice at ++++');
|
||||
testClientA = Client('TestClientA');
|
||||
testClientA.database = getDatabase();
|
||||
testClientA = Client('TestClientA', databaseBuilder: getDatabase);
|
||||
await testClientA.checkHomeserver(TestUser.homeserver);
|
||||
await testClientA.login(
|
||||
user: TestUser.username, password: TestUser.password);
|
||||
assert(testClientA.encryptionEnabled);
|
||||
|
||||
Logs.success('++++ Login Bob ++++');
|
||||
testClientB = Client('TestClientB');
|
||||
testClientB.database = getDatabase();
|
||||
testClientB = Client('TestClientB', databaseBuilder: getDatabase);
|
||||
await testClientB.checkHomeserver(TestUser.homeserver);
|
||||
await testClientB.login(
|
||||
user: TestUser.username2, password: TestUser.password);
|
||||
|
|
@ -221,7 +219,7 @@ void test() async {
|
|||
"++++ (Alice) Received decrypted message: '${room.lastMessage}' ++++");
|
||||
|
||||
Logs.success('++++ Login Bob in another client ++++');
|
||||
var testClientC = Client('TestClientC', database: getDatabase());
|
||||
var testClientC = Client('TestClientC', databaseBuilder: getDatabase);
|
||||
await testClientC.checkHomeserver(TestUser.homeserver);
|
||||
await testClientC.login(
|
||||
user: TestUser.username2, password: TestUser.password);
|
||||
|
|
@ -269,7 +267,7 @@ void test() async {
|
|||
"++++ (Bob) Received decrypted message: '${inviteRoom.lastMessage}' ++++");
|
||||
|
||||
Logs.success('++++ Logout Bob another client ++++');
|
||||
await testClientC.dispose();
|
||||
await testClientC.dispose(closeDatabase: false);
|
||||
await testClientC.logout();
|
||||
testClientC = null;
|
||||
await Future.delayed(Duration(seconds: 5));
|
||||
|
|
@ -317,8 +315,8 @@ void test() async {
|
|||
Logs.success('++++ Logout Alice and Bob ++++');
|
||||
if (testClientA?.isLogged() ?? false) await testClientA.logoutAll();
|
||||
if (testClientA?.isLogged() ?? false) await testClientB.logoutAll();
|
||||
await testClientA?.dispose();
|
||||
await testClientB?.dispose();
|
||||
await testClientA?.dispose(closeDatabase: false);
|
||||
await testClientB?.dispose(closeDatabase: false);
|
||||
testClientA = null;
|
||||
testClientB = null;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue