88import SwiftUI
99
1010struct PasswordEditView : View {
11- @Environment ( MessageBus . self) private var messageBus
1211 @Environment ( \. dismiss) private var dismiss
13- @State private var isUpdating = false
14- @State private var currentPassword : String = " "
15- @State private var password : String = " "
16- @State private var passwordConfirmation : String = " "
17- private var accountPasswordRepository : AccountPasswordRepositoryProtocol
12+ @State private var viewModel : PasswordEditViewModel
1813
19- init (
20- accountPasswordRepository: AccountPasswordRepositoryProtocol
21- ) {
22- self . accountPasswordRepository = accountPasswordRepository
23- }
24-
25- private var hasInvalidData : Bool {
26- if Utility . isBlank ( currentPassword) ||
27- Utility . isBlank ( password) ||
28- Utility . isBlank ( passwordConfirmation) {
29- return true
30- }
31-
32- if hasInvalidDataPassword {
33- return true
34- }
35-
36- return false
37- }
38-
39- private var hasInvalidDataPassword : Bool {
40- if Utility . isBlank ( password) {
41- return true
42- }
43-
44- if password. count < . minimumPasswordLength {
45- return true
46- }
47-
48- return false
14+ init ( viewModel: PasswordEditViewModel ) {
15+ self . _viewModel = State ( wrappedValue: viewModel)
4916 }
5017
5118 var body : some View {
5219 contentView
20+ . onChange ( of: viewModel. shouldDismiss) { _, shouldDismiss in
21+ if shouldDismiss {
22+ dismiss ( )
23+ }
24+ }
5325 }
5426}
5527
@@ -58,7 +30,7 @@ private extension PasswordEditView {
5830 var contentView : some View {
5931
6032 @ViewBuilder var contentView : some View {
61- if isUpdating {
33+ if viewModel . isBusy {
6234 LoadingView ( )
6335 } else {
6436 passwordEditView
@@ -71,7 +43,7 @@ private extension PasswordEditView {
7143 var passwordEditView : some View {
7244 Form {
7345 Section {
74- SecureField ( String . currentPassword, text: $currentPassword)
46+ SecureField ( String . currentPassword, text: $viewModel . currentPassword)
7547 . textContentType ( . password)
7648 . autocapitalization ( . none)
7749 . autocorrectionDisabled ( true )
@@ -82,35 +54,35 @@ private extension PasswordEditView {
8254 Text ( String . weNeedYourCurrentPassword)
8355 . font ( . uiFootnote)
8456 Text ( String . currentPasswordIsRequired)
85- . foregroundStyle ( Utility . isBlank ( currentPassword) ? . red : . clear)
57+ . foregroundStyle ( Utility . isBlank ( viewModel . currentPassword) ? . red : . clear)
8658 . font ( . uiFootnote)
8759 }
8860 }
8961 Section {
90- SecureField ( String . newPassword, text: $password)
62+ SecureField ( String . newPassword, text: $viewModel . password)
9163 . textContentType ( . password)
9264 . autocapitalization ( . none)
9365 . autocorrectionDisabled ( true )
9466 } header: {
9567 Text ( String . newPassword)
9668 } footer: {
9769 VStack ( alignment: . leading) {
98- Text ( " \( Int . minimumPasswordLength) characters minimum. " )
70+ Text ( " \( viewModel . minimumPasswordLength) characters minimum. " )
9971 . font ( . uiFootnote)
10072
101- if Utility . isBlank ( password) {
73+ if Utility . isBlank ( viewModel . password) {
10274 Text ( String . newPasswordIsRequired)
10375 . foregroundStyle ( . red)
10476 . font ( . uiFootnote)
105- } else if hasInvalidDataPassword {
77+ } else if viewModel . hasInvalidDataPassword {
10678 Text ( String . passwordIsInvalid)
10779 . foregroundStyle ( . red)
10880 . font ( . uiFootnote)
10981 }
11082 }
11183 }
11284 Section {
113- SecureField ( String . confirmNewPassword, text: $passwordConfirmation)
85+ SecureField ( String . confirmNewPassword, text: $viewModel . passwordConfirmation)
11486 . textContentType ( . password)
11587 . autocapitalization ( . none)
11688 . autocorrectionDisabled ( true )
@@ -119,46 +91,19 @@ private extension PasswordEditView {
11991 } footer: {
12092 Text ( String . confirmNewPasswordIsRequired)
12193 . font ( . uiFootnote)
122- . foregroundStyle ( Utility . isBlank ( passwordConfirmation) ? . red : . clear)
94+ . foregroundStyle ( Utility . isBlank ( viewModel . passwordConfirmation) ? . red : . clear)
12395 }
12496 }
12597 . navigationTitle ( String . updatePassword)
12698 . toolbar {
12799 ToolbarItem ( placement: . navigationBarTrailing) {
128100 Button {
129- updatePassword ( )
101+ viewModel . updatePassword ( )
130102 } label: {
131103 Text ( String . save)
132104 }
133- . disabled ( hasInvalidData)
134- }
135- }
136- }
137-
138- func updatePassword( ) {
139- let whitespacesAndNewlines = CharacterSet . whitespacesAndNewlines
140- let theCurrentPassword = currentPassword. trimmingCharacters ( in: whitespacesAndNewlines)
141- let thePassword = password. trimmingCharacters ( in: whitespacesAndNewlines)
142- let thePasswordConfirmation = passwordConfirmation. trimmingCharacters ( in: whitespacesAndNewlines)
143-
144- Task { @MainActor in
145- isUpdating = true
146-
147- do {
148- let updatePassword = UpdatePassword (
149- currentPassword: theCurrentPassword,
150- password: thePassword,
151- passwordConfirmation: thePasswordConfirmation
152- )
153-
154- try await accountPasswordRepository. update ( updatePassword: updatePassword)
155- messageBus. post ( message: Message ( level: . success, message: . passwordUpdated) )
156- dismiss ( )
157- } catch {
158- messageBus. post ( message: Message ( level: . error, message: error. localizedDescription, autoDismiss: false ) )
105+ . disabled ( viewModel. hasInvalidData)
159106 }
160-
161- isUpdating = false
162107 }
163108 }
164109}
0 commit comments