mirror of
https://github.com/ProtonMail/ios-mail.git
synced 2026-06-14 09:54:45 +00:00
ET-2530 Make migration work seamlessly while offline
This commit is contained in:
@@ -119,6 +119,11 @@ private struct RootView: View {
|
||||
|
||||
case .activeSessionTransition:
|
||||
EmptyView()
|
||||
case .waitingForSessionInitialization:
|
||||
OperationInProgressView(
|
||||
text: nil,
|
||||
toast: .error(message: L10n.Session.initializationDifficulties.string)
|
||||
)
|
||||
}
|
||||
}
|
||||
.transition(.opacity)
|
||||
@@ -132,7 +137,7 @@ private struct RootView: View {
|
||||
case .checkingIfMigrationIsNeeded:
|
||||
EmptyView()
|
||||
case .inProgress:
|
||||
MigrationInProgressView()
|
||||
OperationInProgressView(text: L10n.LegacyMigration.migrationInProgress, toast: nil)
|
||||
case .pinRequired(let errorFromLatestAttempt):
|
||||
PINLockScreen(error: .constant(errorFromLatestAttempt)) { output in
|
||||
switch output {
|
||||
@@ -154,13 +159,26 @@ private struct RootView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private struct MigrationInProgressView: View {
|
||||
private struct OperationInProgressView: View {
|
||||
let text: LocalizedStringResource?
|
||||
let toast: Toast?
|
||||
|
||||
var body: some View {
|
||||
ZStack(alignment: .center) {
|
||||
Color.clear
|
||||
|
||||
ProgressView() {
|
||||
Text(L10n.LegacyMigration.migrationInProgress)
|
||||
if let text {
|
||||
Text(text)
|
||||
}
|
||||
}
|
||||
|
||||
if let toast {
|
||||
VStack {
|
||||
Spacer()
|
||||
|
||||
ToastView(model: toast) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2605,6 +2605,9 @@
|
||||
"Protection" : {
|
||||
"comment" : "Protection setting title in app settings."
|
||||
},
|
||||
"Proton Mail needs to connect to the server to finish initialization. Please ensure you have a good internet connection." : {
|
||||
"comment" : "Error when the connection fails during session initialization."
|
||||
},
|
||||
"Provided value is not a valid PIN" : {
|
||||
"comment" : "Error message when setting up PIN"
|
||||
},
|
||||
|
||||
@@ -23,6 +23,7 @@ struct ApplicationServices {
|
||||
var enterBackgroundServices: [ApplicationServiceDidEnterBackground] = []
|
||||
var terminateServices: [ApplicationServiceTerminate] = []
|
||||
|
||||
@MainActor
|
||||
func setUp() {
|
||||
setUpServices.forEach { $0.setUpService() }
|
||||
}
|
||||
@@ -41,6 +42,7 @@ struct ApplicationServices {
|
||||
}
|
||||
|
||||
protocol ApplicationServiceSetUp {
|
||||
@MainActor
|
||||
func setUpService()
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ final class AppContext: Sendable, ObservableObject {
|
||||
self.dependencies = dependencies
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private func start() throws {
|
||||
AppLogger.log(message: "AppContext.start", category: .appLifeCycle)
|
||||
|
||||
@@ -87,12 +88,7 @@ final class AppContext: Sendable, ObservableObject {
|
||||
setupAccountBindings()
|
||||
|
||||
if let currentSession = accountAuthCoordinator.primaryAccountSignedInSession() {
|
||||
switch mailSession.userContextFromSession(session: currentSession) {
|
||||
case .ok(let newUserSession):
|
||||
withAnimation { sessionState = .activeSession(session: newUserSession) }
|
||||
case .error(let error):
|
||||
throw error
|
||||
}
|
||||
setupActiveUserSession(session: currentSession)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,9 +123,26 @@ extension AppContext: AccountAuthDelegate {
|
||||
|
||||
@MainActor
|
||||
private func setupActiveUserSession(session: StoredSession) {
|
||||
let start = ContinuousClock.now
|
||||
|
||||
switch mailSession.userContextFromSession(session: session) {
|
||||
case .ok(let newUserSession):
|
||||
withAnimation { self.sessionState = .activeSession(session: newUserSession) }
|
||||
case .error(.other(.network)):
|
||||
AppLogger.log(
|
||||
message: "Failed to initialize session due to network error, will retry...",
|
||||
category: .userSessions,
|
||||
isError: true
|
||||
)
|
||||
|
||||
withAnimation { sessionState = .waitingForSessionInitialization }
|
||||
|
||||
Task {
|
||||
let minimumTimeBetweenRetries = Duration.seconds(5)
|
||||
let earliestNextAttemptTime = start + minimumTimeBetweenRetries
|
||||
try! await Task.sleep(until: earliestNextAttemptTime)
|
||||
setupActiveUserSession(session: session)
|
||||
}
|
||||
case .error(let error):
|
||||
AppLogger.log(error: error, category: .userSessions)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ enum SessionState: Equatable {
|
||||
case noSession
|
||||
case activeSession(session: MailUserSession)
|
||||
case activeSessionTransition
|
||||
case waitingForSessionInitialization
|
||||
|
||||
var userSession: MailUserSession? {
|
||||
guard case .activeSession(let session) = self else { return nil }
|
||||
@@ -34,6 +35,8 @@ enum SessionState: Equatable {
|
||||
return true
|
||||
case (.activeSessionTransition, .activeSessionTransition):
|
||||
return true
|
||||
case (.waitingForSessionInitialization, .waitingForSessionInitialization):
|
||||
return true
|
||||
case (.activeSession(let lhsSession), .activeSession(let rhsSession)):
|
||||
return lhsSession.sessionId() == rhsSession.sessionId()
|
||||
default:
|
||||
|
||||
@@ -22,7 +22,7 @@ extension SessionState {
|
||||
switch self {
|
||||
case .activeSession:
|
||||
true
|
||||
case .noSession, .activeSessionTransition:
|
||||
case .noSession, .activeSessionTransition, .waitingForSessionInitialization:
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -665,6 +665,13 @@ enum L10n {
|
||||
)
|
||||
}
|
||||
|
||||
enum Session {
|
||||
static let initializationDifficulties = LocalizedStringResource(
|
||||
"Proton Mail needs to connect to the server to finish initialization. Please ensure you have a good internet connection.",
|
||||
comment: "Error when the connection fails during session initialization."
|
||||
)
|
||||
}
|
||||
|
||||
enum Settings {
|
||||
enum App {
|
||||
static let title = LocalizedStringResource(
|
||||
|
||||
@@ -61,7 +61,7 @@ final class UserNotificationCenterDelegateTests {
|
||||
mailSession.onPrimaryAccountChanged = nil
|
||||
}
|
||||
|
||||
@Test
|
||||
@MainActor @Test
|
||||
func whenServicesAreSetUp_assignsItselfAsUserNotificationCenterDelegate() {
|
||||
sut.setUpService()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user