From 50e73931e7015c2b93803fe1cc62e1268c303c6c Mon Sep 17 00:00:00 2001 From: Sejin Lee Date: Mon, 26 Dec 2022 15:32:22 +0900 Subject: [PATCH 1/9] =?UTF-8?q?[Add]=20#57=20-=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EB=B3=80=EA=B2=BD=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20=ED=8C=8C=EC=9D=BC=EB=93=A4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Repository/SettingRepository.swift | 4 +- .../Transform/PasswordSettingTransform.swift | 19 +++++++ .../Sources/Model/PasswordChangeModel.swift | 16 ++++++ .../PasswordChangeRepositoryInterface.swift | 13 +++++ .../UseCase/PasswordChangeUseCase.swift | 27 ++++++++++ .../Sources/Entity/PasswordChangeEntity.swift | 13 +++++ .../PasswordChangeVC.swift | 43 +++++++++++++++ .../ViewModel/PasswordChangeViewModel.swift | 52 +++++++++++++++++++ .../Sources/ModuleFactory/ModuleFactory.swift | 2 +- 9 files changed, 186 insertions(+), 3 deletions(-) create mode 100644 SOPT-Stamp-iOS/Projects/Data/Sources/Transform/PasswordSettingTransform.swift create mode 100644 SOPT-Stamp-iOS/Projects/Domain/Sources/Model/PasswordChangeModel.swift create mode 100644 SOPT-Stamp-iOS/Projects/Domain/Sources/RepositoryInterface/PasswordChangeRepositoryInterface.swift create mode 100644 SOPT-Stamp-iOS/Projects/Domain/Sources/UseCase/PasswordChangeUseCase.swift create mode 100644 SOPT-Stamp-iOS/Projects/Modules/Network/Sources/Entity/PasswordChangeEntity.swift create mode 100644 SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/PasswordChangeVC.swift create mode 100644 SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/ViewModel/PasswordChangeViewModel.swift diff --git a/SOPT-Stamp-iOS/Projects/Data/Sources/Repository/SettingRepository.swift b/SOPT-Stamp-iOS/Projects/Data/Sources/Repository/SettingRepository.swift index ca414383..1c592e6e 100644 --- a/SOPT-Stamp-iOS/Projects/Data/Sources/Repository/SettingRepository.swift +++ b/SOPT-Stamp-iOS/Projects/Data/Sources/Repository/SettingRepository.swift @@ -14,10 +14,10 @@ import Network public class SettingRepository { - private let networkService: UserService + private let networkService: AuthService private let cancelBag = CancelBag() - public init(service: UserService) { + public init(service: AuthService) { self.networkService = service } } diff --git a/SOPT-Stamp-iOS/Projects/Data/Sources/Transform/PasswordSettingTransform.swift b/SOPT-Stamp-iOS/Projects/Data/Sources/Transform/PasswordSettingTransform.swift new file mode 100644 index 00000000..f495cf0f --- /dev/null +++ b/SOPT-Stamp-iOS/Projects/Data/Sources/Transform/PasswordSettingTransform.swift @@ -0,0 +1,19 @@ +// +// PasswordSettingTransform.swift +// Data +// +// Created by sejin on 2022/12/26. +// Copyright © 2022 SOPT-Stamp-iOS. All rights reserved. +// + +import Foundation + +import Domain +import Network + +extension PasswordChangeEntity { + + public func toDomain() -> PasswordChangeModel { + return PasswordChangeModel.init() + } +} diff --git a/SOPT-Stamp-iOS/Projects/Domain/Sources/Model/PasswordChangeModel.swift b/SOPT-Stamp-iOS/Projects/Domain/Sources/Model/PasswordChangeModel.swift new file mode 100644 index 00000000..328749c5 --- /dev/null +++ b/SOPT-Stamp-iOS/Projects/Domain/Sources/Model/PasswordChangeModel.swift @@ -0,0 +1,16 @@ +// +// PasswordChangeModel.swift +// Domain +// +// Created by sejin on 2022/12/26. +// Copyright © 2022 SOPT-Stamp-iOS. All rights reserved. +// + +import Foundation + +public struct PasswordChangeModel { + + public init() { + + } +} diff --git a/SOPT-Stamp-iOS/Projects/Domain/Sources/RepositoryInterface/PasswordChangeRepositoryInterface.swift b/SOPT-Stamp-iOS/Projects/Domain/Sources/RepositoryInterface/PasswordChangeRepositoryInterface.swift new file mode 100644 index 00000000..c33321d4 --- /dev/null +++ b/SOPT-Stamp-iOS/Projects/Domain/Sources/RepositoryInterface/PasswordChangeRepositoryInterface.swift @@ -0,0 +1,13 @@ +// +// PasswordChangeRepositoryInterface.swift +// Domain +// +// Created by sejin on 2022/12/26. +// Copyright © 2022 SOPT-Stamp-iOS. All rights reserved. +// + +import Combine + +public protocol PasswordChangeRepositoryInterface { + +} diff --git a/SOPT-Stamp-iOS/Projects/Domain/Sources/UseCase/PasswordChangeUseCase.swift b/SOPT-Stamp-iOS/Projects/Domain/Sources/UseCase/PasswordChangeUseCase.swift new file mode 100644 index 00000000..35104a5c --- /dev/null +++ b/SOPT-Stamp-iOS/Projects/Domain/Sources/UseCase/PasswordChangeUseCase.swift @@ -0,0 +1,27 @@ +// +// PasswordChangeUseCase.swift +// Domain +// +// Created by sejin on 2022/12/26. +// Copyright © 2022 SOPT-Stamp-iOS. All rights reserved. +// + +import Combine + +public protocol PasswordChangeUseCase { + +} + +public class DefaultPasswordChangeUseCase { + + private let repository: PasswordChangeRepositoryInterface + private var cancelBag = Set() + + public init(repository: PasswordChangeRepositoryInterface) { + self.repository = repository + } +} + +extension DefaultPasswordChangeUseCase: PasswordChangeUseCase { + +} diff --git a/SOPT-Stamp-iOS/Projects/Modules/Network/Sources/Entity/PasswordChangeEntity.swift b/SOPT-Stamp-iOS/Projects/Modules/Network/Sources/Entity/PasswordChangeEntity.swift new file mode 100644 index 00000000..3016b72c --- /dev/null +++ b/SOPT-Stamp-iOS/Projects/Modules/Network/Sources/Entity/PasswordChangeEntity.swift @@ -0,0 +1,13 @@ +// +// PasswordChangeEntity.swift +// Network +// +// Created by sejin on 2022/12/26. +// Copyright © 2022 SOPT-Stamp-iOS. All rights reserved. +// + +import Foundation + +public struct PasswordChangeEntity { + +} diff --git a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/PasswordChangeVC.swift b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/PasswordChangeVC.swift new file mode 100644 index 00000000..c44a8f91 --- /dev/null +++ b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/PasswordChangeVC.swift @@ -0,0 +1,43 @@ +// +// PasswordChangeVC.swift +// Presentation +// +// Created by sejin on 2022/12/26. +// Copyright © 2022 SOPT-Stamp-iOS. All rights reserved. +// + +import UIKit + +import Combine + +import Core +import SnapKit +import Then + +public class PasswordChangeVC: UIViewController { + + // MARK: - Properties + + public var viewModel: PasswordChangeViewModel! + private var cancelBag = CancelBag() + + // MARK: - UI Components + + // MARK: - View Life Cycle + + public override func viewDidLoad() { + super.viewDidLoad() + self.bindViewModels() + } +} + +// MARK: - Methods + +extension PasswordChangeVC { + + private func bindViewModels() { + let input = PasswordChangeViewModel.Input() + let output = self.viewModel.transform(from: input, cancelBag: self.cancelBag) + } + +} diff --git a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/ViewModel/PasswordChangeViewModel.swift b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/ViewModel/PasswordChangeViewModel.swift new file mode 100644 index 00000000..96ab6ad8 --- /dev/null +++ b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/ViewModel/PasswordChangeViewModel.swift @@ -0,0 +1,52 @@ +// +// PasswordChangeViewModel.swift +// Presentation +// +// Created by sejin on 2022/12/26. +// Copyright © 2022 SOPT-Stamp-iOS. All rights reserved. +// + +import Foundation + +import Combine + +import Core +import Domain + +public class PasswordChangeViewModel: ViewModelType { + + private let useCase: PasswordChangeUseCase + private var cancelBag = CancelBag() + + // MARK: - Inputs + + public struct Input { + + } + + // MARK: - Outputs + + public struct Output { + + } + + // MARK: - init + + public init(useCase: PasswordChangeUseCase) { + self.useCase = useCase + } +} + +extension PasswordChangeViewModel { + public func transform(from input: Input, cancelBag: CancelBag) -> Output { + let output = Output() + self.bindOutput(output: output, cancelBag: cancelBag) + // input,output 상관관계 작성 + + return output + } + + private func bindOutput(output: Output, cancelBag: CancelBag) { + + } +} diff --git a/SOPT-Stamp-iOS/Projects/SOPT-Stamp-iOS/Sources/ModuleFactory/ModuleFactory.swift b/SOPT-Stamp-iOS/Projects/SOPT-Stamp-iOS/Sources/ModuleFactory/ModuleFactory.swift index 97c85304..ce3fcb2d 100644 --- a/SOPT-Stamp-iOS/Projects/SOPT-Stamp-iOS/Sources/ModuleFactory/ModuleFactory.swift +++ b/SOPT-Stamp-iOS/Projects/SOPT-Stamp-iOS/Sources/ModuleFactory/ModuleFactory.swift @@ -110,7 +110,7 @@ extension ModuleFactory: ModuleFactoryInterface { } public func makeSettingVC() -> SettingVC { - let repository = SettingRepository(service: userService) + let repository = SettingRepository(service: authService) let useCase = DefaultSettingUseCase(repository: repository) let viewModel = SettingViewModel(useCase: useCase) let settingVC = SettingVC() From 7a37171dbbfa5a3aa8b0730244f1708f75cd9f42 Mon Sep 17 00:00:00 2001 From: Sejin Lee Date: Mon, 26 Dec 2022 15:46:07 +0900 Subject: [PATCH 2/9] =?UTF-8?q?[Feat]=20#57=20-=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EB=B3=80=EA=B2=BD=20=EB=B7=B0=EB=A5=BC=20?= =?UTF-8?q?ModuleFactory=EC=97=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/Sources/ModuleFactoryInterface.swift | 1 + .../Sources/ModuleFactory/ModuleFactory.swift | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/SOPT-Stamp-iOS/Projects/Presentation/Sources/ModuleFactoryInterface.swift b/SOPT-Stamp-iOS/Projects/Presentation/Sources/ModuleFactoryInterface.swift index 73f662a1..96a5b436 100644 --- a/SOPT-Stamp-iOS/Projects/Presentation/Sources/ModuleFactoryInterface.swift +++ b/SOPT-Stamp-iOS/Projects/Presentation/Sources/ModuleFactoryInterface.swift @@ -22,4 +22,5 @@ public protocol ModuleFactoryInterface { func makeAlertVC(title: String, customButtonTitle: String) -> AlertVC func makeRankingVC() -> RankingVC func makeSettingVC() -> SettingVC + func makePasswordChangeVC() -> PasswordChangeVC } diff --git a/SOPT-Stamp-iOS/Projects/SOPT-Stamp-iOS/Sources/ModuleFactory/ModuleFactory.swift b/SOPT-Stamp-iOS/Projects/SOPT-Stamp-iOS/Sources/ModuleFactory/ModuleFactory.swift index ce3fcb2d..6bc901aa 100644 --- a/SOPT-Stamp-iOS/Projects/SOPT-Stamp-iOS/Sources/ModuleFactory/ModuleFactory.swift +++ b/SOPT-Stamp-iOS/Projects/SOPT-Stamp-iOS/Sources/ModuleFactory/ModuleFactory.swift @@ -118,4 +118,14 @@ extension ModuleFactory: ModuleFactoryInterface { settingVC.viewModel = viewModel return settingVC } + + public func makePasswordChangeVC() -> PasswordChangeVC { + let repository = SettingRepository(service: authService) + let useCase = DefaultPasswordChangeUseCase(repository: repository) + let viewModel = PasswordChangeViewModel(useCase: useCase) + let passwordChangeVC = PasswordChangeVC() + passwordChangeVC.factory = self + passwordChangeVC.viewModel = viewModel + return passwordChangeVC + } } From c4647e95ea1ecb7263372969b4d79f9b2aac32a5 Mon Sep 17 00:00:00 2001 From: Sejin Lee Date: Mon, 26 Dec 2022 15:53:52 +0900 Subject: [PATCH 3/9] =?UTF-8?q?[Feat]=20#57=20-=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EB=B3=80=EA=B2=BD=20=EB=B7=B0=20=EA=B8=B0?= =?UTF-8?q?=EC=B4=88=20UI=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Literals/StringLiterals.swift | 2 +- .../Repository/SettingRepository.swift | 4 ++ .../PasswordChangeVC.swift | 60 ++++++++++++++++++- .../Sources/Application/SceneDelegate.swift | 2 +- 4 files changed, 64 insertions(+), 4 deletions(-) diff --git a/SOPT-Stamp-iOS/Projects/Core/Sources/Literals/StringLiterals.swift b/SOPT-Stamp-iOS/Projects/Core/Sources/Literals/StringLiterals.swift index b5d6cf2e..b4a4995e 100644 --- a/SOPT-Stamp-iOS/Projects/Core/Sources/Literals/StringLiterals.swift +++ b/SOPT-Stamp-iOS/Projects/Core/Sources/Literals/StringLiterals.swift @@ -84,7 +84,7 @@ public struct I18N { public static let setting = "설정" public static let myinfo = "내 정보" public static let bioEdit = "한 마디 편집" - public static let passwordEdit = "비밀번호 편집" + public static let passwordEdit = "비밀번호 변경" public static let nicknameEdit = "닉네임 변경" public static let serviceUsagePolicy = "서비스 이용방침" public static let personalInfoPolicy = "개인정보처리방침" diff --git a/SOPT-Stamp-iOS/Projects/Data/Sources/Repository/SettingRepository.swift b/SOPT-Stamp-iOS/Projects/Data/Sources/Repository/SettingRepository.swift index 1c592e6e..721c8220 100644 --- a/SOPT-Stamp-iOS/Projects/Data/Sources/Repository/SettingRepository.swift +++ b/SOPT-Stamp-iOS/Projects/Data/Sources/Repository/SettingRepository.swift @@ -25,3 +25,7 @@ public class SettingRepository { extension SettingRepository: SettingRepositoryInterface { } + +extension SettingRepository: PasswordChangeRepositoryInterface { + +} diff --git a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/PasswordChangeVC.swift b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/PasswordChangeVC.swift index c44a8f91..974f3a35 100644 --- a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/PasswordChangeVC.swift +++ b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/PasswordChangeVC.swift @@ -9,25 +9,48 @@ import UIKit import Combine - -import Core import SnapKit import Then +import Core +import Domain +import DSKit + public class PasswordChangeVC: UIViewController { // MARK: - Properties + public var factory: ModuleFactoryInterface! public var viewModel: PasswordChangeViewModel! private var cancelBag = CancelBag() // MARK: - UI Components + + private lazy var naviBar = CustomNavigationBar(self, type: .titleWithLeftButton) + .setTitle(I18N.Setting.passwordEdit) + .setTitleTypoStyle(.h1) + + private lazy var passwordTextFieldView = CustomTextFieldView(type: .title) + .setTitle(I18N.SignUp.password) + .setTextFieldType(.password) + .setPlaceholder(I18N.SignUp.passwordTextFieldPlaceholder) + .setAlertDelegate(passwordCheckTextFieldView) + + private lazy var passwordCheckTextFieldView = CustomTextFieldView(type: .plain) + .setPlaceholder(I18N.SignUp.passwordCheckTextFieldPlaceholder) + .setTextFieldType(.password) + .setAlertLabelEnabled(I18N.SignUp.invalidPasswordForm) + + private let passwordChangeButton = CustomButton(title: I18N.Setting.passwordEdit) + .setEnabled(false) // MARK: - View Life Cycle public override func viewDidLoad() { super.viewDidLoad() self.bindViewModels() + self.setUI() + self.setLayout() } } @@ -41,3 +64,36 @@ extension PasswordChangeVC { } } + +// MARK: - UI & Layout + +extension PasswordChangeVC { + private func setUI() { + self.view.backgroundColor = .white + self.navigationController?.navigationBar.isHidden = true + } + + private func setLayout() { + self.view.addSubviews(naviBar, passwordTextFieldView, passwordCheckTextFieldView, passwordChangeButton) + + naviBar.snp.makeConstraints { make in + make.leading.top.trailing.equalTo(view.safeAreaLayoutGuide) + } + + passwordTextFieldView.snp.makeConstraints { make in + make.top.equalTo(naviBar.snp.bottom).offset(12) + make.leading.trailing.equalToSuperview().inset(20) + } + + passwordCheckTextFieldView.snp.makeConstraints { make in + make.top.equalTo(passwordTextFieldView.snp.bottom).offset(12) + make.leading.trailing.equalToSuperview().inset(20) + } + + passwordChangeButton.snp.makeConstraints { make in + make.top.equalTo(passwordCheckTextFieldView.snp.bottom).offset(26) + make.leading.trailing.equalToSuperview().inset(20) + make.height.equalTo(56) + } + } +} diff --git a/SOPT-Stamp-iOS/Projects/SOPT-Stamp-iOS/Sources/Application/SceneDelegate.swift b/SOPT-Stamp-iOS/Projects/SOPT-Stamp-iOS/Sources/Application/SceneDelegate.swift index 339bbc1e..312d92c6 100644 --- a/SOPT-Stamp-iOS/Projects/SOPT-Stamp-iOS/Sources/Application/SceneDelegate.swift +++ b/SOPT-Stamp-iOS/Projects/SOPT-Stamp-iOS/Sources/Application/SceneDelegate.swift @@ -20,7 +20,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { window = UIWindow(frame: scene.coordinateSpace.bounds) window?.windowScene = scene - let rootVC = ModuleFactory.shared.makeSignUpVC() + let rootVC = ModuleFactory.shared.makePasswordChangeVC() window?.rootViewController = UINavigationController(rootViewController: rootVC) window?.makeKeyAndVisible() } From 40a379aa242942c64c34cb0cc4bd952c9668707e Mon Sep 17 00:00:00 2001 From: Sejin Lee Date: Mon, 26 Dec 2022 16:10:19 +0900 Subject: [PATCH 4/9] =?UTF-8?q?[Feat]=20#57=20-=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EC=9E=85=EB=A0=A5=20=EC=8B=9C=20alert=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UseCase/PasswordChangeUseCase.swift | 64 +++++++++++++++++-- .../{ => VC}/PasswordChangeVC.swift | 32 +++++++++- .../ViewModel/PasswordChangeViewModel.swift | 48 ++++++++++++-- 3 files changed, 134 insertions(+), 10 deletions(-) rename SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/{ => VC}/PasswordChangeVC.swift (69%) diff --git a/SOPT-Stamp-iOS/Projects/Domain/Sources/UseCase/PasswordChangeUseCase.swift b/SOPT-Stamp-iOS/Projects/Domain/Sources/UseCase/PasswordChangeUseCase.swift index 35104a5c..51101f7f 100644 --- a/SOPT-Stamp-iOS/Projects/Domain/Sources/UseCase/PasswordChangeUseCase.swift +++ b/SOPT-Stamp-iOS/Projects/Domain/Sources/UseCase/PasswordChangeUseCase.swift @@ -6,22 +6,76 @@ // Copyright © 2022 SOPT-Stamp-iOS. All rights reserved. // +import Foundation import Combine -public protocol PasswordChangeUseCase { +import Core +public protocol PasswordChangeUseCase { + func checkPassword(password: String) + func checkAccordPassword(firstPassword: String, secondPassword: String) + func changePassword(password: String) + + var isPasswordFormValid: CurrentValueSubject { get set } + var isAccordPassword: CurrentValueSubject { get set } + var isValidForm: CurrentValueSubject { get set } + var passwordChangeSuccess: CurrentValueSubject { get set } } public class DefaultPasswordChangeUseCase { - + private let repository: PasswordChangeRepositoryInterface - private var cancelBag = Set() - + private var cancelBag = CancelBag() + + public var isPasswordFormValid = CurrentValueSubject(false) + public var isAccordPassword = CurrentValueSubject(false) + public var isValidForm = CurrentValueSubject(false) + public var passwordChangeSuccess = CurrentValueSubject(false) + public init(repository: PasswordChangeRepositoryInterface) { self.repository = repository + self.bindFormValid() } } extension DefaultPasswordChangeUseCase: PasswordChangeUseCase { - + public func checkPassword(password: String) { + checkPasswordForm(password: password) + } + + public func checkAccordPassword(firstPassword: String, secondPassword: String) { + checkAccordPasswordForm(firstPassword: firstPassword, secondPassword: secondPassword) + } + + public func changePassword(password: String) { + // repository 연결 + } +} + +// MARK: - Methods + +extension DefaultPasswordChangeUseCase { + func bindFormValid() { + isPasswordFormValid.combineLatest(isAccordPassword) + .map { (isPasswordValid, isAccordPassword) in + (isPasswordValid && isAccordPassword) + } + .sink { event in + print("PasswordChangeUseCase - completion: \(event)") + } receiveValue: { isValid in + self.isValidForm.send(isValid) + }.store(in: cancelBag) + } + + func checkPasswordForm(password: String) { + let passwordRegEx = "^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[!@#$%^&*()_+=-]).{8,15}" // 8자리 ~ 15자리 영어+숫자+특수문자 + let passwordTest = NSPredicate(format: "SELF MATCHES %@", passwordRegEx) + let isValid = passwordTest.evaluate(with: password) + isPasswordFormValid.send(isValid) + } + + func checkAccordPasswordForm(firstPassword: String, secondPassword: String) { + let isValid = (firstPassword == secondPassword) + isAccordPassword.send(isValid) + } } diff --git a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/PasswordChangeVC.swift b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift similarity index 69% rename from SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/PasswordChangeVC.swift rename to SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift index 974f3a35..ac2e6a4a 100644 --- a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/PasswordChangeVC.swift +++ b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift @@ -59,8 +59,38 @@ public class PasswordChangeVC: UIViewController { extension PasswordChangeVC { private func bindViewModels() { - let input = PasswordChangeViewModel.Input() + let passwordChangeButtonTapped = passwordChangeButton + .publisher(for: .touchUpInside) + .map { _ in self.passwordTextFieldView.text } + .asDriver() + + let input = PasswordChangeViewModel.Input( + passwordTextChanged: passwordTextFieldView.textChanged, + passwordCheckTextChanged: passwordCheckTextFieldView.textChanged, + passwordChangeButtonTapped: passwordChangeButtonTapped) + let output = self.viewModel.transform(from: input, cancelBag: self.cancelBag) + + output.passwordAlert + .map { $0.convertToTextFieldAlertType() } + .assign(to: passwordTextFieldView.kf.alertType, + on: passwordTextFieldView) + .store(in: cancelBag) + + output.passwordAccordAlert + .map { $0.convertToTextFieldAlertType() } + .assign(to: passwordTextFieldView.kf.alertType, + on: passwordCheckTextFieldView) + .store(in: cancelBag) + + output.isValidForm + .assign(to: \.isEnabled, on: passwordChangeButton) + .store(in: cancelBag) + + output.passwordChangeSuccessed.sink { [weak self] isSuccess in + guard let self = self else { return } + print(isSuccess) + }.store(in: cancelBag) } } diff --git a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/ViewModel/PasswordChangeViewModel.swift b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/ViewModel/PasswordChangeViewModel.swift index 96ab6ad8..a1ff9cb4 100644 --- a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/ViewModel/PasswordChangeViewModel.swift +++ b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/ViewModel/PasswordChangeViewModel.swift @@ -21,13 +21,18 @@ public class PasswordChangeViewModel: ViewModelType { // MARK: - Inputs public struct Input { - + let passwordTextChanged: Driver + let passwordCheckTextChanged: Driver + let passwordChangeButtonTapped: Driver } // MARK: - Outputs public struct Output { - + var passwordAlert = PassthroughSubject() + var passwordAccordAlert = PassthroughSubject() + var isValidForm = PassthroughSubject() + var passwordChangeSuccessed = PassthroughSubject() } // MARK: - init @@ -41,12 +46,47 @@ extension PasswordChangeViewModel { public func transform(from input: Input, cancelBag: CancelBag) -> Output { let output = Output() self.bindOutput(output: output, cancelBag: cancelBag) - // input,output 상관관계 작성 + + input.passwordTextChanged + .compactMap({ $0 }) + .sink { password in + self.useCase.checkPassword(password: password) + }.store(in: self.cancelBag) + + input.passwordTextChanged + .compactMap({ $0 }) + .combineLatest(input.passwordCheckTextChanged.compactMap({ $0 })) + .sink { (firstPassword, secondPassword) in + self.useCase.checkAccordPassword(firstPassword: firstPassword, secondPassword: secondPassword) + }.store(in: self.cancelBag) + + input.passwordChangeButtonTapped + .sink { signUpRequest in + // 버튼 클릭 액션 + }.store(in: self.cancelBag) return output } private func bindOutput(output: Output, cancelBag: CancelBag) { - + useCase.isPasswordFormValid.combineLatest(useCase.isAccordPassword).sink { event in + print("PasswordChangeViewModel - completion: \(event)") + } receiveValue: { (isFormValid, isAccordValid) in + if !isFormValid { + output.passwordAlert.send(.invalid(text: I18N.SignUp.invalidPasswordForm)) + } else if isFormValid && !isAccordValid { + output.passwordAlert.send(.valid(text: "")) + output.passwordAccordAlert.send(.invalid(text: (I18N.SignUp.passwordNotAccord))) + } else { + output.passwordAlert.send(.valid(text: "")) + output.passwordAccordAlert.send(.valid(text: "")) + } + }.store(in: cancelBag) + + useCase.isValidForm.sink { event in + print("PasswordChangeViewModel - completion: \(event)") + } receiveValue: { isValidForm in + output.isValidForm.send(isValidForm) + }.store(in: cancelBag) } } From 4eed4d3c8db236a5edf78edcdae446cde95cdd34 Mon Sep 17 00:00:00 2001 From: Sejin Lee Date: Mon, 26 Dec 2022 16:31:47 +0900 Subject: [PATCH 5/9] =?UTF-8?q?[Feat]=20#57=20-=20Data=20Layer=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Repository/SettingRepository.swift | 5 ++++- .../PasswordChangeRepositoryInterface.swift | 2 +- .../Modules/Network/Sources/API/AuthAPI.swift | 18 ++++++++++++++++++ .../Network/Sources/Service/AuthService.swift | 5 +++++ 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/SOPT-Stamp-iOS/Projects/Data/Sources/Repository/SettingRepository.swift b/SOPT-Stamp-iOS/Projects/Data/Sources/Repository/SettingRepository.swift index 721c8220..c2bbc5c7 100644 --- a/SOPT-Stamp-iOS/Projects/Data/Sources/Repository/SettingRepository.swift +++ b/SOPT-Stamp-iOS/Projects/Data/Sources/Repository/SettingRepository.swift @@ -27,5 +27,8 @@ extension SettingRepository: SettingRepositoryInterface { } extension SettingRepository: PasswordChangeRepositoryInterface { - + public func changePassword(password: String) -> AnyPublisher { + networkService.changePassword(password: password, userId: 12).map { statusCode in statusCode == 200 } + .eraseToAnyPublisher() + } } diff --git a/SOPT-Stamp-iOS/Projects/Domain/Sources/RepositoryInterface/PasswordChangeRepositoryInterface.swift b/SOPT-Stamp-iOS/Projects/Domain/Sources/RepositoryInterface/PasswordChangeRepositoryInterface.swift index c33321d4..78edcf9b 100644 --- a/SOPT-Stamp-iOS/Projects/Domain/Sources/RepositoryInterface/PasswordChangeRepositoryInterface.swift +++ b/SOPT-Stamp-iOS/Projects/Domain/Sources/RepositoryInterface/PasswordChangeRepositoryInterface.swift @@ -9,5 +9,5 @@ import Combine public protocol PasswordChangeRepositoryInterface { - + func changePassword(password: String) -> AnyPublisher } diff --git a/SOPT-Stamp-iOS/Projects/Modules/Network/Sources/API/AuthAPI.swift b/SOPT-Stamp-iOS/Projects/Modules/Network/Sources/API/AuthAPI.swift index 16d2605e..d148241f 100644 --- a/SOPT-Stamp-iOS/Projects/Modules/Network/Sources/API/AuthAPI.swift +++ b/SOPT-Stamp-iOS/Projects/Modules/Network/Sources/API/AuthAPI.swift @@ -14,17 +14,29 @@ import Moya public enum AuthAPI { case getNicknameAvailable(nickname: String) case getEmailAvailable(email: String) + case changePassword(password: String, userId: Int) } extension AuthAPI: BaseAPI { public static var apiType: APIType = .auth + // MARK: - Header + public var headers: [String: String]? { + switch self { + case .changePassword(_, let userId): + return HeaderType.userId(userId: userId).value + default: return HeaderType.json.value + } + } + // MARK: - Path public var path: String { switch self { case .getNicknameAvailable, .getEmailAvailable: return "" + case .changePassword: + return "password" } } @@ -33,6 +45,8 @@ extension AuthAPI: BaseAPI { switch self { case .getNicknameAvailable, .getEmailAvailable: return .get + case .changePassword: + return .put } } @@ -42,6 +56,8 @@ extension AuthAPI: BaseAPI { switch self { case .getNicknameAvailable, .getEmailAvailable: break + case .changePassword(let password, _): + params["password"] = password } return params } @@ -59,6 +75,8 @@ extension AuthAPI: BaseAPI { return .requestParameters(parameters: ["nickname": nickname], encoding: URLEncoding.queryString) case .getEmailAvailable(let email): return .requestParameters(parameters: ["email": email], encoding: URLEncoding.queryString) + case .changePassword: + return .requestParameters(parameters: bodyParameters ?? [:], encoding: parameterEncoding) default: return .requestPlain } diff --git a/SOPT-Stamp-iOS/Projects/Modules/Network/Sources/Service/AuthService.swift b/SOPT-Stamp-iOS/Projects/Modules/Network/Sources/Service/AuthService.swift index efb818d4..8b081f65 100644 --- a/SOPT-Stamp-iOS/Projects/Modules/Network/Sources/Service/AuthService.swift +++ b/SOPT-Stamp-iOS/Projects/Modules/Network/Sources/Service/AuthService.swift @@ -17,6 +17,7 @@ public typealias DefaultAuthService = BaseService public protocol AuthService { func getNicknameAvailable(nickname: String) -> AnyPublisher func getEmailAvailable(email: String) -> AnyPublisher + func changePassword(password: String, userId: Int) -> AnyPublisher } extension DefaultAuthService: AuthService { @@ -27,4 +28,8 @@ extension DefaultAuthService: AuthService { public func getEmailAvailable(email: String) -> AnyPublisher { return requestObjectInCombineNoResult(.getEmailAvailable(email: email)) } + + public func changePassword(password: String, userId: Int) -> AnyPublisher { + return requestObjectInCombineNoResult(.changePassword(password: password, userId: userId)) + } } From 8ffe786f9fba353b8a4ae1187f8f710b1b702bee Mon Sep 17 00:00:00 2001 From: Sejin Lee Date: Mon, 26 Dec 2022 16:32:19 +0900 Subject: [PATCH 6/9] =?UTF-8?q?[Feat]=20#57=20-=20Domain=20Layer=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EB=B0=8F=20VC=EC=99=80=20=EB=B0=94?= =?UTF-8?q?=EC=9D=B8=EB=94=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Domain/Sources/UseCase/PasswordChangeUseCase.swift | 7 ++++++- .../PasswordSettingScene/VC/PasswordChangeVC.swift | 1 - .../ViewModel/PasswordChangeViewModel.swift | 10 ++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/SOPT-Stamp-iOS/Projects/Domain/Sources/UseCase/PasswordChangeUseCase.swift b/SOPT-Stamp-iOS/Projects/Domain/Sources/UseCase/PasswordChangeUseCase.swift index 51101f7f..18989035 100644 --- a/SOPT-Stamp-iOS/Projects/Domain/Sources/UseCase/PasswordChangeUseCase.swift +++ b/SOPT-Stamp-iOS/Projects/Domain/Sources/UseCase/PasswordChangeUseCase.swift @@ -48,7 +48,12 @@ extension DefaultPasswordChangeUseCase: PasswordChangeUseCase { } public func changePassword(password: String) { - // repository 연결 + repository.changePassword(password: password) + .sink { event in + print("PasswordChangeUseCase: \(event)") + } receiveValue: { isSuccess in + self.passwordChangeSuccess.send(isSuccess) + }.store(in: cancelBag) } } diff --git a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift index ac2e6a4a..786056cd 100644 --- a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift +++ b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift @@ -92,7 +92,6 @@ extension PasswordChangeVC { print(isSuccess) }.store(in: cancelBag) } - } // MARK: - UI & Layout diff --git a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/ViewModel/PasswordChangeViewModel.swift b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/ViewModel/PasswordChangeViewModel.swift index a1ff9cb4..359e4aba 100644 --- a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/ViewModel/PasswordChangeViewModel.swift +++ b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/ViewModel/PasswordChangeViewModel.swift @@ -61,8 +61,8 @@ extension PasswordChangeViewModel { }.store(in: self.cancelBag) input.passwordChangeButtonTapped - .sink { signUpRequest in - // 버튼 클릭 액션 + .sink { password in + self.useCase.changePassword(password: password) }.store(in: self.cancelBag) return output @@ -88,5 +88,11 @@ extension PasswordChangeViewModel { } receiveValue: { isValidForm in output.isValidForm.send(isValidForm) }.store(in: cancelBag) + + useCase.passwordChangeSuccess.sink { event in + print("PasswordChangeViewModel - completion: \(event)") + } receiveValue: { isSuccess in + output.passwordChangeSuccessed.send(isSuccess) + }.store(in: cancelBag) } } From 3c9685f7dd01f20a34f1becd51f93b4f4c8d9461 Mon Sep 17 00:00:00 2001 From: Sejin Lee Date: Mon, 26 Dec 2022 17:05:12 +0900 Subject: [PATCH 7/9] =?UTF-8?q?[Feat]=20#57=20-=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EB=B3=80=EA=B2=BD=20=ED=9B=84=20SettingVC?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=8F=99=20=EB=B0=8F=20=ED=86=A0=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Core/Sources/Literals/StringLiterals.swift | 2 ++ .../VC/PasswordChangeVC.swift | 9 ++++++++- .../Sources/SettingScene/VC/SettingVC.swift | 18 +++++++++++++++--- .../Sources/Application/SceneDelegate.swift | 2 +- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/SOPT-Stamp-iOS/Projects/Core/Sources/Literals/StringLiterals.swift b/SOPT-Stamp-iOS/Projects/Core/Sources/Literals/StringLiterals.swift index b4a4995e..d8f705da 100644 --- a/SOPT-Stamp-iOS/Projects/Core/Sources/Literals/StringLiterals.swift +++ b/SOPT-Stamp-iOS/Projects/Core/Sources/Literals/StringLiterals.swift @@ -94,5 +94,7 @@ public struct I18N { public static let resetMission = "미션 초기화" public static let logout = "로그아웃" public static let withdraw = "탈퇴하기" + public static let passwordEditSuccess = "비밀번호가 변경되었습니다." + public static let passwordEditFail = "비밀번호 변경 실패" } } diff --git a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift index 786056cd..6f2d4e09 100644 --- a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift +++ b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift @@ -23,6 +23,8 @@ public class PasswordChangeVC: UIViewController { public var factory: ModuleFactoryInterface! public var viewModel: PasswordChangeViewModel! private var cancelBag = CancelBag() + + @Published public var passwordChangeSuccessed = false // MARK: - UI Components @@ -89,7 +91,12 @@ extension PasswordChangeVC { output.passwordChangeSuccessed.sink { [weak self] isSuccess in guard let self = self else { return } - print(isSuccess) + self.passwordChangeSuccessed = isSuccess + if isSuccess { + self.navigationController?.popViewController(animated: true) + } else { + self.showToast(message: I18N.Setting.passwordEditFail) + } }.store(in: cancelBag) } } diff --git a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/VC/SettingVC.swift b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/VC/SettingVC.swift index 57a67438..fd5d0635 100644 --- a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/VC/SettingVC.swift +++ b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/VC/SettingVC.swift @@ -29,8 +29,7 @@ public class SettingVC: UIViewController { .setTitle(I18N.Setting.setting) private let collectionViewFlowlayout = UICollectionViewFlowLayout() private lazy var collectionView = UICollectionView(frame: .zero, collectionViewLayout: collectionViewFlowlayout) - - + // MARK: - View Life Cycle public override func viewDidLoad() { @@ -62,6 +61,19 @@ extension SettingVC { self.collectionView.delegate = self self.collectionView.dataSource = self } + + private func showPasswordChangeView() { + let passwordChangeVC = self.factory.makePasswordChangeVC() + passwordChangeVC.$passwordChangeSuccessed + .sink { [weak self] isSuccess in + guard let self = self else { return } + if isSuccess { + self.showToast(message: I18N.Setting.passwordEditSuccess) + } + }.store(in: cancelBag) + + navigationController?.pushViewController(passwordChangeVC, animated: true) + } } // MARK: - UI & Layout @@ -106,7 +118,7 @@ extension SettingVC: UICollectionViewDelegate { case 0: print("한마디 편집") case 1: - print("비밀번호 변경") + showPasswordChangeView() default: print("닉네임 변경") } diff --git a/SOPT-Stamp-iOS/Projects/SOPT-Stamp-iOS/Sources/Application/SceneDelegate.swift b/SOPT-Stamp-iOS/Projects/SOPT-Stamp-iOS/Sources/Application/SceneDelegate.swift index 312d92c6..d3423e0f 100644 --- a/SOPT-Stamp-iOS/Projects/SOPT-Stamp-iOS/Sources/Application/SceneDelegate.swift +++ b/SOPT-Stamp-iOS/Projects/SOPT-Stamp-iOS/Sources/Application/SceneDelegate.swift @@ -20,7 +20,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { window = UIWindow(frame: scene.coordinateSpace.bounds) window?.windowScene = scene - let rootVC = ModuleFactory.shared.makePasswordChangeVC() + let rootVC = ModuleFactory.shared.makeSettingVC() window?.rootViewController = UINavigationController(rootViewController: rootVC) window?.makeKeyAndVisible() } From e08de37a466ea00c645d9c0d6a5e085c62d5efc1 Mon Sep 17 00:00:00 2001 From: Sejin Lee Date: Thu, 29 Dec 2022 00:47:00 +0900 Subject: [PATCH 8/9] =?UTF-8?q?[Chore]=20#57=20-=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EB=B3=80=EA=B2=BD=20=ED=9B=84=20Toast=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=A1=9C=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DSKit/Sources/Components/Toast.swift | 47 ++++++++++++++++++- .../VC/PasswordChangeVC.swift | 7 ++- .../Sources/SettingScene/VC/SettingVC.swift | 8 ---- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/SOPT-Stamp-iOS/Projects/Modules/DSKit/Sources/Components/Toast.swift b/SOPT-Stamp-iOS/Projects/Modules/DSKit/Sources/Components/Toast.swift index edc7410c..84e1823a 100644 --- a/SOPT-Stamp-iOS/Projects/Modules/DSKit/Sources/Components/Toast.swift +++ b/SOPT-Stamp-iOS/Projects/Modules/DSKit/Sources/Components/Toast.swift @@ -5,7 +5,6 @@ // Copyright © 2022 SOPT-Stamp-iOS. All rights reserved. // - import UIKit import SnapKit @@ -17,7 +16,7 @@ public extension UIViewController { } public class Toast { - static func show(message: String, controller: UIViewController) { + public static func show(message: String, controller: UIViewController) { let toastContainer = UIView() let toastLabel = UILabel() @@ -60,4 +59,48 @@ public class Toast { }) }) } + + public static func showInView(message: String, view: UIView) { + + let toastContainer = UIView() + let toastLabel = UILabel() + + toastContainer.backgroundColor = DSKitAsset.Colors.gray600.color + toastContainer.alpha = 1 + toastContainer.layer.cornerRadius = 9 + toastContainer.clipsToBounds = true + toastContainer.isUserInteractionEnabled = false + + toastLabel.textColor = .white + toastLabel.textAlignment = .center + toastLabel.setTypoStyle(.caption1) + toastLabel.text = message + toastLabel.clipsToBounds = true + toastLabel.numberOfLines = 0 + toastLabel.sizeToFit() + + toastContainer.addSubview(toastLabel) + view.addSubview(toastContainer) + + toastContainer.snp.makeConstraints { + $0.centerX.equalToSuperview() + $0.bottom.equalToSuperview().inset(40) + $0.width.equalTo(213) + $0.height.equalTo(44) + } + + toastLabel.snp.makeConstraints { + $0.center.equalToSuperview() + } + + UIView.animate(withDuration: 0.4, delay: 0.0, options: .curveEaseIn, animations: { + toastContainer.alpha = 1.0 + }, completion: { _ in + UIView.animate(withDuration: 0.4, delay: 1.0, options: .curveEaseOut, animations: { + toastContainer.alpha = 0.0 + }, completion: {_ in + toastContainer.removeFromSuperview() + }) + }) + } } diff --git a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift index 6f2d4e09..d4dd2874 100644 --- a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift +++ b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift @@ -23,9 +23,7 @@ public class PasswordChangeVC: UIViewController { public var factory: ModuleFactoryInterface! public var viewModel: PasswordChangeViewModel! private var cancelBag = CancelBag() - - @Published public var passwordChangeSuccessed = false - + // MARK: - UI Components private lazy var naviBar = CustomNavigationBar(self, type: .titleWithLeftButton) @@ -91,9 +89,10 @@ extension PasswordChangeVC { output.passwordChangeSuccessed.sink { [weak self] isSuccess in guard let self = self else { return } - self.passwordChangeSuccessed = isSuccess if isSuccess { self.navigationController?.popViewController(animated: true) + let window = self.view.window! + Toast.showInView(message: I18N.Setting.passwordEditSuccess, view: window) } else { self.showToast(message: I18N.Setting.passwordEditFail) } diff --git a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/VC/SettingVC.swift b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/VC/SettingVC.swift index fd5d0635..8f507cfd 100644 --- a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/VC/SettingVC.swift +++ b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/VC/SettingVC.swift @@ -64,14 +64,6 @@ extension SettingVC { private func showPasswordChangeView() { let passwordChangeVC = self.factory.makePasswordChangeVC() - passwordChangeVC.$passwordChangeSuccessed - .sink { [weak self] isSuccess in - guard let self = self else { return } - if isSuccess { - self.showToast(message: I18N.Setting.passwordEditSuccess) - } - }.store(in: cancelBag) - navigationController?.pushViewController(passwordChangeVC, animated: true) } } From b768a8b27fe691e62feed6fbf05cab63807a5ab2 Mon Sep 17 00:00:00 2001 From: Sejin Lee Date: Thu, 29 Dec 2022 01:06:20 +0900 Subject: [PATCH 9/9] =?UTF-8?q?[Chore]=20#57=20-=20Toast=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DSKit/Sources/Components/Toast.swift | 50 ++----------------- .../VC/PasswordChangeVC.swift | 2 +- 2 files changed, 4 insertions(+), 48 deletions(-) diff --git a/SOPT-Stamp-iOS/Projects/Modules/DSKit/Sources/Components/Toast.swift b/SOPT-Stamp-iOS/Projects/Modules/DSKit/Sources/Components/Toast.swift index 84e1823a..980cfb87 100644 --- a/SOPT-Stamp-iOS/Projects/Modules/DSKit/Sources/Components/Toast.swift +++ b/SOPT-Stamp-iOS/Projects/Modules/DSKit/Sources/Components/Toast.swift @@ -11,56 +11,12 @@ import SnapKit public extension UIViewController { func showToast(message: String) { - Toast.show(message: message, controller: self) + Toast.show(message: message, view: self.view, safeAreaBottomInset: self.safeAreaBottomInset()) } } public class Toast { - public static func show(message: String, controller: UIViewController) { - - let toastContainer = UIView() - let toastLabel = UILabel() - - toastContainer.backgroundColor = DSKitAsset.Colors.gray600.color - toastContainer.alpha = 1 - toastContainer.layer.cornerRadius = 9 - toastContainer.clipsToBounds = true - toastContainer.isUserInteractionEnabled = false - - toastLabel.textColor = .white - toastLabel.textAlignment = .center - toastLabel.setTypoStyle(.caption1) - toastLabel.text = message - toastLabel.clipsToBounds = true - toastLabel.numberOfLines = 0 - toastLabel.sizeToFit() - - toastContainer.addSubview(toastLabel) - controller.view.addSubview(toastContainer) - - toastContainer.snp.makeConstraints { - $0.centerX.equalToSuperview() - $0.bottom.equalTo(controller.safeAreaBottomInset()).inset(40) - $0.width.equalTo(213) - $0.height.equalTo(44) - } - - toastLabel.snp.makeConstraints { - $0.center.equalToSuperview() - } - - UIView.animate(withDuration: 0.4, delay: 0.0, options: .curveEaseIn, animations: { - toastContainer.alpha = 1.0 - }, completion: { _ in - UIView.animate(withDuration: 0.4, delay: 1.0, options: .curveEaseOut, animations: { - toastContainer.alpha = 0.0 - }, completion: {_ in - toastContainer.removeFromSuperview() - }) - }) - } - - public static func showInView(message: String, view: UIView) { + public static func show(message: String, view: UIView, safeAreaBottomInset: CGFloat = 0) { let toastContainer = UIView() let toastLabel = UILabel() @@ -84,7 +40,7 @@ public class Toast { toastContainer.snp.makeConstraints { $0.centerX.equalToSuperview() - $0.bottom.equalToSuperview().inset(40) + $0.bottom.equalToSuperview().inset(safeAreaBottomInset+40) $0.width.equalTo(213) $0.height.equalTo(44) } diff --git a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift index d4dd2874..ce4bfc8b 100644 --- a/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift +++ b/SOPT-Stamp-iOS/Projects/Presentation/Sources/SettingScene/PasswordSettingScene/VC/PasswordChangeVC.swift @@ -92,7 +92,7 @@ extension PasswordChangeVC { if isSuccess { self.navigationController?.popViewController(animated: true) let window = self.view.window! - Toast.showInView(message: I18N.Setting.passwordEditSuccess, view: window) + Toast.show(message: I18N.Setting.passwordEditSuccess, view: window, safeAreaBottomInset: self.safeAreaBottomInset()) } else { self.showToast(message: I18N.Setting.passwordEditFail) }