diff --git a/Monal/Classes/ChangePassword.swift b/Monal/Classes/ChangePassword.swift new file mode 100644 index 0000000000..2b99eee57b --- /dev/null +++ b/Monal/Classes/ChangePassword.swift @@ -0,0 +1,98 @@ +// +// ChangePassword.swift +// Monal +// +// Created by lissine on 2/8/2024. +// Copyright © 2024 monal-im.org. All rights reserved. +// + +struct ChangePassword: View { + @State private var oldPass = "" + @State private var newPass = "" + + @State private var showAlert = false + @State private var alertPrompt = AlertPrompt(dismissLabel: Text("Close")) + + @StateObject private var overlay = LoadingOverlayState() + + let accountID: NSNumber + + private func errorAlert(title: Text, message: Text = Text("")) { + alertPrompt.title = title + alertPrompt.message = message + showAlert = true + } + private func successAlert(title: Text, message: Text) { + alertPrompt.title = title + alertPrompt.message = message + showAlert = true + } + private func passwordChangeProcessing() { + guard let account = MLXMPPManager.sharedInstance().getEnabledAccount(forID: accountID) else { + errorAlert(title: Text("Account Offline"), message: Text("Please make sure you are connected before changing your password.")) + return + } + + guard MLXMPPManager.sharedInstance().isValidPassword(oldPass, forAccount: accountID) else { + errorAlert(title: Text("Wrong Password!"), message: Text("The current password is not correct.")) + return + } + + showLoadingOverlay(overlay, headlineView: Text("Changing Password"), descriptionView: Text("")) + + account.changePassword(newPass) { success, message in + DispatchQueue.main.async { + hideLoadingOverlay(overlay) + if success { + successAlert(title: Text("Success"), message: Text("The password has been changed")) + MLXMPPManager.sharedInstance().updatePassword(newPass, forAccount: accountID) + } else { + errorAlert(title: Text("Error"), message: Text(message ?? "Could not change the password")) + } + + } + } + + } + + var body: some View { + + Form { + Section(header: Text("Enter your new password. Passwords may not be empty. They may also be governed by server or company policies.")) { +#if IS_QUICKSY + TextField("Current Password", text: $oldPass) + .textInputAutocapitalization(.never) + .disableAutocorrection(true) + .onAppear { + oldPass = MLXMPPManager.sharedInstance().getPasswordForAccount(accountID) + } +#else + SecureField("Current Password", text: $oldPass) +#endif + SecureField("New Password", text: $newPass) + } + + Section { + Button(action: passwordChangeProcessing) { + Text("Change Password") + .frame(maxWidth: .infinity, alignment: .center) + } + .disabled(oldPass.isEmpty || newPass.isEmpty) + .alert( + alertPrompt.title, + isPresented: $showAlert + ) { + Button("Close") { + } + } message: { + alertPrompt.message + } + + } + } + .navigationTitle("Change Password") + .navigationBarTitleDisplayMode(NavigationBarItem.TitleDisplayMode.inline) + .addLoadingOverlay(overlay) + + } +} diff --git a/Monal/Classes/MLPasswordChangeTableViewController.h b/Monal/Classes/MLPasswordChangeTableViewController.h deleted file mode 100644 index ed5fe24ec2..0000000000 --- a/Monal/Classes/MLPasswordChangeTableViewController.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// MLPasswordChangeTableViewController.h -// Monal -// -// Created by Anurodh Pokharel on 5/22/19. -// Copyright © 2019 Monal.im. All rights reserved. -// - -#import -#import "MLConstants.h" -#import "xmpp.h" -#import "MLButtonCell.h" -#import "MLTextInputCell.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface MLPasswordChangeTableViewController : UITableViewController - -@property (nonatomic, strong) xmpp *xmppAccount; --(IBAction) changePress:(id)sender; - -@end - - -NS_ASSUME_NONNULL_END diff --git a/Monal/Classes/MLPasswordChangeTableViewController.m b/Monal/Classes/MLPasswordChangeTableViewController.m deleted file mode 100644 index 0460b2d31d..0000000000 --- a/Monal/Classes/MLPasswordChangeTableViewController.m +++ /dev/null @@ -1,200 +0,0 @@ -// -// MLPasswordChangeTableViewController.m -// Monal -// -// Created by Anurodh Pokharel on 5/22/19. -// Copyright © 2019 Monal.im. All rights reserved. -// - -#import "MLPasswordChangeTableViewController.h" -#import "MBProgressHUD.h" -#import "MLXMPPManager.h" - - -@interface MLPasswordChangeTableViewController () -@property (nonatomic, weak) MLTextInputCell* passwordOld; -@property (nonatomic, weak) MLTextInputCell* passwordNew; -@property (nonatomic, strong) MBProgressHUD* progress; -@end - -@implementation MLPasswordChangeTableViewController - --(void) closeView -{ - [self dismissViewControllerAnimated:YES completion:nil]; -} - --(IBAction) changePress:(id)sender -{ - if(!self.xmppAccount) - { - UIAlertController* messageAlert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"No connected accounts", @"") message:NSLocalizedString(@"Please make sure you are connected before changing your password.", @"") preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction* closeAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Close", @"") style:UIAlertActionStyleCancel handler:^(UIAlertAction* action __unused) {}]; - [messageAlert addAction:closeAction]; - - [self presentViewController:messageAlert animated:YES completion:nil]; - } - else - { - if([self.passwordNew getText].length > 0 && [self.passwordOld getText] > 0) - { - if([[MLXMPPManager sharedInstance] isValidPassword:[self.passwordOld getText] forAccount:self.xmppAccount.accountID] == NO) - { - UIAlertController* messageAlert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Invalid Password!", @"") message:NSLocalizedString(@"The current password is not correct.", @"") preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction* closeAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Close", @"") style:UIAlertActionStyleCancel handler:^(UIAlertAction* action __unused) {}]; - [messageAlert addAction:closeAction]; - - [self presentViewController:messageAlert animated:YES completion:nil]; - return; - } - - self.progress = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; - self.progress.label.text = NSLocalizedString(@"Changing Password", @""); - self.progress.mode = MBProgressHUDModeIndeterminate; - self.progress.removeFromSuperViewOnHide = YES; - self.progress.hidden = NO; - - [self.xmppAccount changePassword:[self.passwordNew getText] withCompletion:^(BOOL success, NSString* message) { - dispatch_async(dispatch_get_main_queue(), ^{ - self.progress.hidden = YES; - NSString* title = NSLocalizedString(@"Error", @""); - NSString* displayMessage = message; - if(success == YES) { - title = NSLocalizedString(@"Success", @""); - displayMessage = NSLocalizedString(@"The password has been changed", @""); - - [[MLXMPPManager sharedInstance] updatePassword:[self.passwordNew getText] forAccount:self.xmppAccount.accountID]; - } else { - if(displayMessage.length == 0) displayMessage = NSLocalizedString(@"Could not change the password", @""); - } - - UIAlertController* messageAlert = [UIAlertController alertControllerWithTitle:title message:displayMessage preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction* closeAction =[UIAlertAction actionWithTitle:NSLocalizedString(@"Close", @"") style:UIAlertActionStyleCancel handler:^(UIAlertAction* action __unused) { - - }]; - [messageAlert addAction:closeAction]; - - [self presentViewController:messageAlert animated:YES completion:nil]; - }); - }]; - } - else - { - UIAlertController *messageAlert =[UIAlertController alertControllerWithTitle:NSLocalizedString(@"Error", @"") message:NSLocalizedString(@"Password cannot be empty", @"") preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction* closeAction =[UIAlertAction actionWithTitle:NSLocalizedString(@"Close", @"") style:UIAlertActionStyleCancel handler:^(UIAlertAction* action __unused) { - - }]; - [messageAlert addAction:closeAction]; - - [self presentViewController:messageAlert animated:YES completion:nil]; - - } - - } -} - -#pragma mark - textfield delegate - -- (BOOL)textFieldShouldReturn:(UITextField *)textField -{ - [textField resignFirstResponder]; - - return YES; -} - - -- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { - - return YES; -} - - -#pragma mark View life cycle - --(void) viewDidLoad -{ - [super viewDidLoad]; - self.navigationItem.title=NSLocalizedString(@"Change Password", @""); - [self.tableView registerNib:[UINib nibWithNibName:@"MLTextInputCell" - bundle:[NSBundle mainBundle]] - forCellReuseIdentifier:@"TextCell"]; -} - --(void) viewWillAppear:(BOOL)animated -{ - [super viewWillAppear:animated]; - -} - -#pragma mark tableview datasource delegate - --(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView -{ - return 2; -} - -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section -{ - if(section == 0) - return NSLocalizedString(@"Enter your new password. Passwords may not be empty. They may also be governed by server or company policies.",@ ""); - else - return nil; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section -{ - NSInteger toreturn = 0; - switch (section) { - case 0: - toreturn = 2; - break; - case 1: - toreturn = 1; - break; - - default: - break; - } - - return toreturn; -} - -- (UITableViewCell*) tableView:(UITableView*) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath -{ - if(indexPath.section == 0) - { - MLTextInputCell* textCell = [tableView dequeueReusableCellWithIdentifier:@"TextCell"]; - if(indexPath.row == 0) - { -#ifdef IS_QUICKSY - [textCell initTextCell:[[MLXMPPManager sharedInstance] getPasswordForAccount:self.xmppAccount.accountID] andPlaceholder:NSLocalizedString(@"Current Password", @"") andDelegate:self]; -#else - [textCell initPasswordCell:[[MLXMPPManager sharedInstance] getPasswordForAccount:self.xmppAccount.accountID] andPlaceholder:NSLocalizedString(@"Current Password", @"") andDelegate:self]; -#endif - self.passwordOld = textCell; - } - else if(indexPath.row == 1) - { - [textCell initPasswordCell:nil andPlaceholder:NSLocalizedString(@"New Password", @"") andDelegate:self]; - self.passwordNew = textCell; - } - else - { - unreachable(); - } - return textCell; - } - else - return [tableView dequeueReusableCellWithIdentifier:@"addButton"]; -} - -#pragma mark tableview delegate -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ - -} - - - - -@end diff --git a/Monal/Classes/SwiftuiHelpers.swift b/Monal/Classes/SwiftuiHelpers.swift index f02f38cc1c..4f34a5f6f5 100644 --- a/Monal/Classes/SwiftuiHelpers.swift +++ b/Monal/Classes/SwiftuiHelpers.swift @@ -736,7 +736,14 @@ class SwiftuiInterface : NSObject { } return host } - + + @objc + func makeChangePasswordView(for accountID: NSNumber) -> UIViewController { + let host = UIHostingController(rootView:AnyView(EmptyView())) + host.rootView = AnyView(ChangePassword(accountID: accountID)) + return host + } + @objc func makeAccountRegistration(_ registerData: [String:AnyObject]?) -> UIViewController { let delegate = SheetDismisserProtocol() diff --git a/Monal/Classes/XMPPEdit.m b/Monal/Classes/XMPPEdit.m index ca806977fe..7ba607bab6 100644 --- a/Monal/Classes/XMPPEdit.m +++ b/Monal/Classes/XMPPEdit.m @@ -12,7 +12,6 @@ #import "MLBlockedUsersTableViewController.h" #import "MLButtonCell.h" #import "MLImageManager.h" -#import "MLPasswordChangeTableViewController.h" #import "MLSwitchCell.h" #import "MLOMEMO.h" #import "MLNotificationQueue.h" @@ -829,9 +828,11 @@ -(void) tableView:(UITableView*) tableView didSelectRowAtIndexPath:(NSIndexPath* { switch(newIndexPath.row) { - case SettingsChangePasswordRow: - [self performSegueWithIdentifier:@"showPassChange" sender:self]; + case SettingsChangePasswordRow: { + UIViewController* changePasswordView = [[SwiftuiInterface new] makeChangePasswordViewFor:self.accountID]; + [self showDetailViewController:changePasswordView sender:self]; break; + } case SettingsOmemoKeysRow: { UIViewController* ownOmemoKeysView; xmpp* xmppAccount = [[MLXMPPManager sharedInstance] getEnabledAccountForID:self.accountID]; @@ -900,14 +901,6 @@ -(void) prepareForSegue:(UIStoryboardSegue*) segue sender:(id) sender MLBlockedUsersTableViewController* blockedUsers = (MLBlockedUsersTableViewController*)segue.destinationViewController; blockedUsers.xmppAccount = xmppAccount; } - else if([segue.identifier isEqualToString:@"showPassChange"]) - { - if(self.jid && self.accountID) - { - MLPasswordChangeTableViewController* pwchange = (MLPasswordChangeTableViewController*)segue.destinationViewController; - pwchange.xmppAccount = [[MLXMPPManager sharedInstance] getEnabledAccountForID:self.accountID]; - } - } } #pragma mark - text input fielddelegate diff --git a/Monal/Monal.xcodeproj/project.pbxproj b/Monal/Monal.xcodeproj/project.pbxproj index 2b81d1c85a..ee0cb3d28b 100644 --- a/Monal/Monal.xcodeproj/project.pbxproj +++ b/Monal/Monal.xcodeproj/project.pbxproj @@ -43,7 +43,6 @@ 26AA70152146BBB900598605 /* ShareViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 26AA70142146BBB900598605 /* ShareViewController.m */; }; 26AA70182146BBB900598605 /* iosShare.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 26AA70162146BBB900598605 /* iosShare.storyboard */; }; 26AA701C2146BBB900598605 /* shareSheet.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 26AA70112146BBB800598605 /* shareSheet.appex */; platformFilter = ios; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - 26AAAADC2295742500200433 /* MLPasswordChangeTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 26AAAAD92295742400200433 /* MLPasswordChangeTableViewController.m */; }; 26AAE285179F7B0200271345 /* MLSettingCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 26AAE284179F7B0200271345 /* MLSettingCell.m */; }; 26B0CA8921AE2E3C0080B133 /* MLSoundsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 26B0CA8821AE2E3C0080B133 /* MLSoundsTableViewController.m */; }; 26B0CA8B21AE410E0080B133 /* AlertSounds in Resources */ = {isa = PBXBuildFile; fileRef = 26B0CA8A21AE410E0080B133 /* AlertSounds */; }; @@ -218,6 +217,7 @@ C1F5C7AF2777638B0001F295 /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = C1F5C7AE2777638B0001F295 /* OrderedCollections */; }; D09B51F62C7F30DD008D725B /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 26B2A4BA1B73061400272E63 /* Images.xcassets */; }; D0FA79B12C7E5C7400216D2A /* ServerDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA79B02C7E5C7400216D2A /* ServerDetails.swift */; }; + D0FE3F542C5C56ED007AAD23 /* ChangePassword.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FE3F532C5C56ED007AAD23 /* ChangePassword.swift */; }; D7E74AF213445E39318BC648 /* Pods_MonalUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29250DA62DD2322383585B2B /* Pods_MonalUITests.framework */; }; E89DD32525C6626400925F62 /* MLFileTransferDataCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E89DD32025C6626300925F62 /* MLFileTransferDataCell.m */; }; E89DD32625C6626400925F62 /* MLFileTransferVideoCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E89DD32125C6626300925F62 /* MLFileTransferVideoCell.m */; }; @@ -411,8 +411,6 @@ 26AA70172146BBB900598605 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/iosShare.storyboard; sourceTree = ""; }; 26AA70192146BBB900598605 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 26AA70222146E2B900598605 /* shareSheet.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = shareSheet.entitlements; sourceTree = ""; }; - 26AAAAD82295742400200433 /* MLPasswordChangeTableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MLPasswordChangeTableViewController.h; sourceTree = ""; }; - 26AAAAD92295742400200433 /* MLPasswordChangeTableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MLPasswordChangeTableViewController.m; sourceTree = ""; }; 26AAE283179F7B0200271345 /* MLSettingCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLSettingCell.h; sourceTree = ""; }; 26AAE284179F7B0200271345 /* MLSettingCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLSettingCell.m; sourceTree = ""; }; 26ABE9FB494A9E7F3044C695 /* Pods-MonalUITests.appstore-quicksy.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MonalUITests.appstore-quicksy.xcconfig"; path = "Target Support Files/Pods-MonalUITests/Pods-MonalUITests.appstore-quicksy.xcconfig"; sourceTree = ""; }; @@ -761,6 +759,7 @@ C1F5C7A82775DA000001F295 /* MLContactSoftwareVersionInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MLContactSoftwareVersionInfo.m; sourceTree = ""; }; C1F5C7AB2777621B0001F295 /* ContactResources.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactResources.swift; sourceTree = ""; }; D0FA79B02C7E5C7400216D2A /* ServerDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerDetails.swift; sourceTree = ""; }; + D0FE3F532C5C56ED007AAD23 /* ChangePassword.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangePassword.swift; sourceTree = ""; }; D310A8387B2EB10761312F77 /* Pods-NotificaionService.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificaionService.appstore.xcconfig"; path = "Target Support Files/Pods-NotificaionService/Pods-NotificaionService.appstore.xcconfig"; sourceTree = ""; }; D8D2595B2BE453296E59F1AF /* Pods-MonalUITests.appstore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MonalUITests.appstore.xcconfig"; path = "Target Support Files/Pods-MonalUITests/Pods-MonalUITests.appstore.xcconfig"; sourceTree = ""; }; DC5DA2C9782510B3433FD50D /* Pods-monalxmpp.beta.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-monalxmpp.beta.xcconfig"; path = "Target Support Files/Pods-monalxmpp/Pods-monalxmpp.beta.xcconfig"; sourceTree = ""; }; @@ -1052,11 +1051,10 @@ 2636C43E177BD58C001CA71F /* XMPPEdit.m */, 262AEFE620AE756800498F82 /* MLMAMPrefTableViewController.h */, 262AEFE720AE756800498F82 /* MLMAMPrefTableViewController.m */, - 26AAAAD82295742400200433 /* MLPasswordChangeTableViewController.h */, - 26AAAAD92295742400200433 /* MLPasswordChangeTableViewController.m */, C1B1982425AB31B800D5028E /* MLBlockedUsersTableViewController.h */, C1B1982525AB31B800D5028E /* MLBlockedUsersTableViewController.m */, D0FA79B02C7E5C7400216D2A /* ServerDetails.swift */, + D0FE3F532C5C56ED007AAD23 /* ChangePassword.swift */, ); name = Accounts; sourceTree = ""; @@ -2083,6 +2081,7 @@ 84E55E7D2964424E003E191A /* ActiveChatsViewController.m in Sources */, C1E8A7F72B8E47C300760220 /* EditGroupSubject.swift in Sources */, 263DFAC32187D0E00038E716 /* MLLinkCell.m in Sources */, + D0FE3F542C5C56ED007AAD23 /* ChangePassword.swift in Sources */, 3D65B78D27234B74005A30F4 /* ContactDetails.swift in Sources */, E89DD32525C6626400925F62 /* MLFileTransferDataCell.m in Sources */, E89DD32825C6626400925F62 /* MLFileTransferTextCell.m in Sources */, @@ -2125,7 +2124,6 @@ 3D5A91422842B4AE008CE57E /* MemberList.swift in Sources */, 849248492AD4CEC400986C1A /* ZoomableContainer.swift in Sources */, 2644D4921FF0064C00F46AB5 /* MLChatImageCell.m in Sources */, - 26AAAADC2295742500200433 /* MLPasswordChangeTableViewController.m in Sources */, 8441EFF92921B53500E851E9 /* BackgroundSettings.swift in Sources */, 841898AC2957DBAD00FEC77D /* RichAlert.swift in Sources */, 840E23CA28ADA56900A7FAC9 /* MLUploadQueueCell.m in Sources */,