feat: (BREAKING) Replace onMigration with advanced callback onInitStateChanged
This makes it possible to track the process of initialization in the client by just enhancing what the onMigration callback already does.
This commit is contained in:
parent
cd31df9b27
commit
29aa28eecf
|
|
@ -597,6 +597,7 @@ class Client extends MatrixApi {
|
||||||
bool? refreshToken,
|
bool? refreshToken,
|
||||||
AuthenticationData? auth,
|
AuthenticationData? auth,
|
||||||
AccountKind? kind,
|
AccountKind? kind,
|
||||||
|
void Function(InitState)? onInitStateChanged,
|
||||||
}) async {
|
}) async {
|
||||||
final response = await super.register(
|
final response = await super.register(
|
||||||
kind: kind,
|
kind: kind,
|
||||||
|
|
@ -632,6 +633,7 @@ class Client extends MatrixApi {
|
||||||
newHomeserver: homeserver,
|
newHomeserver: homeserver,
|
||||||
newDeviceName: initialDeviceDisplayName ?? '',
|
newDeviceName: initialDeviceDisplayName ?? '',
|
||||||
newDeviceID: deviceId_,
|
newDeviceID: deviceId_,
|
||||||
|
onInitStateChanged: onInitStateChanged,
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
@ -655,6 +657,7 @@ class Client extends MatrixApi {
|
||||||
@Deprecated('Deprecated in favour of identifier.') String? user,
|
@Deprecated('Deprecated in favour of identifier.') String? user,
|
||||||
@Deprecated('Deprecated in favour of identifier.') String? medium,
|
@Deprecated('Deprecated in favour of identifier.') String? medium,
|
||||||
@Deprecated('Deprecated in favour of identifier.') String? address,
|
@Deprecated('Deprecated in favour of identifier.') String? address,
|
||||||
|
void Function(InitState)? onInitStateChanged,
|
||||||
}) async {
|
}) async {
|
||||||
if (homeserver == null) {
|
if (homeserver == null) {
|
||||||
final domain = identifier is AuthenticationUserIdentifier
|
final domain = identifier is AuthenticationUserIdentifier
|
||||||
|
|
@ -704,6 +707,7 @@ class Client extends MatrixApi {
|
||||||
newHomeserver: homeserver_,
|
newHomeserver: homeserver_,
|
||||||
newDeviceName: initialDeviceDisplayName ?? '',
|
newDeviceName: initialDeviceDisplayName ?? '',
|
||||||
newDeviceID: deviceId_,
|
newDeviceID: deviceId_,
|
||||||
|
onInitStateChanged: onInitStateChanged,
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
@ -1931,7 +1935,11 @@ class Client extends MatrixApi {
|
||||||
bool waitUntilLoadCompletedLoaded = true,
|
bool waitUntilLoadCompletedLoaded = true,
|
||||||
|
|
||||||
/// Will be called if the app performs a migration task from the [legacyDatabaseBuilder]
|
/// Will be called if the app performs a migration task from the [legacyDatabaseBuilder]
|
||||||
|
@Deprecated('Use onInitStateChanged and listen to `InitState.migration`.')
|
||||||
void Function()? onMigration,
|
void Function()? onMigration,
|
||||||
|
|
||||||
|
/// To track what actually happens you can set a callback here.
|
||||||
|
void Function(InitState)? onInitStateChanged,
|
||||||
}) async {
|
}) async {
|
||||||
if ((newToken != null ||
|
if ((newToken != null ||
|
||||||
newUserID != null ||
|
newUserID != null ||
|
||||||
|
|
@ -1956,6 +1964,7 @@ class Client extends MatrixApi {
|
||||||
String? accessToken;
|
String? accessToken;
|
||||||
String? userID;
|
String? userID;
|
||||||
try {
|
try {
|
||||||
|
onInitStateChanged?.call(InitState.initializing);
|
||||||
Logs().i('Initialize client $clientName');
|
Logs().i('Initialize client $clientName');
|
||||||
if (onLoginStateChanged.value == LoginState.loggedIn) {
|
if (onLoginStateChanged.value == LoginState.loggedIn) {
|
||||||
throw ClientInitPreconditionError(
|
throw ClientInitPreconditionError(
|
||||||
|
|
@ -2036,14 +2045,21 @@ class Client extends MatrixApi {
|
||||||
encryption?.pickledOlmAccount,
|
encryption?.pickledOlmAccount,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
onInitStateChanged?.call(InitState.finished);
|
||||||
onLoginStateChanged.add(LoginState.loggedIn);
|
onLoginStateChanged.add(LoginState.loggedIn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accessToken == null || homeserver == null || userID == null) {
|
if (accessToken == null || homeserver == null || userID == null) {
|
||||||
if (legacyDatabaseBuilder != null) {
|
if (legacyDatabaseBuilder != null) {
|
||||||
await _migrateFromLegacyDatabase(onMigration: onMigration);
|
await _migrateFromLegacyDatabase(
|
||||||
if (isLogged()) return;
|
onInitStateChanged: onInitStateChanged,
|
||||||
|
onMigration: onMigration,
|
||||||
|
);
|
||||||
|
if (isLogged()) {
|
||||||
|
onInitStateChanged?.call(InitState.finished);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// we aren't logged in
|
// we aren't logged in
|
||||||
await encryption?.dispose();
|
await encryption?.dispose();
|
||||||
|
|
@ -2051,6 +2067,7 @@ class Client extends MatrixApi {
|
||||||
onLoginStateChanged.add(LoginState.loggedOut);
|
onLoginStateChanged.add(LoginState.loggedOut);
|
||||||
Logs().i('User is not logged in.');
|
Logs().i('User is not logged in.');
|
||||||
_initLock = false;
|
_initLock = false;
|
||||||
|
onInitStateChanged?.call(InitState.finished);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2065,6 +2082,7 @@ class Client extends MatrixApi {
|
||||||
await encryption?.dispose();
|
await encryption?.dispose();
|
||||||
_encryption = null;
|
_encryption = null;
|
||||||
}
|
}
|
||||||
|
onInitStateChanged?.call(InitState.settingUpEncryption);
|
||||||
await encryption?.init(olmAccount);
|
await encryption?.init(olmAccount);
|
||||||
|
|
||||||
final database = this.database;
|
final database = this.database;
|
||||||
|
|
@ -2112,6 +2130,7 @@ class Client extends MatrixApi {
|
||||||
// ignore: deprecated_member_use_from_same_package
|
// ignore: deprecated_member_use_from_same_package
|
||||||
presences.clear();
|
presences.clear();
|
||||||
if (waitUntilLoadCompletedLoaded) {
|
if (waitUntilLoadCompletedLoaded) {
|
||||||
|
onInitStateChanged?.call(InitState.loadingData);
|
||||||
await userDeviceKeysLoading;
|
await userDeviceKeysLoading;
|
||||||
await roomsLoading;
|
await roomsLoading;
|
||||||
await _accountDataLoading;
|
await _accountDataLoading;
|
||||||
|
|
@ -2127,14 +2146,18 @@ class Client extends MatrixApi {
|
||||||
/// Timeout of 0, so that we don't see a spinner for 30 seconds.
|
/// Timeout of 0, so that we don't see a spinner for 30 seconds.
|
||||||
firstSyncReceived = _sync(timeout: Duration.zero);
|
firstSyncReceived = _sync(timeout: Duration.zero);
|
||||||
if (waitForFirstSync) {
|
if (waitForFirstSync) {
|
||||||
|
onInitStateChanged?.call(InitState.waitingForFirstSync);
|
||||||
await firstSyncReceived;
|
await firstSyncReceived;
|
||||||
}
|
}
|
||||||
|
onInitStateChanged?.call(InitState.finished);
|
||||||
return;
|
return;
|
||||||
} on ClientInitPreconditionError {
|
} on ClientInitPreconditionError {
|
||||||
|
onInitStateChanged?.call(InitState.error);
|
||||||
rethrow;
|
rethrow;
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
Logs().wtf('Client initialization failed', e, s);
|
Logs().wtf('Client initialization failed', e, s);
|
||||||
onLoginStateChanged.addError(e, s);
|
onLoginStateChanged.addError(e, s);
|
||||||
|
onInitStateChanged?.call(InitState.error);
|
||||||
final clientInitException = ClientInitException(
|
final clientInitException = ClientInitException(
|
||||||
e,
|
e,
|
||||||
homeserver: homeserver,
|
homeserver: homeserver,
|
||||||
|
|
@ -3728,6 +3751,7 @@ class Client extends MatrixApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _migrateFromLegacyDatabase({
|
Future<void> _migrateFromLegacyDatabase({
|
||||||
|
void Function(InitState)? onInitStateChanged,
|
||||||
void Function()? onMigration,
|
void Function()? onMigration,
|
||||||
}) async {
|
}) async {
|
||||||
Logs().i('Check legacy database for migration data...');
|
Logs().i('Check legacy database for migration data...');
|
||||||
|
|
@ -3741,6 +3765,7 @@ class Client extends MatrixApi {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Logs().i('Found data in the legacy database!');
|
Logs().i('Found data in the legacy database!');
|
||||||
|
onInitStateChanged?.call(InitState.migratingDatabase);
|
||||||
onMigration?.call();
|
onMigration?.call();
|
||||||
_id = migrateClient['client_id'];
|
_id = migrateClient['client_id'];
|
||||||
final tokenExpiresAtMs =
|
final tokenExpiresAtMs =
|
||||||
|
|
@ -3858,6 +3883,7 @@ class Client extends MatrixApi {
|
||||||
return init(
|
return init(
|
||||||
waitForFirstSync: false,
|
waitForFirstSync: false,
|
||||||
waitUntilLoadCompletedLoaded: false,
|
waitUntilLoadCompletedLoaded: false,
|
||||||
|
onInitStateChanged: onInitStateChanged,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3958,3 +3984,30 @@ class _EventPendingDecryption {
|
||||||
|
|
||||||
_EventPendingDecryption(this.event);
|
_EventPendingDecryption(this.event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum InitState {
|
||||||
|
/// Initialization has been started. Client fetches information from the database.
|
||||||
|
initializing,
|
||||||
|
|
||||||
|
/// The database has been updated. A migration is in progress.
|
||||||
|
migratingDatabase,
|
||||||
|
|
||||||
|
/// The encryption module will be set up now. For the first login this also
|
||||||
|
/// includes uploading keys to the server.
|
||||||
|
settingUpEncryption,
|
||||||
|
|
||||||
|
/// The client is loading rooms, device keys and account data from the
|
||||||
|
/// database.
|
||||||
|
loadingData,
|
||||||
|
|
||||||
|
/// The client waits now for the first sync before procceeding. Get more
|
||||||
|
/// information from `Client.onSyncUpdate`.
|
||||||
|
waitingForFirstSync,
|
||||||
|
|
||||||
|
/// Initialization is complete without errors. The client is now either
|
||||||
|
/// logged in or no active session was found.
|
||||||
|
finished,
|
||||||
|
|
||||||
|
/// Initialization has been completed with an error.
|
||||||
|
error,
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,15 +82,26 @@ void main() {
|
||||||
databaseBuilder: getDatabase,
|
databaseBuilder: getDatabase,
|
||||||
);
|
);
|
||||||
expect(client.isLogged(), false);
|
expect(client.isLogged(), false);
|
||||||
await client.init();
|
final Set<InitState> initStates = {};
|
||||||
|
await client.init(onInitStateChanged: initStates.add);
|
||||||
expect(client.isLogged(), false);
|
expect(client.isLogged(), false);
|
||||||
|
expect(initStates, {InitState.initializing, InitState.finished});
|
||||||
|
initStates.clear();
|
||||||
await client.login(
|
await client.login(
|
||||||
LoginType.mLoginPassword,
|
LoginType.mLoginPassword,
|
||||||
token: 'abcd',
|
token: 'abcd',
|
||||||
identifier:
|
identifier:
|
||||||
AuthenticationUserIdentifier(user: '@test:fakeServer.notExisting'),
|
AuthenticationUserIdentifier(user: '@test:fakeServer.notExisting'),
|
||||||
deviceId: 'GHTYAJCE',
|
deviceId: 'GHTYAJCE',
|
||||||
|
onInitStateChanged: initStates.add,
|
||||||
);
|
);
|
||||||
|
expect(initStates, {
|
||||||
|
InitState.initializing,
|
||||||
|
InitState.settingUpEncryption,
|
||||||
|
InitState.loadingData,
|
||||||
|
InitState.waitingForFirstSync,
|
||||||
|
InitState.finished,
|
||||||
|
});
|
||||||
|
|
||||||
expect(client.isLogged(), true);
|
expect(client.isLogged(), true);
|
||||||
|
|
||||||
|
|
@ -1439,7 +1450,14 @@ void main() {
|
||||||
databaseBuilder: getDatabase,
|
databaseBuilder: getDatabase,
|
||||||
legacyDatabaseBuilder: (_) => database,
|
legacyDatabaseBuilder: (_) => database,
|
||||||
);
|
);
|
||||||
await hiveClient.init();
|
final Set<InitState> initStates = {};
|
||||||
|
await hiveClient.init(onInitStateChanged: initStates.add);
|
||||||
|
expect(initStates, {
|
||||||
|
InitState.initializing,
|
||||||
|
InitState.migratingDatabase,
|
||||||
|
InitState.settingUpEncryption,
|
||||||
|
InitState.finished,
|
||||||
|
});
|
||||||
await Future.delayed(Duration(milliseconds: 200));
|
await Future.delayed(Duration(milliseconds: 200));
|
||||||
expect(hiveClient.isLogged(), true);
|
expect(hiveClient.isLogged(), true);
|
||||||
await hiveClient.dispose(closeDatabase: false);
|
await hiveClient.dispose(closeDatabase: false);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue