Account Settings View
We include many basic account-related features that 99% of the apps need anyways. Is also styled to look like the native account settings in iOS. Cool.
This screeds includes following features:
- Changing Account Name - Change the user's name
- Changing Password - Allowing the user to change their password (not applicable Signed in with Apple users)
- Account Deletion - Allowing the user to delete their account
- Signing Out - Allowing the user to sign out
We'll walk through each piece of functionality in the following sections.
Changing Account Name
The user can change their account name by tapping on the "Change Name" cell. This will present an alert where the user can enter their new name.
This calls the newDisplayName()
function of the DB
object.
public struct AccountSettingsView: View {
// ...
@EnvironmentObject var db: DB
@State private var showNewNameAlert = false
@State private var newName = ""
// ...
public var body: some View {
List {
// ... account settings header (image, name, email)
Section {
Button("Change Name") {
showNewNameAlert = true
}
.alert("Enter your new account name", isPresented: $showNewNameAlert) {
TextField(/* ... */, text: $newName)
Button("OK") {
// ...
await db.newDisplayName(newName)
// ...
}
// ... cancel button
}
// ... change password, delete account, sign out
}
}
}
}
Changing Profile Picture
This is actually just a placeholder PhotosPicker
element that you can repurpose for your own needs.
Pretty much only social apps require a feature like this, which is why we didn't include it out of the box.
Changing Password
The user can change their password by tapping on the "Change Password" cell.
Because this is a sensitive operation, a re-authentication sheet will appear (ReAuthSheet
)
prompting the user to enter their current password.
After this a sheet will appear where the user can enter their new password. After the user has entered their new password,
the setNewPassword()
function of the DB
object will be called.
(Note that because of the way iOS handles password fields, the keyboard and the password field is hidden in the GIF below.)
public struct AccountSettingsView: View {
// ...
@EnvironmentObject var db: DB
@State private var newPasswordSheetRef = false
@State private var reAuthSheetRef = false
// ...
public var body: some View {
List {
// ... account settings header (image, name, email)
Section {
// ...
if db.currentUserProvider == .email {
Button("Change Password") {
// ...
// show sheet to re-authenticate
showReAuthSheet(db: db, reAuthSheetRef: $reAuthSheetRef) { result in
switch result {
case .success: // on success, hide re-auth sheet and show password sheet after 0.25s
dismissReAuthSheet(reAuthSheetRef: $reAuthSheetRef)
Task {
try await Task.sleep(for: .seconds(0.25))
setShowPasswordSheet(true)
}
case .canceled: // on cancel, hide re-auth sheet
dismissReAuthSheet(reAuthSheetRef: $reAuthSheetRef)
case .forgotPassword:
// ... show password reset sheet
}
}
}
}
// ...
}
// ...
}
}
func setShowPasswordSheet(_ show: Bool) {
// ... show/hide NewPasswordView in a slide over card
}
}
struct NewPasswordView: View {
@EnvironmentObject var db: DB
// ...
public var body: some View {
VStack {
// ...
if let user = db.currentUser {
EmailInputFields(
// ...
continueAction: { email, password in
// ...
await db.setNewPassword(password)
// ...
})
} else {
// ...
}
// ...
}
// ...
}
}
Account Deletion
The user can change delete their accoutn by tapping on the "Delete Account" cell.
This is a destructive action, so after clicking on the button, we show a confirmation dialog will appear, asking the user to confirm that they want to delete their account.
Then, because this is a sensitive operation, a re-authentication sheet will appear (ReAuthSheet
)
prompting the user to enter their current password (or to sign in with Apple again).
(Note that because of the way iOS handles password fields, the keyboard and the password field is hidden in the GIF below.)
public struct AccountSettingsView: View {
// ...
@EnvironmentObject var db: DB
@State private var showAccountDeleteDialog = false
@State private var reAuthSheetRef = false
// ...
public var body: some View {
List {
// ... account settings header (image, name, email)
Section {
// ... change name button
// ... photos picker
// ... change password button
Button("Delete Account", role: .destructive) {
// ...
showAccountDeleteDialog = true
}
.confirmationDialog(
"Are you sure you want to delete your Account?", isPresented: $showAccountDeleteDialog
) {
Button("Confirm Account Deletion", role: .destructive) {
// show sheet to re-authenticate
showReAuthSheet(db: db, reAuthSheetRef: $reAuthSheetRef) { result in
switch result {
case .success: // on success, hide re-auth sheet and show password sheet after delay
// ...
await Task.sleep(for: .seconds(0.5))
await db.deleteUser()
// ...
dismissReAuthSheet(reAuthSheetRef: $reAuthSheetRef)
case .canceled: // on cancel, hide re-auth sheet
dismissReAuthSheet(reAuthSheetRef: $reAuthSheetRef)
case .forgotPassword:
// ... show password reset sheet
}
}
}
}
// ... sign out button
}
}
// ...
}
// ...
}
Signing Out
When the user signs out, we simply call the signOut()
function from the DB
object, which also navigates us back to the app settings screen.