Merge pull request #1962 from famedly/krille/init-state

feat: (BREAKING) Replace onMigration with advanced callback onInitStateChanged
This commit is contained in:
Krille-chan 2024-12-09 12:36:06 +01:00 committed by GitHub
commit 3bfc5efdc6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 75 additions and 4 deletions

View File

@ -597,6 +597,7 @@ class Client extends MatrixApi {
bool? refreshToken,
AuthenticationData? auth,
AccountKind? kind,
void Function(InitState)? onInitStateChanged,
}) async {
final response = await super.register(
kind: kind,
@ -632,6 +633,7 @@ class Client extends MatrixApi {
newHomeserver: homeserver,
newDeviceName: initialDeviceDisplayName ?? '',
newDeviceID: deviceId_,
onInitStateChanged: onInitStateChanged,
);
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? medium,
@Deprecated('Deprecated in favour of identifier.') String? address,
void Function(InitState)? onInitStateChanged,
}) async {
if (homeserver == null) {
final domain = identifier is AuthenticationUserIdentifier
@ -704,6 +707,7 @@ class Client extends MatrixApi {
newHomeserver: homeserver_,
newDeviceName: initialDeviceDisplayName ?? '',
newDeviceID: deviceId_,
onInitStateChanged: onInitStateChanged,
);
return response;
}
@ -1931,7 +1935,11 @@ class Client extends MatrixApi {
bool waitUntilLoadCompletedLoaded = true,
/// Will be called if the app performs a migration task from the [legacyDatabaseBuilder]
@Deprecated('Use onInitStateChanged and listen to `InitState.migration`.')
void Function()? onMigration,
/// To track what actually happens you can set a callback here.
void Function(InitState)? onInitStateChanged,
}) async {
if ((newToken != null ||
newUserID != null ||
@ -1956,6 +1964,7 @@ class Client extends MatrixApi {
String? accessToken;
String? userID;
try {
onInitStateChanged?.call(InitState.initializing);
Logs().i('Initialize client $clientName');
if (onLoginStateChanged.value == LoginState.loggedIn) {
throw ClientInitPreconditionError(
@ -2036,14 +2045,21 @@ class Client extends MatrixApi {
encryption?.pickledOlmAccount,
);
}
onInitStateChanged?.call(InitState.finished);
onLoginStateChanged.add(LoginState.loggedIn);
return;
}
if (accessToken == null || homeserver == null || userID == null) {
if (legacyDatabaseBuilder != null) {
await _migrateFromLegacyDatabase(onMigration: onMigration);
if (isLogged()) return;
await _migrateFromLegacyDatabase(
onInitStateChanged: onInitStateChanged,
onMigration: onMigration,
);
if (isLogged()) {
onInitStateChanged?.call(InitState.finished);
return;
}
}
// we aren't logged in
await encryption?.dispose();
@ -2051,6 +2067,7 @@ class Client extends MatrixApi {
onLoginStateChanged.add(LoginState.loggedOut);
Logs().i('User is not logged in.');
_initLock = false;
onInitStateChanged?.call(InitState.finished);
return;
}
@ -2065,6 +2082,7 @@ class Client extends MatrixApi {
await encryption?.dispose();
_encryption = null;
}
onInitStateChanged?.call(InitState.settingUpEncryption);
await encryption?.init(olmAccount);
final database = this.database;
@ -2112,6 +2130,7 @@ class Client extends MatrixApi {
// ignore: deprecated_member_use_from_same_package
presences.clear();
if (waitUntilLoadCompletedLoaded) {
onInitStateChanged?.call(InitState.loadingData);
await userDeviceKeysLoading;
await roomsLoading;
await _accountDataLoading;
@ -2127,14 +2146,18 @@ class Client extends MatrixApi {
/// Timeout of 0, so that we don't see a spinner for 30 seconds.
firstSyncReceived = _sync(timeout: Duration.zero);
if (waitForFirstSync) {
onInitStateChanged?.call(InitState.waitingForFirstSync);
await firstSyncReceived;
}
onInitStateChanged?.call(InitState.finished);
return;
} on ClientInitPreconditionError {
onInitStateChanged?.call(InitState.error);
rethrow;
} catch (e, s) {
Logs().wtf('Client initialization failed', e, s);
onLoginStateChanged.addError(e, s);
onInitStateChanged?.call(InitState.error);
final clientInitException = ClientInitException(
e,
homeserver: homeserver,
@ -3728,6 +3751,7 @@ class Client extends MatrixApi {
}
Future<void> _migrateFromLegacyDatabase({
void Function(InitState)? onInitStateChanged,
void Function()? onMigration,
}) async {
Logs().i('Check legacy database for migration data...');
@ -3741,6 +3765,7 @@ class Client extends MatrixApi {
return;
}
Logs().i('Found data in the legacy database!');
onInitStateChanged?.call(InitState.migratingDatabase);
onMigration?.call();
_id = migrateClient['client_id'];
final tokenExpiresAtMs =
@ -3858,6 +3883,7 @@ class Client extends MatrixApi {
return init(
waitForFirstSync: false,
waitUntilLoadCompletedLoaded: false,
onInitStateChanged: onInitStateChanged,
);
}
}
@ -3958,3 +3984,30 @@ class _EventPendingDecryption {
_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,
}

View File

@ -82,15 +82,26 @@ void main() {
databaseBuilder: getDatabase,
);
expect(client.isLogged(), false);
await client.init();
final Set<InitState> initStates = {};
await client.init(onInitStateChanged: initStates.add);
expect(client.isLogged(), false);
expect(initStates, {InitState.initializing, InitState.finished});
initStates.clear();
await client.login(
LoginType.mLoginPassword,
token: 'abcd',
identifier:
AuthenticationUserIdentifier(user: '@test:fakeServer.notExisting'),
deviceId: 'GHTYAJCE',
onInitStateChanged: initStates.add,
);
expect(initStates, {
InitState.initializing,
InitState.settingUpEncryption,
InitState.loadingData,
InitState.waitingForFirstSync,
InitState.finished,
});
expect(client.isLogged(), true);
@ -1439,7 +1450,14 @@ void main() {
databaseBuilder: getDatabase,
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));
expect(hiveClient.isLogged(), true);
await hiveClient.dispose(closeDatabase: false);