ios: database error screens redesign (#5256)

* ios: database error screens redesign (wip)

* refactor

* remove code to simulate errors

* fix

* fix texts

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
This commit is contained in:
Diogo
2024-11-27 20:32:18 +00:00
committed by GitHub
parent ba7abcf6f7
commit 22d7db89d8
39 changed files with 169 additions and 102 deletions
@@ -11,6 +11,7 @@ import SimpleXChat
struct DatabaseErrorView: View {
@EnvironmentObject var m: ChatModel
@EnvironmentObject var theme: AppTheme
@State var status: DBMigrationResult
@State private var dbKey = ""
@State private var storedDBKey = kcDatabasePassword.get()
@@ -28,23 +29,39 @@ struct DatabaseErrorView: View {
}
@ViewBuilder private func databaseErrorView() -> some View {
VStack(alignment: .leading, spacing: 16) {
VStack(alignment: .center, spacing: 20) {
switch status {
case let .errorNotADatabase(dbFile):
if useKeychain && storedDBKey != nil && storedDBKey != "" {
titleText("Wrong database passphrase")
Text("Database passphrase is different from saved in the keychain.")
.font(.callout)
.foregroundColor(theme.colors.secondary)
.multilineTextAlignment(.center)
.padding(.horizontal, 25)
databaseKeyField(onSubmit: saveAndRunChat)
saveAndOpenButton()
fileNameText(dbFile)
Spacer()
VStack(spacing: 10) {
saveAndOpenButton()
fileNameText(dbFile)
}
} else {
titleText("Encrypted database")
Text("Database passphrase is required to open chat.")
.font(.callout)
.foregroundColor(theme.colors.secondary)
.multilineTextAlignment(.center)
.padding(.horizontal, 25)
.padding(.bottom, 5)
if useKeychain {
databaseKeyField(onSubmit: saveAndRunChat)
Spacer()
saveAndOpenButton()
} else {
databaseKeyField(onSubmit: { runChat() })
Spacer()
openChatButton()
}
}
@@ -52,73 +69,105 @@ struct DatabaseErrorView: View {
switch migrationError {
case let .upgrade(upMigrations):
titleText("Database upgrade")
Button("Upgrade and open chat") { runChat(confirmMigrations: .yesUp) }
fileNameText(dbFile)
migrationsText(upMigrations.map(\.upName))
Spacer()
VStack(spacing: 10) {
Button("Upgrade and open chat") {
runChat(confirmMigrations: .yesUp)
}.buttonStyle(OnboardingButtonStyle(isDisabled: false))
fileNameText(dbFile)
}
case let .downgrade(downMigrations):
titleText("Database downgrade")
Text("Warning: you may lose some data!").bold()
Button("Downgrade and open chat") { runChat(confirmMigrations: .yesUpDown) }
fileNameText(dbFile)
Text("Warning: you may lose some data!")
.bold()
.padding(.horizontal, 25)
.multilineTextAlignment(.center)
migrationsText(downMigrations)
Spacer()
VStack(spacing: 10) {
Button("Downgrade and open chat") {
runChat(confirmMigrations: .yesUpDown)
}.buttonStyle(OnboardingButtonStyle(isDisabled: false))
fileNameText(dbFile)
}
case let .migrationError(mtrError):
titleText("Incompatible database version")
fileNameText(dbFile)
Text("Error: ") + Text(mtrErrorDescription(mtrError))
fileNameText(dbFile, font: .callout)
errorView(Text(mtrErrorDescription(mtrError)))
}
case let .errorSQL(dbFile, migrationSQLError):
titleText("Database error")
fileNameText(dbFile)
Text("Error: \(migrationSQLError)")
fileNameText(dbFile, font: .callout)
errorView(Text("Error: \(migrationSQLError)"))
case .errorKeychain:
titleText("Keychain error")
Text("Cannot access keychain to save database password")
errorView(Text("Cannot access keychain to save database password"))
case .invalidConfirmation:
// this can only happen if incorrect parameter is passed
Text(String("Invalid migration confirmation")).font(.title)
titleText("Invalid migration confirmation")
errorView()
case let .unknown(json):
titleText("Database error")
Text("Unknown database error: \(json)")
errorView(Text("Unknown database error: \(json)"))
case .ok:
EmptyView()
}
if showRestoreDbButton {
Spacer().frame(height: 10)
Spacer()
Text("The attempt to change database passphrase was not completed.")
.multilineTextAlignment(.center)
.padding(.horizontal, 25)
.font(.footnote)
restoreDbButton()
}
}
.padding()
.padding(.horizontal, 25)
.padding(.top, 75)
.padding(.bottom, 25)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
.onAppear() { showRestoreDbButton = shouldShowRestoreDbButton() }
}
private func titleText(_ s: LocalizedStringKey) -> Text {
Text(s).font(.title)
private func titleText(_ s: LocalizedStringKey) -> some View {
Text(s).font(.largeTitle).bold().multilineTextAlignment(.center)
}
private func fileNameText(_ f: String) -> Text {
Text("File: \((f as NSString).lastPathComponent)")
private func fileNameText(_ f: String, font: Font = .caption) -> Text {
Text("File: \((f as NSString).lastPathComponent)").font(font)
}
private func migrationsText(_ ms: [String]) -> Text {
Text("Migrations: \(ms.joined(separator: ", "))")
private func migrationsText(_ ms: [String]) -> some View {
(Text("Migrations:").font(.subheadline) + Text(verbatim: "\n") + Text(ms.joined(separator: "\n")).font(.caption))
.multilineTextAlignment(.center)
.padding(.horizontal, 25)
}
private func databaseKeyField(onSubmit: @escaping () -> Void) -> some View {
PassphraseField(key: $dbKey, placeholder: "Enter passphrase…", valid: validKey(dbKey), onSubmit: onSubmit)
.padding(.vertical, 10)
.padding(.horizontal)
.background(
RoundedRectangle(cornerRadius: 10, style: .continuous)
.fill(Color(uiColor: .tertiarySystemFill))
)
}
private func saveAndOpenButton() -> some View {
Button("Save passphrase and open chat") {
saveAndRunChat()
}
.buttonStyle(OnboardingButtonStyle(isDisabled: false))
}
private func openChatButton() -> some View {
Button("Open chat") {
runChat()
}
.buttonStyle(OnboardingButtonStyle(isDisabled: false))
}
private func saveAndRunChat() {
@@ -192,8 +241,9 @@ struct DatabaseErrorView: View {
secondaryButton: .cancel()
))
} label: {
Text("Restore database backup").foregroundColor(.red)
Text("Restore database backup")
}
.buttonStyle(OnboardingButtonStyle(isDisabled: false))
}
private func restoreDb() {
@@ -208,6 +258,23 @@ struct DatabaseErrorView: View {
))
}
}
private func errorView(_ s: Text? = nil) -> some View {
VStack(spacing: 35) {
Image(systemName: "exclamationmark.triangle.fill")
.resizable()
.frame(width: 50, height: 50)
.foregroundColor(.red)
if let text = s {
text
.multilineTextAlignment(.center)
.font(.footnote)
}
}
.padding()
.frame(maxWidth: .infinity)
}
}
struct DatabaseErrorView_Previews: PreviewProvider {
@@ -4405,9 +4405,9 @@ This is your link for group %@!</source>
<target>Миграцията е завършена</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<target>Миграции: %@</target>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<target>Миграции:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -2235,8 +2235,8 @@
<source>Migration is completed</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -4253,9 +4253,9 @@ This is your link for group %@!</source>
<target>Přenesení dokončeno</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<target>Migrace: %@</target>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<target>Migrace:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -4558,9 +4558,9 @@ Das ist Ihr Link für die Gruppe %@!</target>
<target>Die Migration wurde abgeschlossen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<target>Migrationen: %@</target>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<target>Migrationen:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -2012,8 +2012,8 @@ Available in v5.1</source>
<source>Migration is completed</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -4600,9 +4600,9 @@ This is your link for group %@!</target>
<target>Migration is completed</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<target>Migrations: %@</target>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<target>Migrations:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -4558,9 +4558,9 @@ This is your link for group %@!</source>
<target>Migración completada</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<target>Migraciones: %@</target>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<target>Migraciones:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -4243,9 +4243,9 @@ This is your link for group %@!</source>
<target>Siirto on valmis</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<target>Siirrot: %@</target>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<target>Siirrot:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -4523,9 +4523,9 @@ Voici votre lien pour le groupe %@ !</target>
<target>La migration est terminée</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<target>Migrations : %@</target>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<target>Migrations :</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -2497,9 +2497,9 @@ Available in v5.1</source>
<target state="translated">ההעברה הושלמה</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve" approved="no">
<source>Migrations: %@</source>
<target state="translated">העברות: %@</target>
<trans-unit id="Migrations:" xml:space="preserve" approved="no">
<source>Migrations:</source>
<target state="translated">העברות:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve" approved="no">
@@ -4558,9 +4558,9 @@ Ez az Ön hivatkozása a(z) %@ csoporthoz!</target>
<target>Az átköltöztetés befejeződött</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<target>Átköltöztetések: %@</target>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<target>Átköltöztetések:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -4558,9 +4558,9 @@ Questo è il tuo link per il gruppo %@!</target>
<target>La migrazione è completata</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<target>Migrazioni: %@</target>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<target>Migrazioni:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -4269,9 +4269,9 @@ This is your link for group %@!</source>
<target>移行が完了しました</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<target>移行 %@</target>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<target>移行</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -4558,9 +4558,9 @@ Dit is jouw link voor groep %@!</target>
<target>Migratie is voltooid</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<target>Migraties: %@</target>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<target>Migraties:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -4548,9 +4548,9 @@ To jest twój link do grupy %@!</target>
<target>Migracja została zakończona</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<target>Migracje: %@</target>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<target>Migracje:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -2115,8 +2115,8 @@ Available in v5.1</source>
<source>Migration is completed</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -4558,9 +4558,9 @@ This is your link for group %@!</source>
<target>Перемещение данных завершено</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<target>Миграции: %@</target>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<target>Миграции:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -4226,9 +4226,9 @@ This is your link for group %@!</source>
<target>การโยกย้ายเสร็จสมบูรณ์</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<target>การย้ายข้อมูล: %@</target>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<target>การย้ายข้อมูล</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -4558,9 +4558,9 @@ Bu senin grup için bağlantın %@!</target>
<target>Geçiş tamamlandı</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<target>Geçişler: %@</target>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<target>Geçişler:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -4523,9 +4523,9 @@ This is your link for group %@!</source>
<target>Міграцію завершено</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<target>Міграції: %@</target>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<target>Міграції:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -4523,9 +4523,9 @@ This is your link for group %@!</source>
<target>迁移完成</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve">
<source>Migrations: %@</source>
<target>迁移%@</target>
<trans-unit id="Migrations:" xml:space="preserve">
<source>Migrations:</source>
<target>迁移</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Moderate" xml:space="preserve">
@@ -4781,8 +4781,8 @@ Available in v5.1</source>
<target state="translated">訊息 &amp; 檔案</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrations: %@" xml:space="preserve" approved="no">
<source>Migrations: %@</source>
<trans-unit id="Migrations:" xml:space="preserve" approved="no">
<source>Migrations:</source>
<target state="translated">遷移:%@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
+1 -1
View File
@@ -2510,7 +2510,7 @@
"Migration is completed" = "Миграцията е завършена";
/* No comment provided by engineer. */
"Migrations: %@" = "Миграции: %@";
"Migrations:" = "Миграции:";
/* time unit */
"minutes" = "минути";
+1 -1
View File
@@ -2029,7 +2029,7 @@
"Migration is completed" = "Přenesení dokončeno";
/* No comment provided by engineer. */
"Migrations: %@" = "Migrace: %@";
"Migrations:" = "Migrace:";
/* time unit */
"minutes" = "minut";
+1 -1
View File
@@ -2984,7 +2984,7 @@
"Migration is completed" = "Die Migration wurde abgeschlossen";
/* No comment provided by engineer. */
"Migrations: %@" = "Migrationen: %@";
"Migrations:" = "Migrationen:";
/* time unit */
"minutes" = "Minuten";
+1 -1
View File
@@ -2984,7 +2984,7 @@
"Migration is completed" = "Migración completada";
/* No comment provided by engineer. */
"Migrations: %@" = "Migraciones: %@";
"Migrations:" = "Migraciones:";
/* time unit */
"minutes" = "minutos";
+1 -1
View File
@@ -2005,7 +2005,7 @@
"Migration is completed" = "Siirto on valmis";
/* No comment provided by engineer. */
"Migrations: %@" = "Siirrot: %@";
"Migrations:" = "Siirrot:";
/* time unit */
"minutes" = "minuuttia";
+1 -1
View File
@@ -2885,7 +2885,7 @@
"Migration is completed" = "La migration est terminée";
/* No comment provided by engineer. */
"Migrations: %@" = "Migrations : %@";
"Migrations:" = "Migrations :";
/* time unit */
"minutes" = "minutes";
+1 -1
View File
@@ -2984,7 +2984,7 @@
"Migration is completed" = "Az átköltöztetés befejeződött";
/* No comment provided by engineer. */
"Migrations: %@" = "Átköltöztetések: %@";
"Migrations:" = "Átköltöztetések:";
/* time unit */
"minutes" = "perc";
+1 -1
View File
@@ -2984,7 +2984,7 @@
"Migration is completed" = "La migrazione è completata";
/* No comment provided by engineer. */
"Migrations: %@" = "Migrazioni: %@";
"Migrations:" = "Migrazioni:";
/* time unit */
"minutes" = "minuti";
+1 -1
View File
@@ -2083,7 +2083,7 @@
"Migration is completed" = "移行が完了しました";
/* No comment provided by engineer. */
"Migrations: %@" = "移行 %@";
"Migrations:" = "移行";
/* time unit */
"minutes" = "分";
+1 -1
View File
@@ -2984,7 +2984,7 @@
"Migration is completed" = "Migratie is voltooid";
/* No comment provided by engineer. */
"Migrations: %@" = "Migraties: %@";
"Migrations:" = "Migraties:";
/* time unit */
"minutes" = "minuten";
+1 -1
View File
@@ -2957,7 +2957,7 @@
"Migration is completed" = "Migracja została zakończona";
/* No comment provided by engineer. */
"Migrations: %@" = "Migracje: %@";
"Migrations:" = "Migracje:";
/* time unit */
"minutes" = "minuty";
+1 -1
View File
@@ -2984,7 +2984,7 @@
"Migration is completed" = "Перемещение данных завершено";
/* No comment provided by engineer. */
"Migrations: %@" = "Миграции: %@";
"Migrations:" = "Миграции:";
/* time unit */
"minutes" = "минут";
+1 -1
View File
@@ -1948,7 +1948,7 @@
"Migration is completed" = "การโยกย้ายเสร็จสมบูรณ์";
/* No comment provided by engineer. */
"Migrations: %@" = "การย้ายข้อมูล: %@";
"Migrations:" = "การย้ายข้อมูล";
/* time unit */
"minutes" = "นาที";
+1 -1
View File
@@ -2984,7 +2984,7 @@
"Migration is completed" = "Geçiş tamamlandı";
/* No comment provided by engineer. */
"Migrations: %@" = "Geçişler: %@";
"Migrations:" = "Geçişler:";
/* time unit */
"minutes" = "dakikalar";
+1 -1
View File
@@ -2885,7 +2885,7 @@
"Migration is completed" = "Міграцію завершено";
/* No comment provided by engineer. */
"Migrations: %@" = "Міграції: %@";
"Migrations:" = "Міграції:";
/* time unit */
"minutes" = "хвилини";
+1 -1
View File
@@ -2885,7 +2885,7 @@
"Migration is completed" = "迁移完成";
/* No comment provided by engineer. */
"Migrations: %@" = "迁移%@";
"Migrations:" = "迁移";
/* time unit */
"minutes" = "分钟";