From 14c495e0f1996992024ed4adc1e02919b449f52f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A4=80=ED=91=9Cjuunpy0?= Date: Thu, 5 Mar 2026 12:17:54 +0900 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=94=A7=20-=20Fix=20::=20=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=EA=B0=80=EC=9E=85=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EA=B2=80=EC=A6=9D=20=EC=98=A4=EB=A5=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PasswordSettingViewController.swift | 52 ++++++++--- .../Auth/SignUp/SignUpViewController.swift | 45 ++++++--- .../Scene/Auth/ViewModel/AuthViewModel.swift | 91 +++++++++++++------ 3 files changed, 131 insertions(+), 57 deletions(-) diff --git a/Projects/Feature/Sources/Scene/Auth/PsswordSetting/PasswordSettingViewController.swift b/Projects/Feature/Sources/Scene/Auth/PsswordSetting/PasswordSettingViewController.swift index 9a20eb21..abb30b8b 100644 --- a/Projects/Feature/Sources/Scene/Auth/PsswordSetting/PasswordSettingViewController.swift +++ b/Projects/Feature/Sources/Scene/Auth/PsswordSetting/PasswordSettingViewController.swift @@ -73,21 +73,49 @@ public final class PasswordSettingViewController: BaseViewController { // MARK: - Seletors @objc func signUpButtonTapped() { - viewModel.setupNewPassword(newPassword: passwordTextField.text ?? "", checkPassword: checkPasswordTextField.text ?? "") - + + view.endEditing(true) + + let password = passwordTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + let confirmPassword = checkPasswordTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + + print("password:", password) + print("confirm:", confirmPassword) + + guard password == confirmPassword else { + passwordErrorUI() + return + } + + viewModel.setupNewPassword(newPassword: password, checkPassword: confirmPassword) + DispatchQueue.main.async { self.present(self.loader, animated: true) } - - viewModel.signUp { success in - if success { - self.signUpSuccessUI() - let signInVC = SignInViewController(viewModel: self.viewModel) - self.navigationController?.pushViewController(signInVC, animated: true) - self.loader.dismiss(animated: true) - } else { - self.passwordErrorUI() - self.loader.dismiss(animated: true) + + viewModel.signUp { [weak self] success in + guard let self = self else { return } + + DispatchQueue.main.async { + + self.loader.dismiss(animated: true) { + + if success { + + self.signUpSuccessUI() + + let signInVC = SignInViewController(viewModel: AuthViewModel()) + + self.navigationController?.setViewControllers([signInVC], animated: true) + + } else { + + self.passwordErrorUI() + + } + + } + } } } diff --git a/Projects/Feature/Sources/Scene/Auth/SignUp/SignUpViewController.swift b/Projects/Feature/Sources/Scene/Auth/SignUp/SignUpViewController.swift index 6258fda4..fd684770 100644 --- a/Projects/Feature/Sources/Scene/Auth/SignUp/SignUpViewController.swift +++ b/Projects/Feature/Sources/Scene/Auth/SignUp/SignUpViewController.swift @@ -79,7 +79,7 @@ public final class SignUpViewController: BaseViewController { let womanAction = UIAlertAction(title: "여성", style: .default) { _ in self.genderTextField.setTitle("여성", for: .normal) self.genderTextField.setTitleColor(.color.gomsTextDefault.color, for: .normal) - self.viewModel.setupGender(gender: Gender.man.rawValue) + self.viewModel.setupGender(gender: Gender.woman.rawValue) self.authCodeButton.isEnabled = self.shouldEnableAuthCodeButton() } @@ -119,7 +119,8 @@ public final class SignUpViewController: BaseViewController { self.present(self.loader, animated: true) } - viewModel.setupEmail(email: emailTextField.text ?? "") + let email = (emailTextField.text ?? "") + "@gsm.hs.kr" + viewModel.setupEmail(email: email) viewModel.setupName(name: nameTextField.text ?? "") viewModel.setupEmailStatus(emailStatus: "BEFORE_SIGNUP") @@ -129,17 +130,28 @@ public final class SignUpViewController: BaseViewController { DispatchQueue.main.async { if susccess { switch statusCode { - case 200: - let authCodeVC = AuthCodeViewController(viewModel: self.viewModel, previousViewController: self, email: self.emailTextField.text ?? "") - self.navigationController?.pushViewController(authCodeVC, animated: true) - self.loader.dismiss(animated: true) - default: - let alert = UIAlertController(title: "서버오류", message: "GOMS 서버 운영팀에게 문의주세요.", preferredStyle: .alert) + case 200..<300: + let authCodeVC = AuthCodeViewController( + viewModel: self.viewModel, + previousViewController: self, + email: email + ) + self.loader.dismiss(animated: true) { + self.navigationController?.pushViewController(authCodeVC, animated: true) + } + + default: + let alert = UIAlertController( + title: "서버오류", + message: "GOMS 서버 운영팀에게 문의주세요.", + preferredStyle: .alert + ) let check = UIAlertAction(title: "확인", style: .cancel) alert.addAction(check) - self.present(alert, animated: true) - self.loader.dismiss(animated: true) + self.loader.dismiss(animated: true) { + self.present(alert, animated: true) + } } } else { switch statusCode { @@ -148,15 +160,17 @@ public final class SignUpViewController: BaseViewController { let check = UIAlertAction(title: "확인", style: .cancel) alert.addAction(check) - self.present(alert, animated: true) - self.loader.dismiss(animated: true) + self.loader.dismiss(animated: true) { + self.present(alert, animated: true) + } default: let alert = UIAlertController(title: "인증코드 발송 실패", message: "인증코드 발송에 실패했습니다.\n다시 시도해 주세요.", preferredStyle: .alert) let check = UIAlertAction(title: "확인", style: .cancel) alert.addAction(check) - self.present(alert, animated: true) - self.loader.dismiss(animated: true) + self.loader.dismiss(animated: true) { + self.present(alert, animated: true) + } } } } @@ -224,7 +238,8 @@ extension SignUpViewController: UITextFieldDelegate { if textField == nameTextField { viewModel.setupName(name: self.nameTextField.text ?? "") } else if textField == emailTextField { - viewModel.setupEmail(email: self.emailTextField.text ?? "") + let email = (self.emailTextField.text ?? "") + "@gsm.hs.kr" + viewModel.setupEmail(email: email) } authCodeButton.isEnabled = shouldEnableAuthCodeButton() diff --git a/Projects/Feature/Sources/Scene/Auth/ViewModel/AuthViewModel.swift b/Projects/Feature/Sources/Scene/Auth/ViewModel/AuthViewModel.swift index 55c02fb0..f75b3d59 100644 --- a/Projects/Feature/Sources/Scene/Auth/ViewModel/AuthViewModel.swift +++ b/Projects/Feature/Sources/Scene/Auth/ViewModel/AuthViewModel.swift @@ -38,9 +38,12 @@ public final class AuthViewModel: BaseViewModel { } func setupEmail(email: String) { - self.email = "\(email)@gsm.hs.kr" + if email.contains("@gsm.hs.kr") { + self.email = email + } else { + self.email = "\(email)@gsm.hs.kr" + } } - func setupPassword(password: String) { self.password = password } @@ -49,6 +52,7 @@ public final class AuthViewModel: BaseViewModel { self.authCode = authCode } + func setupNewPassword(newPassword: String, checkPassword: String) { guard newPassword == checkPassword else { return } self.newPassword = newPassword @@ -72,16 +76,19 @@ public final class AuthViewModel: BaseViewModel { } // MARK: - Sign In + + func signIn(completion: @escaping (Int, String?) -> Void) { let param = SignInRequest(email: email, password: password) authProvider.request(.signIn(param: param)) { [weak self] response in guard let self = self else { return } - DispatchQueue.global().async { [self] in - var authority: String? = nil + var authority: String? = nil + var statusCode: Int = 0 + switch response { case .success(let result): - let statusCode = result.statusCode + statusCode = result.statusCode do { switch statusCode { case 200: @@ -115,7 +122,6 @@ public final class AuthViewModel: BaseViewModel { } - completion(statusCode, authority) default: break } @@ -134,33 +140,24 @@ public final class AuthViewModel: BaseViewModel { } } } - } + // MARK: - Send Auth Code func sendAuthCode(completion: @escaping (Bool, Int) -> Void) { - let param = SendAuthCodeRequest(email: email, emailStatus: emailStatus) + let param = SendAuthCodeRequest(email: email, emailStatus: emailStatus) + + print("📦 email:", email) + print("📦 emailStatus:", emailStatus) + + authProvider.request(.sendAuthCode(param: param)) { response in switch response { case .success(let result): - do { - let statusCode = result.statusCode - switch statusCode { - case 204: - print("success") - completion(true, statusCode) - case 404: - print("존재하지 않는 사용자일때") - completion(false, statusCode) - case 429: - print("이메일 요청이 5번을 초과할 경우") - completion(false, statusCode) - default: - print(result) - completion(false, statusCode) - } - } - case .failure(let err): - print(err.localizedDescription) + print("🔥 statusCode:", result.statusCode) + print("🔥 data:", String(data: result.data, encoding: .utf8) ?? "") + completion((200...299).contains(result.statusCode), result.statusCode) + case .failure(let error): + print("❌ error:", error) completion(false, 0) } } @@ -203,7 +200,13 @@ public final class AuthViewModel: BaseViewModel { // MARK: - New Password func newPassword(completion: @escaping (Bool, Int) -> Void) { - let param = NewPasswordRequest.init(email: email, newPassword: newServePassword) + + print("🔥 FINAL EMAIL:", email) + print("🔥 FINAL PASSWORD:", newServePassword) + + let param = NewPasswordRequest(email: email, newPassword: newServePassword) + print("🔥 REQUEST:", param) + accountProvider.request(.newPassword(param: param)) { response in switch response { case .success(let result): @@ -269,22 +272,51 @@ public final class AuthViewModel: BaseViewModel { // MARK: - Sign Up func signUp(completion: @escaping (Bool) -> Void) { - let param = SignUpRequest.init(email: email, password: newPassword, name: name, gender: gender, major: major) + + print("📦 email:", email) + print("📦 password:", newPassword) + print("📦 name:", name) + print("📦 gender:", gender) + print("📦 major:", major) + + if name.isEmpty || gender.isEmpty || major.isEmpty { + print("🚨 회원가입 정보 누락") + completion(false) + return + } + + let param = SignUpRequest( + email: email, + password: newPassword, + name: name, + gender: gender, + major: major + ) + authProvider.request(.signUp(param: param)) { response in switch response { case .success(let result): let statusCode = result.statusCode + switch statusCode { case 201: print("Created") completion(true) + + case 400: + print("🚨 서버 validation 실패") + print(String(data: result.data, encoding: .utf8) ?? "") + completion(false) + case 500: print("SERVER ERROR") completion(false) + default: print(result) completion(false) } + case .failure(let err): print(err.localizedDescription) completion(false) @@ -292,4 +324,3 @@ public final class AuthViewModel: BaseViewModel { } } } - From f6d2dcd56eddea990603fbccaf01e23486eb6345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A4=80=ED=91=9Cjuunpy0?= Date: Thu, 5 Mar 2026 12:18:10 +0900 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=94=A7=20-=20Fix=20::=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EC=84=B1=EA=B3=B5=20=ED=9B=84=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EC=A0=84=ED=99=98=20=EC=98=A4=EB=A5=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Auth/SignIn/SignInViewController.swift | 27 +++++++++----- .../Admin/View/AdminMainViewController.swift | 35 +++++++++---------- .../Main/User/View/MainViewController.swift | 11 +++--- 3 files changed, 39 insertions(+), 34 deletions(-) diff --git a/Projects/Feature/Sources/Scene/Auth/SignIn/SignInViewController.swift b/Projects/Feature/Sources/Scene/Auth/SignIn/SignInViewController.swift index 6086a96d..094a8ce3 100644 --- a/Projects/Feature/Sources/Scene/Auth/SignIn/SignInViewController.swift +++ b/Projects/Feature/Sources/Scene/Auth/SignIn/SignInViewController.swift @@ -130,28 +130,37 @@ public final class SignInViewController: BaseViewController { guard let self = self else { return } if success { - if self.isTransitioning { + if self.isTransitioning { return } + self.isTransitioning = true + + guard let authority = authority else { + print("authority nil") + self.loader.dismiss(animated: true) { + self.isTransitioning = false + } return } - self.isTransitioning = true + print("authority:", authority) - if let authority = self.profileModel.profileInfo?.authority { - if authority == Authority.admin.rawValue { + self.loader.dismiss(animated: true) { + if authority == "ROLE_STUDENT_COUNCIL" { let mainVC = AdminMainViewController() self.navigationController?.setViewControllers([mainVC], animated: true) - } else if authority == Authority.student.rawValue { + } else if authority == "ROLE_STUDENT" { let mainVC = MainViewController() self.navigationController?.setViewControllers([mainVC], animated: true) } else { - print("권한이 없습니다.") + print("권한이 없습니다. authority:", authority) } + self.isTransitioning = false } } else { print("프로필 정보를 불러오는데 실패했습니다.") + self.loader.dismiss(animated: true) { + self.isTransitioning = false + } } - self.loader.dismiss(animated: true) - self.isTransitioning = false } case 400: self.passwordErrorUI() @@ -192,7 +201,7 @@ public final class SignInViewController: BaseViewController { @objc override func keyboardWillHide(_ sender: Notification) { self.signInButton.isEnabled = true - signInButton.snp.makeConstraints { + signInButton.snp.remakeConstraints { $0.height.equalTo(48) $0.leading.equalTo(bounds.width * 0.05) $0.trailing.equalTo(-bounds.width * 0.05) diff --git a/Projects/Feature/Sources/Scene/Main/Admin/View/AdminMainViewController.swift b/Projects/Feature/Sources/Scene/Main/Admin/View/AdminMainViewController.swift index f3c98d7d..234085b3 100644 --- a/Projects/Feature/Sources/Scene/Main/Admin/View/AdminMainViewController.swift +++ b/Projects/Feature/Sources/Scene/Main/Admin/View/AdminMainViewController.swift @@ -118,10 +118,8 @@ public class AdminMainViewController: BaseViewController, UICollectionViewDataSo super.viewDidLoad() self.latecomerCollectionView.reloadData() self.outingStatusCollectionView.reloadData() - handleRefreshControl() configureRefreshControl() setupScrollView() - refreshControl.beginRefreshing() } func setupScrollView() { @@ -185,23 +183,24 @@ public class AdminMainViewController: BaseViewController, UICollectionViewDataSo if success { if let authority = self.profileViewModel.profileInfo?.authority { - let currentVC = self.navigationController?.viewControllers.last - - switch authority { - case "ROLE_STUDENT": - if !(currentVC is MainViewController) { - let mainVC = MainViewController() - self.navigationController?.setViewControllers([mainVC], animated: false) - } - case "ROLE_STUDENT_COUNCIL": - if !(currentVC is AdminMainViewController) { - let adminVC = AdminMainViewController() - self.navigationController?.setViewControllers([adminVC], animated: false) - } - default: - print("권한이 없습니다.") + + + if authority.contains("ROLE_STUDENT_COUNCIL") { + + print("Admin 유지") + + } else if authority.contains("ROLE_STUDENT") { + let mainVC = MainViewController() + self.navigationController?.setViewControllers([mainVC], animated: false) + + } else { + print("권한이 없습니다. authority:", authority) } + + } else { + print("authority 값이 없습니다.") } + } else { print("프로필 정보를 불러오는데 실패했습니다.") } @@ -318,7 +317,7 @@ public class AdminMainViewController: BaseViewController, UICollectionViewDataSo } if let authority = viewModel.profileData?.authority { - if authority == "ROLE_STUDENT_COUNCIL" { + if authority.contains("ROLE_STUDENT_COUNCIL") { profileView.profileStatus.text = "학생회" basicsProfileView.myOutingStatusLabel.text = "학생회" } diff --git a/Projects/Feature/Sources/Scene/Main/User/View/MainViewController.swift b/Projects/Feature/Sources/Scene/Main/User/View/MainViewController.swift index ae2d6347..3a4ff037 100644 --- a/Projects/Feature/Sources/Scene/Main/User/View/MainViewController.swift +++ b/Projects/Feature/Sources/Scene/Main/User/View/MainViewController.swift @@ -143,10 +143,8 @@ public final class MainViewController: BaseViewController, UICollectionViewDataS super.viewDidLoad() self.latecomerCollectionView.reloadData() self.outingStatusCollectionView.reloadData() - handleRefreshControl() configureRefreshControl() setupScrollView() - refreshControl.beginRefreshing() } func configureRefreshControl() { @@ -191,19 +189,18 @@ public final class MainViewController: BaseViewController, UICollectionViewDataS if let authority = self.profileViewModel.profileInfo?.authority { let currentVC = self.navigationController?.viewControllers.last - switch authority { - case "ROLE_STUDENT_COUNCIL": + if authority.contains("ROLE_STUDENT_COUNCIL") { if !(currentVC is AdminMainViewController) { let adminVC = AdminMainViewController() self.navigationController?.setViewControllers([adminVC], animated: false) } - case "ROLE_STUDENT": + } else if authority.contains("ROLE_STUDENT") { if !(currentVC is MainViewController) { let mainVC = MainViewController() self.navigationController?.setViewControllers([mainVC], animated: false) } - default: - print("권한이 없습니다.") + } else { + print("권한이 없습니다. authority:", authority) } } } else { From 5a42776a49c5e66f4a089c5d1967dd023af5cf09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A4=80=ED=91=9Cjuunpy0?= Date: Thu, 5 Mar 2026 12:18:26 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=94=A7=20-=20Fix=20::=20=EB=B9=84?= =?UTF-8?q?=EB=B0=80=EB=B2=88=ED=98=B8=20=EC=9E=AC=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20Auth=20=ED=99=94=EB=A9=B4=20=ED=9D=90=EB=A6=84=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FindPasswordViewController.swift | 11 ++- .../Auth/Intro/IntroViewController.swift | 1 + .../NewPasswordViewController.swift | 77 +++++++++++-------- 3 files changed, 55 insertions(+), 34 deletions(-) diff --git a/Projects/Feature/Sources/Scene/Auth/FindPassword/FindPasswordViewController.swift b/Projects/Feature/Sources/Scene/Auth/FindPassword/FindPasswordViewController.swift index e9e535a8..1a6c90b4 100644 --- a/Projects/Feature/Sources/Scene/Auth/FindPassword/FindPasswordViewController.swift +++ b/Projects/Feature/Sources/Scene/Auth/FindPassword/FindPasswordViewController.swift @@ -57,7 +57,13 @@ public final class FindPasswordViewController: BaseViewController { viewModel.sendAuthCode { success, statusCode in if statusCode == 204 { self.successUI() - let authCodeVC = AuthCodeViewController(viewModel: self.viewModel, previousViewController: self, email: self.emailTextField.text ?? "") + let email = self.emailTextField.text ?? "" + + let authCodeVC = AuthCodeViewController( + viewModel: self.viewModel, + previousViewController: self, + email: email + ) self.navigationController?.pushViewController(authCodeVC, animated: true) } else if statusCode == 404 { self.nonExistentUser() @@ -166,8 +172,7 @@ public final class FindPasswordViewController: BaseViewController { extension FindPasswordViewController: UITextFieldDelegate { public func textFieldDidChange(_ textField: UITextField) { if textField == emailTextField { - viewModel.setupEmail(email: emailTextField.text ?? "") - } + viewModel.setupEmail(email: emailTextField.text ?? "") } } public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { diff --git a/Projects/Feature/Sources/Scene/Auth/Intro/IntroViewController.swift b/Projects/Feature/Sources/Scene/Auth/Intro/IntroViewController.swift index e5b3436b..88fb0b6a 100644 --- a/Projects/Feature/Sources/Scene/Auth/Intro/IntroViewController.swift +++ b/Projects/Feature/Sources/Scene/Auth/Intro/IntroViewController.swift @@ -138,3 +138,4 @@ public final class IntroViewController: BaseViewController { } } } + diff --git a/Projects/Feature/Sources/Scene/Auth/NewPassword/NewPasswordViewController.swift b/Projects/Feature/Sources/Scene/Auth/NewPassword/NewPasswordViewController.swift index e0186dab..dcab2585 100644 --- a/Projects/Feature/Sources/Scene/Auth/NewPassword/NewPasswordViewController.swift +++ b/Projects/Feature/Sources/Scene/Auth/NewPassword/NewPasswordViewController.swift @@ -87,53 +87,68 @@ public final class NewPasswordViewController: BaseViewController { // MARK: - Seletors @objc func doneButtonTapped() { - let defaults = UserDefaults.standard - let localPassword = defaults.string(forKey: "localPass") - self.validatePassword() - let isValidPassword = self.validatePassword() - - viewModel.setupEmail(email: self.email) - viewModel.setupNewServePassword(newPassword: passwordTextField.text ?? "", checkPassword: checkPasswordTextField.text ?? "") - viewModel.setupPassword(password: localPassword ?? "") - viewModel.newPassword { [self] success, statusCode in - if !isValidPassword { - self.passwordWrongRegularExpressionUI() - - } else if passwordTextField.text != checkPasswordTextField.text { - self.passwordErrorUI() + + + print("🚨 DONE BUTTON TAPPED") + print("🚨 VC email:", email) + + let isValidPassword = validatePassword() + + if !isValidPassword { + passwordWrongRegularExpressionUI() + return + } + + if passwordTextField.text != checkPasswordTextField.text { + passwordErrorUI() conditionsLabel.isHidden = true - } else if passwordTextField.text == "" { - self.passwordErrorUI() + return + } + + if passwordTextField.text == "" { + passwordErrorUI() + return } - else if !success { + + viewModel.setupNewServePassword( + newPassword: passwordTextField.text ?? "", + checkPassword: checkPasswordTextField.text ?? "" + ) + + print("🚨 CALLING newPassword API") + + viewModel.newPassword { [self] success, statusCode in + + if !success { switch statusCode { + case 400: print("400") self.passwordOverlapErrorUI() conditionsLabel.isHidden = false + case 404: print("404") + default: print("Error: \(statusCode)") } - } else if success { - let defaults = UserDefaults.standard + + } else { + UserDefaults.standard.set(self.checkPasswordTextField.text, forKey: "localPass") - let alert = UIAlertController(title: "재설정 완료", message: "비밀번호가 재설정되었습니다.\n로그인 화면으로 돌아갑니다.", preferredStyle: .alert) - - let check = UIAlertAction(title: "확인", style: .default) { action in + + let alert = UIAlertController( + title: "재설정 완료", + message: "비밀번호가 재설정되었습니다.\n로그인 화면으로 돌아갑니다.", + preferredStyle: .alert + ) + + let check = UIAlertAction(title: "확인", style: .default) { _ in let loginVC = IntroViewController() self.navigationController?.pushViewController(loginVC, animated: true) } - - passwordOverlapErrorLabel.isHidden = true - passwordTextField.layer.borderWidth = 0 - passwordTextField.setPlaceholderColor(.color.gomsTertiary.color) - - passwordErrorLabel.isHidden = true - checkPasswordTextField.layer.borderWidth = 0 - checkPasswordTextField.setPlaceholderColor(.color.gomsTertiary.color) - + alert.addAction(check) self.present(alert, animated: true) } From 7bcbb4695a9587a2e2d805e3d4224be1c350cab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A4=80=ED=91=9Cjuunpy0?= Date: Thu, 5 Mar 2026 12:18:39 +0900 Subject: [PATCH 4/4] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20-=20Refactor=20::=20Au?= =?UTF-8?q?th=20=EA=B4=80=EB=A0=A8=20=EC=84=A4=EC=A0=95=20=EB=B0=8F=20?= =?UTF-8?q?=EB=A6=AC=EC=86=8C=EC=8A=A4=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Projects/App/GOMS-iOS-V2Debug.entitlements | 8 +++ .../App/Sources/Application/AppDelegate.swift | 20 +++++++- .../Sources/Application/SceneDelegate.swift | 50 ++++++++++--------- Projects/App/Support/Info.plist | 12 +++-- .../GOMS_TextDefault.colorset/Contents.json | 18 +++---- .../Profile/ViewModel/ProfileViewModel.swift | 1 + .../Sources/Scene/QR/Eum/QRResultType.swift | 1 + .../Project+Templates.swift | 15 ++++-- 8 files changed, 84 insertions(+), 41 deletions(-) create mode 100644 Projects/App/GOMS-iOS-V2Debug.entitlements diff --git a/Projects/App/GOMS-iOS-V2Debug.entitlements b/Projects/App/GOMS-iOS-V2Debug.entitlements new file mode 100644 index 00000000..903def2a --- /dev/null +++ b/Projects/App/GOMS-iOS-V2Debug.entitlements @@ -0,0 +1,8 @@ + + + + + aps-environment + development + + diff --git a/Projects/App/Sources/Application/AppDelegate.swift b/Projects/App/Sources/Application/AppDelegate.swift index 5e047c7b..5433f279 100644 --- a/Projects/App/Sources/Application/AppDelegate.swift +++ b/Projects/App/Sources/Application/AppDelegate.swift @@ -3,9 +3,13 @@ import Firebase import UserNotifications import Feature import AudioToolbox +import FirebaseMessaging @main class AppDelegate: UIResponder, UIApplicationDelegate { + + + let notificationViewModel = NotificationViewModel() @@ -13,18 +17,32 @@ class AppDelegate: UIResponder, UIApplicationDelegate { _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { + + + + FirebaseApp.configure() UNUserNotificationCenter.current().delegate = self - Messaging.messaging().delegate = self + Messaging.messaging().token { token, error in + if let token = token { + print("FCM", token) + } + } + requestNotificationAuthorization() return true } private func requestNotificationAuthorization() { + + + + print("빌드 버전:", + Bundle.main.infoDictionary?["CFBundleVersion"] ?? "nil") UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound, .carPlay]) { granted, error in if let error = error { print("Error requesting notification authorization: \(error.localizedDescription)") diff --git a/Projects/App/Sources/Application/SceneDelegate.swift b/Projects/App/Sources/Application/SceneDelegate.swift index 8c7403d6..45c3a416 100644 --- a/Projects/App/Sources/Application/SceneDelegate.swift +++ b/Projects/App/Sources/Application/SceneDelegate.swift @@ -15,14 +15,14 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { let isSwitchOn = defaults.bool(forKey: "isSwitchOn") let adminIsSwitchOn = defaults.bool(forKey: "isSwitchMakeOn") - checkForUpdates { needsUpdate in - if needsUpdate { - print("업데이트 필요") - self.showUpdatePopup() - } else { - print("최신 버전입니다") - } - } + //*checkForUpdates { needsUpdate in + // if needsUpdate { + // print("업데이트 필요") + // self.showUpdatePopup() + // } else { + // print("최신 버전입니다") + // } + // } applySavedTheme() @@ -133,24 +133,26 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } private func showUpdatePopup() { - let alertController = UIAlertController( - title: "업데이트 알림", - message: "더 나은 서비스를 위해 곰스가 수정되었어요!\n원활한 사용을 위해 업데이트 후 이용해주세요!", - preferredStyle: .alert - ) - - let updateAction = UIAlertAction(title: "확인", style: .default) { _ in - if let url = URL(string: "https://apps.apple.com/kr/app/goms/id6502936560") { - UIApplication.shared.open(url) - } - } + DispatchQueue.main.async { - alertController.addAction(updateAction) + guard let rootVC = self.window?.rootViewController else { return } - DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { - self.window?.rootViewController?.present(alertController, animated: true) { - print("업데이트 팝업 표시됨") - } + // 이미 다른 VC를 present 중이면 중복 방지 + if rootVC.presentedViewController != nil { return } + + let alertController = UIAlertController( + title: "업데이트 알림", + message: "원활한 사용을 위해 업데이트 후 이용해주세요!", + preferredStyle: .alert + ) + + alertController.addAction(UIAlertAction(title: "업데이트", style: .default) { _ in + if let url = URL(string: "앱스토어URL") { + UIApplication.shared.open(url) + } + }) + + rootVC.present(alertController, animated: true) } } diff --git a/Projects/App/Support/Info.plist b/Projects/App/Support/Info.plist index d5e0df73..a6c5de22 100644 --- a/Projects/App/Support/Info.plist +++ b/Projects/App/Support/Info.plist @@ -17,13 +17,15 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.5.1 + $(MARKETING_VERSION) CFBundleVersion - 1 + $(CURRENT_PROJECT_VERSION) CloudTypeBaseURL $(CloudTypeBaseURL) FirebaseAppDelegateProxyEnabled + LSApplicationCategoryType + http://gsmsv-1.yujun.kr:23346 LSRequiresIPhoneOS Localization native development region @@ -32,13 +34,15 @@ NSAllowsArbitraryLoads + NSAllowsArbitraryLoadsUsageDescription + NSCameraUsageDescription QR 스캔을 위해 카메라를 허용해주세요. SERVER_HOST ${SERVER_HOST} SchoolBaseURL - $(SchoolBaseURL) + http://gsmsv-1.yujun.kr:23346/api/v2 UIApplicationSceneManifest UIApplicationSupportsMultipleScenes @@ -82,5 +86,7 @@ UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown + ITSAppUsesNonExemptEncryption + diff --git a/Projects/Feature/Resources/Colors.xcassets/GOMS_TextDefault.colorset/Contents.json b/Projects/Feature/Resources/Colors.xcassets/GOMS_TextDefault.colorset/Contents.json index 646130f7..413ae315 100644 --- a/Projects/Feature/Resources/Colors.xcassets/GOMS_TextDefault.colorset/Contents.json +++ b/Projects/Feature/Resources/Colors.xcassets/GOMS_TextDefault.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "1.000", - "green" : "1.000", - "red" : "1.000" + "blue" : "0xFF", + "green" : "0xFF", + "red" : "0xFF" } }, "idiom" : "universal" @@ -23,9 +23,9 @@ "color-space" : "display-p3", "components" : { "alpha" : "1.000", - "blue" : "0.000", - "green" : "0.000", - "red" : "0.000" + "blue" : "0x00", + "green" : "0x00", + "red" : "0x00" } }, "idiom" : "universal" @@ -41,9 +41,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "1.000", - "green" : "1.000", - "red" : "1.000" + "blue" : "0xFF", + "green" : "0xFF", + "red" : "0xFF" } }, "idiom" : "universal" diff --git a/Projects/Feature/Sources/Scene/Profile/ViewModel/ProfileViewModel.swift b/Projects/Feature/Sources/Scene/Profile/ViewModel/ProfileViewModel.swift index 8070c258..94c8c611 100644 --- a/Projects/Feature/Sources/Scene/Profile/ViewModel/ProfileViewModel.swift +++ b/Projects/Feature/Sources/Scene/Profile/ViewModel/ProfileViewModel.swift @@ -100,6 +100,7 @@ public final class ProfileViewModel: ObservableObject { switch result { case .success: self?.keyChain.delete(key: Const.KeyChainKey.accessToken) + self?.keyChain.delete(key: Const.KeyChainKey.refreshToken) print("Logout successfully") completion(true) case let .failure(err): diff --git a/Projects/Feature/Sources/Scene/QR/Eum/QRResultType.swift b/Projects/Feature/Sources/Scene/QR/Eum/QRResultType.swift index 00d310db..8192acaa 100644 --- a/Projects/Feature/Sources/Scene/QR/Eum/QRResultType.swift +++ b/Projects/Feature/Sources/Scene/QR/Eum/QRResultType.swift @@ -32,6 +32,7 @@ extension QRResultType { } } + var mainText: String { switch self { case .outing: diff --git a/Tuist/ProjectDescriptionHelpers/Project+Templates.swift b/Tuist/ProjectDescriptionHelpers/Project+Templates.swift index 21b462dc..fe72cfa7 100644 --- a/Tuist/ProjectDescriptionHelpers/Project+Templates.swift +++ b/Tuist/ProjectDescriptionHelpers/Project+Templates.swift @@ -13,22 +13,29 @@ public extension Project { infoPlist: InfoPlist = .default ) -> Project { let settings: Settings = .settings( - base: ["OTHER_LDFLAGS": ["-all_load", "-ObjC"]], + base: [ + "OTHER_LDFLAGS": ["-all_load", "-ObjC"], + "MARKETING_VERSION": "1.5.6", + "CURRENT_PROJECT_VERSION": "6" + ], configurations: [ .debug(name: .debug), .release(name: .release) - ], defaultSettings: .recommended) + ], + defaultSettings: .recommended + ) let appTarget: Target = .target( name: name, destinations: destinations, product: product, - bundleId: "\(organizationName).\(name)", + bundleId: "HARIBO.GOMS-iOS-V2", deploymentTargets: .iOS("16.0"), infoPlist: infoPlist, sources: sources, resources: resources, - dependencies: dependencies + dependencies: dependencies, + settings: settings ) let targets: [Target] = [appTarget]