Verify Element X with an existing Element Classic account. (#5374)

* Read and import the secrets from ClassicAppAccounts.

* Record snapshots.

* Add some documentation, tidy up tests and fix the dismissal of the backup instructions.

* Workaround flakey tests (the fulfilments weren't always firing).

* Allow a custom Classic App deep link URL to be configured.
This commit is contained in:
Doug
2026-04-13 15:30:09 +01:00
committed by GitHub
parent 001a389f51
commit 7c812201cb
40 changed files with 947 additions and 103 deletions
@@ -13,6 +13,10 @@ struct AuthenticationClassicAppAccountView: View {
let classicAppAccount: ClassicAppAccount
var isLoadingAccount: Bool {
classicAppAccount.state.isServerSupported == nil || classicAppAccount.state.availableSecrets == nil
}
var body: some View {
FullscreenDialog(topPadding: 25, background: .gradient) {
VStack(spacing: 38) {
@@ -28,6 +32,11 @@ struct AuthenticationClassicAppAccountView: View {
}
.navigationBarTitleDisplayMode(.inline)
.alert(item: $context.alertInfo)
.sheet(isPresented: $context.showClassicAppBackupInstructions) {
AuthenticationClassicAppBackupInstructionsView(classicAppAccount: classicAppAccount) {
context.send(viewAction: .openClassicApp)
}
}
.introspect(.window, on: .supportedVersions) { window in
context.send(viewAction: .updateWindow(window))
}
@@ -73,15 +82,30 @@ struct AuthenticationClassicAppAccountView: View {
var buttons: some View {
VStack(spacing: 16) {
Button(L10n.actionContinue) {
context.send(viewAction: .continueWithClassic(classicAppAccount))
if isLoadingAccount {
Button {
context.send(viewAction: .continueWithClassic(classicAppAccount))
} label: {
Label {
Text(L10n.screenOnboardingCheckingAccount)
} icon: {
ProgressView()
.tint(.compound.iconOnSolidPrimary)
}
}
.buttonStyle(.compound(.primary))
.disabled(true)
} else {
Button(L10n.actionContinue) {
context.send(viewAction: .continueWithClassic(classicAppAccount))
}
.buttonStyle(.compound(.primary))
Button(L10n.commonOtherOptions) {
context.send(viewAction: .otherOptions(classicAppAccount))
}
.buttonStyle(.compound(.secondary))
}
.buttonStyle(.compound(.primary))
Button(L10n.commonOtherOptions) {
context.send(viewAction: .otherOptions(classicAppAccount))
}
.buttonStyle(.compound(.secondary))
}
}
}
@@ -102,17 +126,30 @@ private extension ClassicAppAccount {
struct AuthenticationClassicAppAccountView_Previews: PreviewProvider { // Not Testable – snapshots generated by main screen.
static let viewModel = makeViewModel()
static let classicAppAccount = {
let account = ClassicAppAccount.mockDan
account.state.isServerSupported = true
account.state.availableSecrets = .complete
return account
}()
static var previews: some View {
ElementNavigationStack {
AuthenticationClassicAppAccountView(context: viewModel.context, classicAppAccount: classicAppAccount)
}
.previewDisplayName("Ready")
ElementNavigationStack {
AuthenticationClassicAppAccountView(context: viewModel.context, classicAppAccount: .mockDan)
}
.previewDisplayName("Loading")
}
static func makeViewModel() -> AuthenticationStartScreenViewModel {
AuthenticationStartScreenViewModel(authenticationService: AuthenticationService.mock,
provisioningParameters: nil,
isBugReportServiceEnabled: false,
appMediator: AppMediatorMock(),
appSettings: ServiceLocator.shared.settings,
mediaProvider: MediaProviderMock(configuration: .init()),
userIndicatorController: UserIndicatorControllerMock())