From 24555d7ac5847c2b60f5cfb532af74c9df6bd777 Mon Sep 17 00:00:00 2001 From: michaeldacanay Date: Mon, 12 Jun 2023 19:09:18 -0400 Subject: [PATCH 1/6] Add Settings page and icon to tab bar --- BlogSmart/BlogSmart.xcodeproj/project.pbxproj | 16 ++++-- .../BlogSmart/Base.lproj/Main.storyboard | 53 ++++++++++++++++--- .../Settings/SettingsViewController.swift | 29 ++++++++++ 3 files changed, 86 insertions(+), 12 deletions(-) create mode 100644 BlogSmart/BlogSmart/Settings/SettingsViewController.swift diff --git a/BlogSmart/BlogSmart.xcodeproj/project.pbxproj b/BlogSmart/BlogSmart.xcodeproj/project.pbxproj index 5362dd6..64f9aa5 100644 --- a/BlogSmart/BlogSmart.xcodeproj/project.pbxproj +++ b/BlogSmart/BlogSmart.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ A22881E429FB5DD2007F48B9 /* WriteViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A22881E329FB5DD2007F48B9 /* WriteViewController.swift */; }; A22881EA29FCC824007F48B9 /* GPTResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = A22881E929FCC824007F48B9 /* GPTResponse.swift */; }; A27AC8B829EC31450011E378 /* SignUpViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A27AC8B729EC31450011E378 /* SignUpViewController.swift */; }; + A2C1DA2D2A37D8D500A24C93 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2C1DA2C2A37D8D500A24C93 /* SettingsViewController.swift */; }; AF202F0929E889E600D18F2C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF202F0829E889E600D18F2C /* AppDelegate.swift */; }; AF202F0B29E889E600D18F2C /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF202F0A29E889E600D18F2C /* SceneDelegate.swift */; }; AF202F0D29E889E600D18F2C /* ReadViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF202F0C29E889E600D18F2C /* ReadViewController.swift */; }; @@ -22,7 +23,6 @@ AFA3139729FA22B4003719FE /* PostCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA3139629FA22B4003719FE /* PostCell.swift */; }; AFA3139929FA2A5B003719FE /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA3139829FA2A5B003719FE /* Post.swift */; }; AFAD94482A007BF900510528 /* DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFAD94472A007BF900510528 /* DetailViewController.swift */; }; - AFFB8AD72A37CA1E00EBD49B /* Keys.plist in Resources */ = {isa = PBXBuildFile; fileRef = AFFB8AD62A37CA1E00EBD49B /* Keys.plist */; }; BA1BA4F129EA503A00E13CDC /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA1BA4F029EA503A00E13CDC /* LoginViewController.swift */; }; BA1BA4F429EA534100E13CDC /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA1BA4F329EA534100E13CDC /* User.swift */; }; BA1BA4F729EA571700E13CDC /* ViewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA1BA4F629EA571700E13CDC /* ViewController+Extensions.swift */; }; @@ -33,6 +33,7 @@ A22881E329FB5DD2007F48B9 /* WriteViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WriteViewController.swift; sourceTree = ""; }; A22881E929FCC824007F48B9 /* GPTResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GPTResponse.swift; sourceTree = ""; }; A27AC8B729EC31450011E378 /* SignUpViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignUpViewController.swift; sourceTree = ""; }; + A2C1DA2C2A37D8D500A24C93 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; AF202F0529E889E600D18F2C /* BlogSmart.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BlogSmart.app; sourceTree = BUILT_PRODUCTS_DIR; }; AF202F0829E889E600D18F2C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; AF202F0A29E889E600D18F2C /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -44,7 +45,6 @@ AFA3139629FA22B4003719FE /* PostCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostCell.swift; sourceTree = ""; }; AFA3139829FA2A5B003719FE /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = ""; }; AFAD94472A007BF900510528 /* DetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailViewController.swift; sourceTree = ""; }; - AFFB8AD62A37CA1E00EBD49B /* Keys.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Keys.plist; sourceTree = ""; }; BA1BA4F029EA503A00E13CDC /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = ""; }; BA1BA4F329EA534100E13CDC /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; BA1BA4F629EA571700E13CDC /* ViewController+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ViewController+Extensions.swift"; sourceTree = ""; }; @@ -73,6 +73,14 @@ path = Write; sourceTree = ""; }; + A2C1DA2B2A37D8BE00A24C93 /* Settings */ = { + isa = PBXGroup; + children = ( + A2C1DA2C2A37D8D500A24C93 /* SettingsViewController.swift */, + ); + path = Settings; + sourceTree = ""; + }; AF202EFC29E889E600D18F2C = { isa = PBXGroup; children = ( @@ -92,6 +100,7 @@ AF202F0729E889E600D18F2C /* BlogSmart */ = { isa = PBXGroup; children = ( + A2C1DA2B2A37D8BE00A24C93 /* Settings */, AFAD94462A007BD500510528 /* Detail */, A22881E229FB5DBF007F48B9 /* Write */, AFA3139529FA2231003719FE /* Feed */, @@ -104,7 +113,6 @@ AF202F1129E889E800D18F2C /* Assets.xcassets */, AF202F1329E889E800D18F2C /* LaunchScreen.storyboard */, AF202F1629E889E800D18F2C /* Info.plist */, - AFFB8AD62A37CA1E00EBD49B /* Keys.plist */, ); path = BlogSmart; sourceTree = ""; @@ -222,7 +230,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - AFFB8AD72A37CA1E00EBD49B /* Keys.plist in Resources */, AF202F1529E889E800D18F2C /* LaunchScreen.storyboard in Resources */, AF202F1229E889E800D18F2C /* Assets.xcassets in Resources */, AF202F1029E889E600D18F2C /* Main.storyboard in Resources */, @@ -245,6 +252,7 @@ BA1BA4F929EA57F200E13CDC /* DateFormatter+Extensions.swift in Sources */, AF202F0929E889E600D18F2C /* AppDelegate.swift in Sources */, AFA3139729FA22B4003719FE /* PostCell.swift in Sources */, + A2C1DA2D2A37D8D500A24C93 /* SettingsViewController.swift in Sources */, BA1BA4F429EA534100E13CDC /* User.swift in Sources */, BA1BA4F729EA571700E13CDC /* ViewController+Extensions.swift in Sources */, AF202F0B29E889E600D18F2C /* SceneDelegate.swift in Sources */, diff --git a/BlogSmart/BlogSmart/Base.lproj/Main.storyboard b/BlogSmart/BlogSmart/Base.lproj/Main.storyboard index 1355cb0..cb60faf 100644 --- a/BlogSmart/BlogSmart/Base.lproj/Main.storyboard +++ b/BlogSmart/BlogSmart/Base.lproj/Main.storyboard @@ -3,7 +3,7 @@ - + @@ -440,7 +440,7 @@ These are everything a chocolate chip cookie should be. Crispy and chewy. Doughy - + @@ -451,7 +451,7 @@ These are everything a chocolate chip cookie should be. Crispy and chewy. Doughy - + @@ -463,8 +463,8 @@ These are everything a chocolate chip cookie should be. Crispy and chewy. Doughy - - + + @@ -474,7 +474,7 @@ These are everything a chocolate chip cookie should be. Crispy and chewy. Doughy + + + + + + + + + + + + diff --git a/BlogSmart/BlogSmart/SceneDelegate.swift b/BlogSmart/BlogSmart/SceneDelegate.swift index 0a061d2..71e329d 100644 --- a/BlogSmart/BlogSmart/SceneDelegate.swift +++ b/BlogSmart/BlogSmart/SceneDelegate.swift @@ -43,6 +43,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } + // go to ReadViewController private func login() { let storyboard = UIStoryboard(name: Constants.storyboardIdentifier, bundle: nil) self.window?.rootViewController = storyboard.instantiateViewController(withIdentifier: Constants.readNavigationControllerIdentifier) diff --git a/BlogSmart/BlogSmart/Settings/SettingsViewController.swift b/BlogSmart/BlogSmart/Settings/SettingsViewController.swift index f5738c4..d2eca13 100644 --- a/BlogSmart/BlogSmart/Settings/SettingsViewController.swift +++ b/BlogSmart/BlogSmart/Settings/SettingsViewController.swift @@ -6,24 +6,78 @@ // import UIKit +import ParseSwift class SettingsViewController: UIViewController { - + + @IBOutlet weak var username: UITextField! + @IBOutlet weak var email: UITextField! + @IBOutlet weak var password: UITextField! + + override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. + let user = User.current + username.placeholder = user?.username + email.placeholder = user?.email + password.placeholder = user?.password } - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. + @IBAction func onSave(_ sender: Any) { + // Retrieve the object from the database + if var currentUser = User.current { + if !email.text!.isEmpty { + if !isValidEmail(email.text!) { + showInvalidEmailAlert() + return + } + currentUser.email = email.text + } + + if !username.text!.isEmpty { + // Update the field + currentUser.username = username.text + } + + if !password.text!.isEmpty { + currentUser.password = password.text + } + + // Save the changes + currentUser.save { result in + switch result { + case .success(let updatedUser): + print("Field updated successfully: \(updatedUser)") + case .failure(let error): + print("Error updating field: \(error)") + } + } + } else { + print("No current user") + } + + if !email.text!.isEmpty || !username.text!.isEmpty || !password.text!.isEmpty { + // return to ReadViewController + NotificationCenter.default.post(name: Notification.Name("logout"), object: nil) + } + } - */ + + func isValidEmail(_ email: String) -> Bool { + let emailRegex = "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}" + let emailPredicate = NSPredicate(format: "SELF MATCHES %@", emailRegex) + return emailPredicate.evaluate(with: email) + } + + private func showInvalidEmailAlert() { + let alertController = UIAlertController(title: "Opps...", message: "The email provided is invalid.", preferredStyle: .alert) + let action = UIAlertAction(title: "OK", style: .default) + alertController.addAction(action) + present(alertController, animated: true) + } + + } From 14a8c6428d27af6b53b88499768ae7d9ef374167 Mon Sep 17 00:00:00 2001 From: michaeldacanay Date: Wed, 14 Jun 2023 21:33:01 -0400 Subject: [PATCH 3/6] center cursor for password field in account settings --- BlogSmart/BlogSmart/Base.lproj/Main.storyboard | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BlogSmart/BlogSmart/Base.lproj/Main.storyboard b/BlogSmart/BlogSmart/Base.lproj/Main.storyboard index be7577c..706f03c 100644 --- a/BlogSmart/BlogSmart/Base.lproj/Main.storyboard +++ b/BlogSmart/BlogSmart/Base.lproj/Main.storyboard @@ -602,7 +602,7 @@ These are everything a chocolate chip cookie should be. Crispy and chewy. Doughy - + From e98b448df4c91f5abbcbcec5e7829e4e18eeb036 Mon Sep 17 00:00:00 2001 From: michaeldacanay Date: Wed, 14 Jun 2023 21:50:55 -0400 Subject: [PATCH 4/6] Fix constraint warnings --- .../BlogSmart/Base.lproj/Main.storyboard | 54 +++++++++---------- BlogSmart/BlogSmart/Feed/PostCell.swift | 3 +- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/BlogSmart/BlogSmart/Base.lproj/Main.storyboard b/BlogSmart/BlogSmart/Base.lproj/Main.storyboard index 706f03c..b04bd73 100644 --- a/BlogSmart/BlogSmart/Base.lproj/Main.storyboard +++ b/BlogSmart/BlogSmart/Base.lproj/Main.storyboard @@ -34,20 +34,20 @@ - + - + - + - + @@ -439,6 +439,26 @@ These are everything a chocolate chip cookie should be. Crispy and chewy. Doughy + + + + + + + + + + + + + @@ -463,33 +483,13 @@ These are everything a chocolate chip cookie should be. Crispy and chewy. Doughy - - - - - - - - - - - - - - + @@ -577,7 +577,7 @@ These are everything a chocolate chip cookie should be. Crispy and chewy. Doughy - + @@ -591,7 +591,7 @@ These are everything a chocolate chip cookie should be. Crispy and chewy. Doughy - + diff --git a/BlogSmart/BlogSmart/Feed/PostCell.swift b/BlogSmart/BlogSmart/Feed/PostCell.swift index 44680d2..f298d85 100644 --- a/BlogSmart/BlogSmart/Feed/PostCell.swift +++ b/BlogSmart/BlogSmart/Feed/PostCell.swift @@ -10,7 +10,6 @@ import Alamofire import AlamofireImage class PostCell: UITableViewCell { - @IBOutlet weak var blogImage: UIImageView! @IBOutlet weak var blogDate: UILabel! @@ -27,7 +26,7 @@ class PostCell: UITableViewCell { imageDataRequest = AF.request(imageUrl).responseImage() { [weak self] response in switch response.result { case .success(let image): - print("✅ Post Saved!") + print("✅ Successfully fetched image!") // Set image view image with fetched image self?.blogImage.image = image case .failure(let error): From 4d1f65cbe96410e93e6175251a89edf67284530a Mon Sep 17 00:00:00 2001 From: michaeldacanay Date: Wed, 14 Jun 2023 22:19:58 -0400 Subject: [PATCH 5/6] resize form constraints --- .../BlogSmart/Base.lproj/Main.storyboard | 48 +++++++++---------- .../BlogSmart/Login/LoginViewController.swift | 11 ----- 2 files changed, 24 insertions(+), 35 deletions(-) diff --git a/BlogSmart/BlogSmart/Base.lproj/Main.storyboard b/BlogSmart/BlogSmart/Base.lproj/Main.storyboard index b04bd73..06527c8 100644 --- a/BlogSmart/BlogSmart/Base.lproj/Main.storyboard +++ b/BlogSmart/BlogSmart/Base.lproj/Main.storyboard @@ -34,20 +34,20 @@ - + - + - + - + @@ -121,31 +121,31 @@ - + - + - + - + - + - + @@ -333,17 +333,17 @@ These are everything a chocolate chip cookie should be. Crispy and chewy. Doughy - + - + - - - + + @@ -440,7 +440,7 @@ These are everything a chocolate chip cookie should be. Crispy and chewy. Doughy - + @@ -450,7 +450,7 @@ These are everything a chocolate chip cookie should be. Crispy and chewy. Doughy