feat(settings): Preferences delete-account action
Danger subsection, confirmation dialog before calling users.delete (deleteAccount()), signs out locally on success. Closes out the Preferences page.
This commit is contained in:
@@ -36,6 +36,9 @@ struct SettingsView: View {
|
||||
@State private var languageErrorMessage: String?
|
||||
@State private var isSavingPreferences = false
|
||||
@State private var preferencesErrorMessage: String?
|
||||
@State private var isShowingDeleteAccountConfirmation = false
|
||||
@State private var isDeletingAccount = false
|
||||
@State private var deleteAccountErrorMessage: String?
|
||||
|
||||
/// Full Local Sync and cache-clearing both need a real connection to be
|
||||
/// safe — clearing while offline (or letting Full Local Sync think it
|
||||
@@ -302,9 +305,49 @@ struct SettingsView: View {
|
||||
.font(.caption)
|
||||
.foregroundStyle(.red)
|
||||
}
|
||||
|
||||
preferencesSubsection("Danger") {
|
||||
deleteAccountRow
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: 480, alignment: .leading)
|
||||
.task { await refreshProfile() }
|
||||
.confirmationDialog(
|
||||
"Delete Account?",
|
||||
isPresented: $isShowingDeleteAccountConfirmation,
|
||||
titleVisibility: .visible
|
||||
) {
|
||||
Button("Delete Account", role: .destructive) { Task { await deleteAccount() } }
|
||||
Button("Cancel", role: .cancel) {}
|
||||
} message: {
|
||||
Text("This is unrecoverable — everything associated with your account will be permanently deleted.")
|
||||
}
|
||||
}
|
||||
|
||||
private var deleteAccountRow: some View {
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
HStack {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text("Delete account")
|
||||
Text("You may delete your account at any time, note that this is unrecoverable.")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
Spacer()
|
||||
if isDeletingAccount {
|
||||
ProgressView().controlSize(.small)
|
||||
} else {
|
||||
Button("Delete…", role: .destructive) { isShowingDeleteAccountConfirmation = true }
|
||||
.buttonStyle(.bordered)
|
||||
.tint(.red)
|
||||
}
|
||||
}
|
||||
if let deleteAccountErrorMessage {
|
||||
Text(deleteAccountErrorMessage)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.red)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func preferencesSubsection<Content: View>(
|
||||
@@ -407,6 +450,18 @@ struct SettingsView: View {
|
||||
)
|
||||
}
|
||||
|
||||
private func deleteAccount() async {
|
||||
guard let apiClient = session.apiClient else { return }
|
||||
isDeletingAccount = true
|
||||
defer { isDeletingAccount = false }
|
||||
do {
|
||||
try await apiClient.deleteAccount()
|
||||
session.signOut()
|
||||
} catch {
|
||||
deleteAccountErrorMessage = outlineErrorMessage(error, fallback: "Couldn't delete your account.")
|
||||
}
|
||||
}
|
||||
|
||||
private func saveLanguage(_ code: String) async {
|
||||
guard code != session.userLanguage, let apiClient = session.apiClient, let userId = session.userId else { return }
|
||||
isSavingLanguage = true
|
||||
|
||||
Reference in New Issue
Block a user