From 011fdb9bbdad586f0127d3f068074c85a9397b2a Mon Sep 17 00:00:00 2001 From: daye Date: Sat, 2 Dec 2023 15:26:13 +0900 Subject: [PATCH 01/17] =?UTF-8?q?#onb-55=20keychain=20service=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 --- onboard-iOS.xcodeproj/project.pbxproj | 4 +++ onboard-iOS/Utils/KeychainService.swift | 33 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 onboard-iOS/Utils/KeychainService.swift diff --git a/onboard-iOS.xcodeproj/project.pbxproj b/onboard-iOS.xcodeproj/project.pbxproj index 08ed6691..4b5666e7 100644 --- a/onboard-iOS.xcodeproj/project.pbxproj +++ b/onboard-iOS.xcodeproj/project.pbxproj @@ -84,6 +84,7 @@ 61D15BC92B1218F80060D089 /* TermsAgreementCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D15BC82B1218F80060D089 /* TermsAgreementCoordinator.swift */; }; 61D15BCB2B12EE390060D089 /* TermsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D15BCA2B12EE390060D089 /* TermsViewController.swift */; }; 61D15BCD2B1301BB0060D089 /* TermsReactor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D15BCC2B1301BB0060D089 /* TermsReactor.swift */; }; + 61D95E272B1AE82D007F93D7 /* KeychainService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D95E262B1AE82D007F93D7 /* KeychainService.swift */; }; AA09C27A2ACBE9BC00F51A96 /* KakaoSDKAuth in Frameworks */ = {isa = PBXBuildFile; productRef = AA09C2792ACBE9BC00F51A96 /* KakaoSDKAuth */; }; AA09C27C2ACBE9BC00F51A96 /* KakaoSDKCommon in Frameworks */ = {isa = PBXBuildFile; productRef = AA09C27B2ACBE9BC00F51A96 /* KakaoSDKCommon */; }; AA09C27E2ACBE9BC00F51A96 /* KakaoSDKUser in Frameworks */ = {isa = PBXBuildFile; productRef = AA09C27D2ACBE9BC00F51A96 /* KakaoSDKUser */; }; @@ -179,6 +180,7 @@ 61D15BC82B1218F80060D089 /* TermsAgreementCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsAgreementCoordinator.swift; sourceTree = ""; }; 61D15BCA2B12EE390060D089 /* TermsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsViewController.swift; sourceTree = ""; }; 61D15BCC2B1301BB0060D089 /* TermsReactor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsReactor.swift; sourceTree = ""; }; + 61D95E262B1AE82D007F93D7 /* KeychainService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainService.swift; sourceTree = ""; }; AA09C27F2ACBEB0100F51A96 /* KakaoLoginUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KakaoLoginUseCase.swift; sourceTree = ""; }; AA09C2812ACBF18C00F51A96 /* KakaoLoginManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KakaoLoginManager.swift; sourceTree = ""; }; AA7035FA2ADB81C700B26537 /* GroupRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupRepository.swift; sourceTree = ""; }; @@ -523,6 +525,7 @@ children = ( 611D8C9F2AB884C10074A55A /* AppleLoginManager.swift */, AA09C2812ACBF18C00F51A96 /* KakaoLoginManager.swift */, + 61D95E262B1AE82D007F93D7 /* KeychainService.swift */, ); path = Utils; sourceTree = ""; @@ -727,6 +730,7 @@ 611D8CEC2AC44D230074A55A /* TermsView.swift in Sources */, 1CA1BBCA2ADABFF9000C5F7E /* PopupState.swift in Sources */, 61AC7FCE2AB6DDE300B0B6B5 /* TestDTO.swift in Sources */, + 61D95E272B1AE82D007F93D7 /* KeychainService.swift in Sources */, 61342DAA2B1611FF00AE0268 /* NicknameReactor.swift in Sources */, 61AC7FEA2AB7309400B0B6B5 /* APIEventLogger.swift in Sources */, 1CA1BBCC2ADAC091000C5F7E /* PopupView.swift in Sources */, diff --git a/onboard-iOS/Utils/KeychainService.swift b/onboard-iOS/Utils/KeychainService.swift new file mode 100644 index 00000000..9c269617 --- /dev/null +++ b/onboard-iOS/Utils/KeychainService.swift @@ -0,0 +1,33 @@ +// +// KeychainService.swift +// onboard-iOS +// +// Created by 윤다예 on 12/2/23. +// + +import Foundation + +import SwiftKeychainWrapper + +enum KeychainKey: String { + case accessToken + case refreshToken +} + +final class KeychainService { + + private var keychain: KeychainWrapper { + return KeychainWrapper.standard + } + + func setKeychain(_ value: String, forKey keychainKey: KeychainKey) { + self.keychain.set(value, forKey: keychainKey.rawValue) + } + func getKeychainValue(forKey keychainKey: KeychainKey) -> String? { + return self.keychain.string(forKey: keychainKey.rawValue) + } + func removeKeychain(forKey keychainKey: KeychainKey) { + self.keychain.removeObject(forKey: keychainKey.rawValue) + } + +} From 3eb1d034a0a32f95e4f217430aa272aa46801d55 Mon Sep 17 00:00:00 2001 From: daye Date: Sat, 2 Dec 2023 16:22:38 +0900 Subject: [PATCH 02/17] =?UTF-8?q?#onb-55=20=ED=94=84=EB=A1=9C=ED=86=A0?= =?UTF-8?q?=EC=BD=9C=ED=99=94,=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EB=AA=85?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Enums/OnboardingStage.swift | 8 ++++++++ .../Domain/Entity/OnboardingEntity.swift | 8 ++++++++ onboard-iOS/Repository/DTO/AuthDTO.swift | 14 +------------- .../Repository/DTO/OnboardingDTO.swift | 8 ++++++++ onboard-iOS/Utils/KeychainService.swift | 19 +++++++++++++++---- 5 files changed, 40 insertions(+), 17 deletions(-) create mode 100644 Enums/OnboardingStage.swift create mode 100644 onboard-iOS/Domain/Entity/OnboardingEntity.swift create mode 100644 onboard-iOS/Repository/DTO/OnboardingDTO.swift diff --git a/Enums/OnboardingStage.swift b/Enums/OnboardingStage.swift new file mode 100644 index 00000000..86a0e1f6 --- /dev/null +++ b/Enums/OnboardingStage.swift @@ -0,0 +1,8 @@ +// +// OnboardingStage.swift +// onboard-iOS +// +// Created by 윤다예 on 12/2/23. +// + +import Foundation diff --git a/onboard-iOS/Domain/Entity/OnboardingEntity.swift b/onboard-iOS/Domain/Entity/OnboardingEntity.swift new file mode 100644 index 00000000..a13bd85b --- /dev/null +++ b/onboard-iOS/Domain/Entity/OnboardingEntity.swift @@ -0,0 +1,8 @@ +// +// OnboardingEntity.swift +// onboard-iOS +// +// Created by 윤다예 on 12/2/23. +// + +import Foundation diff --git a/onboard-iOS/Repository/DTO/AuthDTO.swift b/onboard-iOS/Repository/DTO/AuthDTO.swift index 24e888d7..2cf0190a 100644 --- a/onboard-iOS/Repository/DTO/AuthDTO.swift +++ b/onboard-iOS/Repository/DTO/AuthDTO.swift @@ -2,19 +2,7 @@ // AuthDTO.swift // onboard-iOS // -// Created by Daye on 2023/09/23. +// Created by 윤다예 on 12/2/23. // import Foundation - -enum AuthRequest { - struct Body: Encodable { - let type: String - let token: String - } -} - -struct AuthDTO: Decodable { - let accessToken: String - let refreshToken: String -} diff --git a/onboard-iOS/Repository/DTO/OnboardingDTO.swift b/onboard-iOS/Repository/DTO/OnboardingDTO.swift new file mode 100644 index 00000000..fe33076b --- /dev/null +++ b/onboard-iOS/Repository/DTO/OnboardingDTO.swift @@ -0,0 +1,8 @@ +// +// OnboardingDTO.swift +// onboard-iOS +// +// Created by 윤다예 on 12/2/23. +// + +import Foundation diff --git a/onboard-iOS/Utils/KeychainService.swift b/onboard-iOS/Utils/KeychainService.swift index 9c269617..363102f8 100644 --- a/onboard-iOS/Utils/KeychainService.swift +++ b/onboard-iOS/Utils/KeychainService.swift @@ -14,19 +14,30 @@ enum KeychainKey: String { case refreshToken } -final class KeychainService { +protocol KeychainService { + func set(_ value: String, forKey keychainKey: KeychainKey) + func value(forKey keychainKey: KeychainKey) -> String? + func remove(forKey keychainKey: KeychainKey) +} + +final class KeychainServiceImpl: KeychainService { private var keychain: KeychainWrapper { return KeychainWrapper.standard } - func setKeychain(_ value: String, forKey keychainKey: KeychainKey) { + /// 저장 + func set(_ value: String, forKey keychainKey: KeychainKey) { self.keychain.set(value, forKey: keychainKey.rawValue) } - func getKeychainValue(forKey keychainKey: KeychainKey) -> String? { + + /// 불러오기 + func value(forKey keychainKey: KeychainKey) -> String? { return self.keychain.string(forKey: keychainKey.rawValue) } - func removeKeychain(forKey keychainKey: KeychainKey) { + + /// 삭제 + func remove(forKey keychainKey: KeychainKey) { self.keychain.removeObject(forKey: keychainKey.rawValue) } From 47076ba635cc69e6f978d445b3d7681d5159ce6f Mon Sep 17 00:00:00 2001 From: daye Date: Sat, 2 Dec 2023 16:23:03 +0900 Subject: [PATCH 03/17] =?UTF-8?q?#onb-55=20=EC=98=A4=EB=A5=98=EB=B0=A9?= =?UTF-8?q?=EC=A7=80=EB=A5=BC=20=EC=9C=84=ED=95=B4=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=9A=A9=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- onboard-iOS/Presentation/Test/TestReactor.swift | 9 --------- 1 file changed, 9 deletions(-) diff --git a/onboard-iOS/Presentation/Test/TestReactor.swift b/onboard-iOS/Presentation/Test/TestReactor.swift index d4a14cd9..23686bc5 100644 --- a/onboard-iOS/Presentation/Test/TestReactor.swift +++ b/onboard-iOS/Presentation/Test/TestReactor.swift @@ -72,15 +72,6 @@ final class TestReactor: Reactor { return state } - func transform(mutation: Observable) -> Observable { - - let loginMutation = self.mutation( - result: self.appleUseCase.result - ) - - return Observable.merge(mutation, loginMutation) - } - } extension TestReactor { From 4317b0b1680fbdc126603678761d01bf8197332f Mon Sep 17 00:00:00 2001 From: daye Date: Sat, 2 Dec 2023 16:24:16 +0900 Subject: [PATCH 04/17] =?UTF-8?q?#onb-55=20=EC=98=A8=EB=B3=B4=EB=94=A9=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=A0=95=EB=8F=84=20=ED=99=95=EC=9D=B8=20api?= =?UTF-8?q?=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- onboard-iOS/Network/OBRouter.swift | 11 +++++++---- onboard-iOS/Repository/Auth/AuthRepository.swift | 9 +++++++++ onboard-iOS/Repository/DTO/AuthDTO.swift | 14 +++++++++++++- onboard-iOS/Repository/DTO/OnboardingDTO.swift | 5 +++++ 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/onboard-iOS/Network/OBRouter.swift b/onboard-iOS/Network/OBRouter.swift index 9012d101..c783380a 100644 --- a/onboard-iOS/Network/OBRouter.swift +++ b/onboard-iOS/Network/OBRouter.swift @@ -26,6 +26,7 @@ enum OBRouter: URLRequestConvertible { case testAPI case auth(body: Body) case terms + case onboarding case groupList(params: Params) case addGroup(body: Body) @@ -33,7 +34,7 @@ enum OBRouter: URLRequestConvertible { var method: HTTPMethod { switch self { - case .testAPI, .groupList, .terms: + case .testAPI, .groupList, .terms, .onboarding: return .get case .auth, .addGroup: return .post @@ -50,6 +51,8 @@ enum OBRouter: URLRequestConvertible { return "v1/auth/login" case .terms: return "api/v1/terms" + case .onboarding: + return "api/v1/user/me/onboarding" case .groupList, .addGroup: return "v1/group" } @@ -59,7 +62,7 @@ enum OBRouter: URLRequestConvertible { var header: Header? { switch self { - case .testAPI, .auth, .addGroup, .groupList, .terms: + case .testAPI, .auth, .addGroup, .groupList, .terms, .onboarding: return nil } } @@ -68,7 +71,7 @@ enum OBRouter: URLRequestConvertible { var body: Body? { switch self { - case .testAPI, .groupList, .terms: + case .testAPI, .groupList, .terms, .onboarding: return nil case let .auth(body), let .addGroup(body): @@ -80,7 +83,7 @@ enum OBRouter: URLRequestConvertible { var params: Params? { switch self { - case .testAPI, .auth, .addGroup, .terms: + case .testAPI, .auth, .addGroup, .terms, .onboarding: return nil case let .groupList(params): return params diff --git a/onboard-iOS/Repository/Auth/AuthRepository.swift b/onboard-iOS/Repository/Auth/AuthRepository.swift index 11454f6d..26ff5b4a 100644 --- a/onboard-iOS/Repository/Auth/AuthRepository.swift +++ b/onboard-iOS/Repository/Auth/AuthRepository.swift @@ -46,3 +46,12 @@ extension AuthDTO { ) } } + +extension OnboardingDTO { + var toDomain: OnboardingEntity { + return OnboardingEntity( + stages: self.onboarding, + groupId: self.mainGroupId + ) + } +} diff --git a/onboard-iOS/Repository/DTO/AuthDTO.swift b/onboard-iOS/Repository/DTO/AuthDTO.swift index 2cf0190a..24e888d7 100644 --- a/onboard-iOS/Repository/DTO/AuthDTO.swift +++ b/onboard-iOS/Repository/DTO/AuthDTO.swift @@ -2,7 +2,19 @@ // AuthDTO.swift // onboard-iOS // -// Created by 윤다예 on 12/2/23. +// Created by Daye on 2023/09/23. // import Foundation + +enum AuthRequest { + struct Body: Encodable { + let type: String + let token: String + } +} + +struct AuthDTO: Decodable { + let accessToken: String + let refreshToken: String +} diff --git a/onboard-iOS/Repository/DTO/OnboardingDTO.swift b/onboard-iOS/Repository/DTO/OnboardingDTO.swift index fe33076b..754c50ad 100644 --- a/onboard-iOS/Repository/DTO/OnboardingDTO.swift +++ b/onboard-iOS/Repository/DTO/OnboardingDTO.swift @@ -6,3 +6,8 @@ // import Foundation + +struct OnboardingDTO: Decodable { + let onboarding: [String] + let mainGroupId: Int? +} From 4852a3e15110e422c06a8dd9a3766474e1e7baf7 Mon Sep 17 00:00:00 2001 From: daye Date: Sat, 2 Dec 2023 16:24:47 +0900 Subject: [PATCH 05/17] =?UTF-8?q?#onb-55=20=EC=98=A8=EB=B3=B4=EB=94=A9=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=A0=95=EB=8F=84=20enum=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Enums/OnboardingStage.swift | 7 +++++ onboard-iOS.xcodeproj/project.pbxproj | 38 +++++++++++++++++---------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/Enums/OnboardingStage.swift b/Enums/OnboardingStage.swift index 86a0e1f6..3a2f99ee 100644 --- a/Enums/OnboardingStage.swift +++ b/Enums/OnboardingStage.swift @@ -6,3 +6,10 @@ // import Foundation + +enum OnboardingStage: String { + case terms = "TERMS" + case updateTerms = "UPDATE_TERMS" + case nickname = "NICKNAME" + case joinGroup = "JOIN_GROUP" +} diff --git a/onboard-iOS.xcodeproj/project.pbxproj b/onboard-iOS.xcodeproj/project.pbxproj index 4b5666e7..76502edb 100644 --- a/onboard-iOS.xcodeproj/project.pbxproj +++ b/onboard-iOS.xcodeproj/project.pbxproj @@ -44,7 +44,6 @@ 618175F52AC5722500B5E2A0 /* UILabel+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 618175F42AC5722500B5E2A0 /* UILabel+Extension.swift */; }; 618175F92AC5961500B5E2A0 /* TermsAgreementModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 618175F82AC5961500B5E2A0 /* TermsAgreementModalView.swift */; }; 618176162AD2C21000B5E2A0 /* AuthEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 618176152AD2C21000B5E2A0 /* AuthEntity.swift */; }; - 618176182AD2C22A00B5E2A0 /* AuthDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 618176172AD2C22A00B5E2A0 /* AuthDTO.swift */; }; 6181761E2AD2C66500B5E2A0 /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6181761D2AD2C66500B5E2A0 /* LoginViewController.swift */; }; 618176202AD2C6EE00B5E2A0 /* LoginReactor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6181761F2AD2C6EE00B5E2A0 /* LoginReactor.swift */; }; 618176232AD2C87C00B5E2A0 /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 618176222AD2C87C00B5E2A0 /* LoginView.swift */; }; @@ -85,6 +84,10 @@ 61D15BCB2B12EE390060D089 /* TermsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D15BCA2B12EE390060D089 /* TermsViewController.swift */; }; 61D15BCD2B1301BB0060D089 /* TermsReactor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D15BCC2B1301BB0060D089 /* TermsReactor.swift */; }; 61D95E272B1AE82D007F93D7 /* KeychainService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D95E262B1AE82D007F93D7 /* KeychainService.swift */; }; + 61D95E292B1B062B007F93D7 /* OnboardingEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D95E282B1B062B007F93D7 /* OnboardingEntity.swift */; }; + 61D95E2B2B1B06A5007F93D7 /* AuthDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D95E2A2B1B06A5007F93D7 /* AuthDTO.swift */; }; + 61D95E2D2B1B06BB007F93D7 /* OnboardingDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D95E2C2B1B06BB007F93D7 /* OnboardingDTO.swift */; }; + 61D95E322B1B0B5C007F93D7 /* OnboardingStage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D95E312B1B0B5C007F93D7 /* OnboardingStage.swift */; }; AA09C27A2ACBE9BC00F51A96 /* KakaoSDKAuth in Frameworks */ = {isa = PBXBuildFile; productRef = AA09C2792ACBE9BC00F51A96 /* KakaoSDKAuth */; }; AA09C27C2ACBE9BC00F51A96 /* KakaoSDKCommon in Frameworks */ = {isa = PBXBuildFile; productRef = AA09C27B2ACBE9BC00F51A96 /* KakaoSDKCommon */; }; AA09C27E2ACBE9BC00F51A96 /* KakaoSDKUser in Frameworks */ = {isa = PBXBuildFile; productRef = AA09C27D2ACBE9BC00F51A96 /* KakaoSDKUser */; }; @@ -107,7 +110,6 @@ 1C1F51AC2AE1640B0020AA71 /* JoinPopupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinPopupView.swift; sourceTree = ""; }; 1C1F51AE2AE16B600020AA71 /* ImagePopupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePopupView.swift; sourceTree = ""; }; 1C1F51B42AE2B7960020AA71 /* BottomSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomSheetView.swift; sourceTree = ""; }; - 1C5369432AC69C9600AC9AF0 /* AuthDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthDTO.swift; sourceTree = ""; }; 1CA1BBAE2ACF109A000C5F7E /* SpoqaHanSansNeo-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SpoqaHanSansNeo-Medium.ttf"; sourceTree = ""; }; 1CA1BBAF2ACF109A000C5F7E /* SpoqaHanSansNeo-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SpoqaHanSansNeo-Light.ttf"; sourceTree = ""; }; 1CA1BBB02ACF109B000C5F7E /* SpoqaHanSansNeo-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SpoqaHanSansNeo-Regular.ttf"; sourceTree = ""; }; @@ -143,7 +145,6 @@ 618175F42AC5722500B5E2A0 /* UILabel+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILabel+Extension.swift"; sourceTree = ""; }; 618175F82AC5961500B5E2A0 /* TermsAgreementModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsAgreementModalView.swift; sourceTree = ""; }; 618176152AD2C21000B5E2A0 /* AuthEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthEntity.swift; sourceTree = ""; }; - 618176172AD2C22A00B5E2A0 /* AuthDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthDTO.swift; sourceTree = ""; }; 6181761D2AD2C66500B5E2A0 /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = ""; }; 6181761F2AD2C6EE00B5E2A0 /* LoginReactor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginReactor.swift; sourceTree = ""; }; 618176222AD2C87C00B5E2A0 /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = ""; }; @@ -181,6 +182,10 @@ 61D15BCA2B12EE390060D089 /* TermsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsViewController.swift; sourceTree = ""; }; 61D15BCC2B1301BB0060D089 /* TermsReactor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsReactor.swift; sourceTree = ""; }; 61D95E262B1AE82D007F93D7 /* KeychainService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainService.swift; sourceTree = ""; }; + 61D95E282B1B062B007F93D7 /* OnboardingEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingEntity.swift; sourceTree = ""; }; + 61D95E2A2B1B06A5007F93D7 /* AuthDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthDTO.swift; sourceTree = ""; }; + 61D95E2C2B1B06BB007F93D7 /* OnboardingDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingDTO.swift; sourceTree = ""; }; + 61D95E312B1B0B5C007F93D7 /* OnboardingStage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingStage.swift; sourceTree = ""; }; AA09C27F2ACBEB0100F51A96 /* KakaoLoginUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KakaoLoginUseCase.swift; sourceTree = ""; }; AA09C2812ACBF18C00F51A96 /* KakaoLoginManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KakaoLoginManager.swift; sourceTree = ""; }; AA7035FA2ADB81C700B26537 /* GroupRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupRepository.swift; sourceTree = ""; }; @@ -377,6 +382,7 @@ 61AC7F922AB6D4A300B0B6B5 = { isa = PBXGroup; children = ( + 61D95E302B1B0B4E007F93D7 /* Enums */, 61AC7F9D2AB6D4A300B0B6B5 /* onboard-iOS */, 61AC7F9C2AB6D4A300B0B6B5 /* Products */, 61D15BC22B1215AC0060D089 /* Recovered References */, @@ -398,7 +404,6 @@ 6181762B2AD3D64F00B5E2A0 /* BaseComponents */, 611D8CA52ABECB910074A55A /* onboard-iOS.entitlements */, 61AC80032AB73A0F00B0B6B5 /* Extensions */, - 61AC7FE82AB72E5100B0B6B5 /* Enum */, 61AC7FDE2AB6E6C800B0B6B5 /* Utils */, 61AC7FB52AB6D69D00B0B6B5 /* Presentation */, 61AC7FB42AB6D68B00B0B6B5 /* Domain */, @@ -501,10 +506,10 @@ isa = PBXGroup; children = ( 61AC7FCD2AB6DDE300B0B6B5 /* TestDTO.swift */, - 618176172AD2C22A00B5E2A0 /* AuthDTO.swift */, - 1C5369432AC69C9600AC9AF0 /* AuthDTO.swift */, AA7036012ADB8A1400B26537 /* GroupDTO.swift */, 61342DB32B1619DD00AE0268 /* TermsAgreementDTO.swift */, + 61D95E2A2B1B06A5007F93D7 /* AuthDTO.swift */, + 61D95E2C2B1B06BB007F93D7 /* OnboardingDTO.swift */, ); path = DTO; sourceTree = ""; @@ -516,6 +521,7 @@ 618176152AD2C21000B5E2A0 /* AuthEntity.swift */, AA7035FF2ADB85A500B26537 /* GroupListEntity.swift */, 61342DB12B1619BE00AE0268 /* TermsAgreementEntity.swift */, + 61D95E282B1B062B007F93D7 /* OnboardingEntity.swift */, ); path = Entity; sourceTree = ""; @@ -530,13 +536,6 @@ path = Utils; sourceTree = ""; }; - 61AC7FE82AB72E5100B0B6B5 /* Enum */ = { - isa = PBXGroup; - children = ( - ); - path = Enum; - sourceTree = ""; - }; 61AC80032AB73A0F00B0B6B5 /* Extensions */ = { isa = PBXGroup; children = ( @@ -571,6 +570,14 @@ path = Coordinator; sourceTree = ""; }; + 61D95E302B1B0B4E007F93D7 /* Enums */ = { + isa = PBXGroup; + children = ( + 61D95E312B1B0B5C007F93D7 /* OnboardingStage.swift */, + ); + path = Enums; + sourceTree = ""; + }; AA7035F92ADB81B600B26537 /* Group */ = { isa = PBXGroup; children = ( @@ -731,6 +738,7 @@ 1CA1BBCA2ADABFF9000C5F7E /* PopupState.swift in Sources */, 61AC7FCE2AB6DDE300B0B6B5 /* TestDTO.swift in Sources */, 61D95E272B1AE82D007F93D7 /* KeychainService.swift in Sources */, + 61D95E292B1B062B007F93D7 /* OnboardingEntity.swift in Sources */, 61342DAA2B1611FF00AE0268 /* NicknameReactor.swift in Sources */, 61AC7FEA2AB7309400B0B6B5 /* APIEventLogger.swift in Sources */, 1CA1BBCC2ADAC091000C5F7E /* PopupView.swift in Sources */, @@ -741,7 +749,6 @@ 61D15BCD2B1301BB0060D089 /* TermsReactor.swift in Sources */, 61AC7FC42AB6DA0200B0B6B5 /* OBRouter.swift in Sources */, 61AC7FE72AB6EEB700B0B6B5 /* APIConstants.swift in Sources */, - 618176182AD2C22A00B5E2A0 /* AuthDTO.swift in Sources */, 61AC7F9F2AB6D4A300B0B6B5 /* AppDelegate.swift in Sources */, 618176202AD2C6EE00B5E2A0 /* LoginReactor.swift in Sources */, 1CA1BBC42ADABEBD000C5F7E /* TextField.swift in Sources */, @@ -749,6 +756,7 @@ AACCA91B2AE19A09000A4CDA /* NewGroupButton.swift in Sources */, 61CC3C242AEE876500AE8599 /* GoogleLoginManager.swift in Sources */, 61AC7FBC2AB6D72C00B0B6B5 /* TestView.swift in Sources */, + 61D95E2D2B1B06BB007F93D7 /* OnboardingDTO.swift in Sources */, 61AC7FC42AB6DA0200B0B6B5 /* OBRouter.swift in Sources */, 61AC7FE72AB6EEB700B0B6B5 /* APIConstants.swift in Sources */, 61342DAE2B16170E00AE0268 /* OBRequestInterceptor.swift in Sources */, @@ -763,6 +771,7 @@ AA9105642ADA242800DA2E96 /* GroupSearchReactor.swift in Sources */, 611D8CA22AB886B10074A55A /* AppleLoginUseCase.swift in Sources */, 1CA1BBD82AE0337E000C5F7E /* BaseButton.swift in Sources */, + 61D95E2B2B1B06A5007F93D7 /* AuthDTO.swift in Sources */, 61D15BC72B1217E70060D089 /* LoginCoordinator.swift in Sources */, 1C1F51B52AE2B7960020AA71 /* BottomSheetView.swift in Sources */, 1CA1BBBF2AD439BA000C5F7E /* IconImage.swift in Sources */, @@ -791,6 +800,7 @@ 618176312AD3D89200B5E2A0 /* UITableView+Extension.swift in Sources */, 618176282AD3C7E500B5E2A0 /* TermsAgreementItemView.swift in Sources */, 61342DA62B160D6400AE0268 /* NicknameView.swift in Sources */, + 61D95E322B1B0B5C007F93D7 /* OnboardingStage.swift in Sources */, 61AC7FC92AB6DB1800B0B6B5 /* OBNetworkManager.swift in Sources */, 61AC7FA12AB6D4A300B0B6B5 /* SceneDelegate.swift in Sources */, 6181762D2AD3D66D00B5E2A0 /* BaseTableViewCell.swift in Sources */, From 38f3019e85634d47860512205bd0551882852558 Mon Sep 17 00:00:00 2001 From: daye Date: Sat, 2 Dec 2023 16:25:03 +0900 Subject: [PATCH 06/17] =?UTF-8?q?#onb-55=20=EC=98=A8=EB=B3=B4=EB=94=A9=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=A0=95=EB=8F=84=20entity=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- onboard-iOS/Domain/Entity/OnboardingEntity.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/onboard-iOS/Domain/Entity/OnboardingEntity.swift b/onboard-iOS/Domain/Entity/OnboardingEntity.swift index a13bd85b..58f45553 100644 --- a/onboard-iOS/Domain/Entity/OnboardingEntity.swift +++ b/onboard-iOS/Domain/Entity/OnboardingEntity.swift @@ -6,3 +6,8 @@ // import Foundation + +struct OnboardingEntity { + let stages: [String] + let groupId: Int? +} From b492f0e8c4f1369a71d8ba6a8fba92bc8d0b230d Mon Sep 17 00:00:00 2001 From: daye Date: Sat, 2 Dec 2023 16:25:53 +0900 Subject: [PATCH 07/17] =?UTF-8?q?#onb-55=20=ED=82=A4=EC=B2=B4=EC=9D=B8?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=EB=B6=80=ED=84=B0=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EB=B6=88=EB=9F=AC=EC=99=80=20bearer=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- onboard-iOS/Network/OBRequestInterceptor.swift | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/onboard-iOS/Network/OBRequestInterceptor.swift b/onboard-iOS/Network/OBRequestInterceptor.swift index a4aadd27..44877fa7 100644 --- a/onboard-iOS/Network/OBRequestInterceptor.swift +++ b/onboard-iOS/Network/OBRequestInterceptor.swift @@ -11,6 +11,12 @@ import Alamofire final class OBRequestInterceptor: RequestInterceptor { + private var keychainService: KeychainService + + init(keychainService: KeychainService) { + self.keychainService = keychainService + } + func adapt( _ urlRequest: URLRequest, for session: Session, @@ -19,15 +25,13 @@ final class OBRequestInterceptor: RequestInterceptor { var request = urlRequest - // TODO: - 키체인, 소셜로그인 구현 후 삭제할 것 - let sugarToken = "77+9bVoF77+9ZjHvv71gDe+/vRNDKe+/vT1NZO+/" - - guard urlRequest.url?.absoluteString.hasPrefix(API.BASE_URL) == true else { + guard urlRequest.url?.absoluteString.hasPrefix(API.BASE_URL) == true, + let accessToken = self.keychainService.value(forKey: .accessToken) else { completion(.success(urlRequest)) return } - request.setValue("Bearer " + sugarToken, forHTTPHeaderField: "Authorization") + request.setValue("Bearer " + accessToken, forHTTPHeaderField: "Authorization") completion(.success(request)) } From 1da53a3272a5c113c5a353a8e73c5c2147ec37d0 Mon Sep 17 00:00:00 2001 From: daye Date: Sat, 2 Dec 2023 16:26:20 +0900 Subject: [PATCH 08/17] =?UTF-8?q?#onb-55=20keychainService=20=EC=A3=BC?= =?UTF-8?q?=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- onboard-iOS/Network/OBNetworkManager.swift | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/onboard-iOS/Network/OBNetworkManager.swift b/onboard-iOS/Network/OBNetworkManager.swift index 2d838b59..30887a1f 100644 --- a/onboard-iOS/Network/OBNetworkManager.swift +++ b/onboard-iOS/Network/OBNetworkManager.swift @@ -15,7 +15,9 @@ final class OBNetworkManager { private var session: Session - private let interceptor = OBRequestInterceptor() + private let interceptor = OBRequestInterceptor( + keychainService: KeychainServiceImpl() + ) private let apiLogger = APIEventLogger() private init() { @@ -37,12 +39,6 @@ final class OBNetworkManager { .validate(statusCode: 200..<300) .serializingDecodable(object) .response - - // if let afError = response.error as? AFError { - // if let data = response.data, let dataString = String(data: data, encoding: .utf8) { - // print(dataString) - // } - // } return response } From 80bc880739346682d90086c3609ddb6a0012ea08 Mon Sep 17 00:00:00 2001 From: daye Date: Sat, 2 Dec 2023 16:26:38 +0900 Subject: [PATCH 09/17] =?UTF-8?q?#onb-55=20=EC=98=A8=EB=B3=B4=EB=94=A9=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=A0=95=EB=8F=84=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=9D=BC=20=ED=99=94=EB=A9=B4=20=EC=9D=B4=EB=8F=99=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 --- .../Coordinator/LoginCoordinator.swift | 11 +++- .../Domain/Login/AppleLoginUseCase.swift | 29 +++++----- .../Domain/Login/KakaoLoginUseCase.swift | 20 +++---- .../Presentation/Login/LoginReactor.swift | 57 +++++++++---------- .../Repository/Auth/AuthRepository.swift | 22 +++++++ 5 files changed, 84 insertions(+), 55 deletions(-) diff --git a/onboard-iOS/Coordinator/LoginCoordinator.swift b/onboard-iOS/Coordinator/LoginCoordinator.swift index b6ff6031..4570803f 100644 --- a/onboard-iOS/Coordinator/LoginCoordinator.swift +++ b/onboard-iOS/Coordinator/LoginCoordinator.swift @@ -24,9 +24,11 @@ final class LoginCoordinator: Coordinator { func start() { let appleLoginManager = AppleLoginManagerImpl() let authRepository = AuthRepositoryImpl() + let keychainService = KeychainServiceImpl() let appleLoginUseCase = AppleLoginUseCaseImpl( appleLoginManager: appleLoginManager, - authRepository: authRepository + authRepository: authRepository, + keychainService: keychainService ) let kakaoLoginManager = KakaoLoginManagerImpl() @@ -53,4 +55,11 @@ extension LoginCoordinator: LoginCoordinatorNavigateDelegate { ) coordinator.start() } + + func showNicknameSetting() { + let coordinator = NicknameCoordinator( + navigationController: self.navigationController + ) + coordinator.start() + } } diff --git a/onboard-iOS/Domain/Login/AppleLoginUseCase.swift b/onboard-iOS/Domain/Login/AppleLoginUseCase.swift index 597f1316..b93957a8 100644 --- a/onboard-iOS/Domain/Login/AppleLoginUseCase.swift +++ b/onboard-iOS/Domain/Login/AppleLoginUseCase.swift @@ -10,7 +10,7 @@ import Foundation import RxSwift protocol AppleLoginUseCase { - var result: Observable { get } + var result: Observable { get } func signIn() async } @@ -22,22 +22,26 @@ protocol AppleLoginDelegate: AnyObject { protocol AuthRepository { // api 호출 및 토큰 가져오기 func signIn(req: AuthEntity.Req) async throws -> AuthEntity.Res + func onboarding() async throws -> OnboardingEntity } final class AppleLoginUseCaseImpl: AppleLoginUseCase { private let appleLoginManager: AppleLoginManager private let authRepository: AuthRepository + private let keychainService: KeychainService - var result: Observable - private let _result: PublishSubject = .init() + var result: Observable + private let _result: PublishSubject = .init() init( appleLoginManager: AppleLoginManager, - authRepository: AuthRepository + authRepository: AuthRepository, + keychainService: KeychainService ) { self.appleLoginManager = appleLoginManager self.authRepository = authRepository + self.keychainService = keychainService self.result = self._result } @@ -52,18 +56,15 @@ extension AppleLoginUseCaseImpl: AppleLoginDelegate { func success(token: String) { Task { - let result = try await self.authRepository.signIn( + let authResult = try await self.authRepository.signIn( req: AuthEntity.Req(type: .apple, token: token) ) - - // TODO: 온보딩 진행정보 받아오기 호출 구현 - // 임시로 false 처리 - let isExisted = false - print(result.accessToken) - print("-=-----==========") - print(result.refreshToken) - - self._result.onNext(isExisted) + self.keychainService.set(authResult.accessToken, forKey: .accessToken) + self.keychainService.set(authResult.refreshToken, forKey: .refreshToken) + + let onboardingResult = try await self.authRepository.onboarding() + + self._result.onNext(onboardingResult) } } } diff --git a/onboard-iOS/Domain/Login/KakaoLoginUseCase.swift b/onboard-iOS/Domain/Login/KakaoLoginUseCase.swift index 6532c946..21b24681 100644 --- a/onboard-iOS/Domain/Login/KakaoLoginUseCase.swift +++ b/onboard-iOS/Domain/Login/KakaoLoginUseCase.swift @@ -9,7 +9,7 @@ import Foundation import RxSwift protocol KakaoLoginUseCase { - var result: Observable { get } + var result: Observable { get } func signIn() async } @@ -22,9 +22,10 @@ final class KakaoLoginUseCaseImpl: KakaoLoginUseCase { private let kakaoLoginManager: KakaoLoginManager private let authRepository: AuthRepository + private let keychainService = KeychainServiceImpl() - var result: Observable - private let _result: PublishSubject = .init() + var result: Observable + private let _result: PublishSubject = .init() init( kakaoLoginManager: KakaoLoginManager, @@ -45,17 +46,16 @@ final class KakaoLoginUseCaseImpl: KakaoLoginUseCase { extension KakaoLoginUseCaseImpl: KakaoLoginDelegate { func sendOAuthToken(_ token: String) { Task { - let result = try await self.authRepository.signIn( + let authResult = try await self.authRepository.signIn( req: AuthEntity.Req(type: .kakao, token: token) ) - // TODO: 온보딩 진행정보 받아오기 호출 구현 - // 임시로 false 처리 - let isExisted = false - print(result.accessToken) - print(result.refreshToken) + self.keychainService.set(authResult.accessToken, forKey: .accessToken) + self.keychainService.set(authResult.refreshToken, forKey: .refreshToken) - self._result.onNext(isExisted) + let onboardingResult = try await self.authRepository.onboarding() + + self._result.onNext(onboardingResult) } } } diff --git a/onboard-iOS/Presentation/Login/LoginReactor.swift b/onboard-iOS/Presentation/Login/LoginReactor.swift index c8b6c9e1..be3227e0 100644 --- a/onboard-iOS/Presentation/Login/LoginReactor.swift +++ b/onboard-iOS/Presentation/Login/LoginReactor.swift @@ -19,12 +19,9 @@ final class LoginReactor: Reactor { case kakao } - enum Mutation { - case setLoginResult(result: String) - } - struct State { var result: String = "" + var stage: [OnboardingStage] = [] } private let coordinator: LoginCoordinator @@ -50,41 +47,41 @@ final class LoginReactor: Reactor { return self.googleLoginResult() case .kakao: - // TODO: Kakao Login return self.excuteKakaoLogin() } } - - func reduce(state: State, mutation: Mutation) -> State { - var state = state - - switch mutation { - case let .setLoginResult(token): - state.result = token - } - - return state - } - - func transform(mutation: Observable) -> Observable { - - let loginMutation = self.mutation( - result: self.appleUseCase.result - ) - - return Observable.merge(mutation, loginMutation) - } - } extension LoginReactor { - private func mutation(result: Observable) -> Observable { + private func mutation(result: Observable) -> Observable { return result.flatMap { response -> Observable in - if response { - return .just(.setLoginResult(result: "success")) + + guard let firstStage = response.stages.first, + let stage = OnboardingStage(rawValue: firstStage) else { + + // TODO: - 온보딩 남은 스테이지 없음 -> home으로 이동 +// if response.stages.isEmpty { +// return self.coordinator.showHome() +// } + return .empty() + } + + switch stage { + case .terms, .updateTerms: + DispatchQueue.main.async { + self.coordinator.showTermsAgreementView() + } + case .nickname: + DispatchQueue.main.async { + self.coordinator.showNicknameSetting() + } + case .joinGroup: + // TODO: - group 설정 페이지 이동 + break } - return .just(.setLoginResult(result: "fail")) + + return .empty() } } diff --git a/onboard-iOS/Repository/Auth/AuthRepository.swift b/onboard-iOS/Repository/Auth/AuthRepository.swift index 26ff5b4a..183b190a 100644 --- a/onboard-iOS/Repository/Auth/AuthRepository.swift +++ b/onboard-iOS/Repository/Auth/AuthRepository.swift @@ -36,6 +36,28 @@ final class AuthRepositoryImpl: AuthRepository { throw error } } + + func onboarding() async throws -> OnboardingEntity { + do { + let result = try await OBNetworkManager + .shared + .asyncRequest( + object: OnboardingDTO.self, + router: OBRouter.onboarding + ) + + guard let data = result.value else { + throw NetworkError.noExist + } + + return data.toDomain + + } catch { + print(error.localizedDescription) + + throw error + } + } } extension AuthDTO { From aaa3ea4735f9cfd55f68fb82c7154eaf58bfcf40 Mon Sep 17 00:00:00 2001 From: daye Date: Sat, 2 Dec 2023 16:35:57 +0900 Subject: [PATCH 10/17] =?UTF-8?q?#onb-55=20=EA=B7=B8=EB=A3=B9=EA=B2=80?= =?UTF-8?q?=EC=83=89=20=ED=99=94=EB=A9=B4=20=EC=A0=84=ED=99=98=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 --- onboard-iOS.xcodeproj/project.pbxproj | 4 +++ .../Coordinator/GroupSearchCoordinator.swift | 28 +++++++++++++++++++ .../Coordinator/LoginCoordinator.swift | 9 ++++++ .../Coordinator/NicknameCoordinator.swift | 13 +++++++++ .../Presentation/Login/LoginReactor.swift | 6 +++- .../Presentation/SignUp/NicknameReactor.swift | 1 + 6 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 onboard-iOS/Coordinator/GroupSearchCoordinator.swift diff --git a/onboard-iOS.xcodeproj/project.pbxproj b/onboard-iOS.xcodeproj/project.pbxproj index 76502edb..cb304f52 100644 --- a/onboard-iOS.xcodeproj/project.pbxproj +++ b/onboard-iOS.xcodeproj/project.pbxproj @@ -88,6 +88,7 @@ 61D95E2B2B1B06A5007F93D7 /* AuthDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D95E2A2B1B06A5007F93D7 /* AuthDTO.swift */; }; 61D95E2D2B1B06BB007F93D7 /* OnboardingDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D95E2C2B1B06BB007F93D7 /* OnboardingDTO.swift */; }; 61D95E322B1B0B5C007F93D7 /* OnboardingStage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D95E312B1B0B5C007F93D7 /* OnboardingStage.swift */; }; + 61D95E342B1B1417007F93D7 /* GroupSearchCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D95E332B1B1417007F93D7 /* GroupSearchCoordinator.swift */; }; AA09C27A2ACBE9BC00F51A96 /* KakaoSDKAuth in Frameworks */ = {isa = PBXBuildFile; productRef = AA09C2792ACBE9BC00F51A96 /* KakaoSDKAuth */; }; AA09C27C2ACBE9BC00F51A96 /* KakaoSDKCommon in Frameworks */ = {isa = PBXBuildFile; productRef = AA09C27B2ACBE9BC00F51A96 /* KakaoSDKCommon */; }; AA09C27E2ACBE9BC00F51A96 /* KakaoSDKUser in Frameworks */ = {isa = PBXBuildFile; productRef = AA09C27D2ACBE9BC00F51A96 /* KakaoSDKUser */; }; @@ -186,6 +187,7 @@ 61D95E2A2B1B06A5007F93D7 /* AuthDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthDTO.swift; sourceTree = ""; }; 61D95E2C2B1B06BB007F93D7 /* OnboardingDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingDTO.swift; sourceTree = ""; }; 61D95E312B1B0B5C007F93D7 /* OnboardingStage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingStage.swift; sourceTree = ""; }; + 61D95E332B1B1417007F93D7 /* GroupSearchCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupSearchCoordinator.swift; sourceTree = ""; }; AA09C27F2ACBEB0100F51A96 /* KakaoLoginUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KakaoLoginUseCase.swift; sourceTree = ""; }; AA09C2812ACBF18C00F51A96 /* KakaoLoginManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KakaoLoginManager.swift; sourceTree = ""; }; AA7035FA2ADB81C700B26537 /* GroupRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupRepository.swift; sourceTree = ""; }; @@ -566,6 +568,7 @@ 61D15BC62B1217E70060D089 /* LoginCoordinator.swift */, 61D15BC82B1218F80060D089 /* TermsAgreementCoordinator.swift */, 61342DAB2B1612AA00AE0268 /* NicknameCoordinator.swift */, + 61D95E332B1B1417007F93D7 /* GroupSearchCoordinator.swift */, ); path = Coordinator; sourceTree = ""; @@ -731,6 +734,7 @@ files = ( 618176352AD5902300B5E2A0 /* TermsAgreementViewController.swift in Sources */, 61342DAC2B1612AA00AE0268 /* NicknameCoordinator.swift in Sources */, + 61D95E342B1B1417007F93D7 /* GroupSearchCoordinator.swift in Sources */, 61342DB42B1619DD00AE0268 /* TermsAgreementDTO.swift in Sources */, 618175F52AC5722500B5E2A0 /* UILabel+Extension.swift in Sources */, 611D8CEE2AC44EEA0074A55A /* UIView+SwiftUI+Extension.swift in Sources */, diff --git a/onboard-iOS/Coordinator/GroupSearchCoordinator.swift b/onboard-iOS/Coordinator/GroupSearchCoordinator.swift new file mode 100644 index 00000000..081bfd7b --- /dev/null +++ b/onboard-iOS/Coordinator/GroupSearchCoordinator.swift @@ -0,0 +1,28 @@ +// +// GroupSearchCoordinator.swift +// onboard-iOS +// +// Created by 윤다예 on 12/2/23. +// + +import UIKit + +final class GroupSearchCoordinator: Coordinator { + + var childCoordinators: [Coordinator] = [] + + private var navigationController: UINavigationController? + + init(navigationController: UINavigationController?) { + self.navigationController = navigationController + } + + func start() { + let repository = GroupRepositoryImpl() + let useCase = GroupSearchUseCaseImpl(groupRepository: repository) + let reactor = GroupSearchReactor(useCase: useCase) + let viewController = GroupSearchViewController(reactor: reactor) + + self.navigationController?.pushViewController(viewController, animated: true) + } +} diff --git a/onboard-iOS/Coordinator/LoginCoordinator.swift b/onboard-iOS/Coordinator/LoginCoordinator.swift index 4570803f..a9b5f435 100644 --- a/onboard-iOS/Coordinator/LoginCoordinator.swift +++ b/onboard-iOS/Coordinator/LoginCoordinator.swift @@ -9,6 +9,8 @@ import UIKit protocol LoginCoordinatorNavigateDelegate: AnyObject { func showTermsAgreementView() + func showNicknameSetting() + func showGroupSearch() } final class LoginCoordinator: Coordinator { @@ -62,4 +64,11 @@ extension LoginCoordinator: LoginCoordinatorNavigateDelegate { ) coordinator.start() } + + func showGroupSearch() { + let coordinator = GroupSearchCoordinator( + navigationController: self.navigationController + ) + coordinator.start() + } } diff --git a/onboard-iOS/Coordinator/NicknameCoordinator.swift b/onboard-iOS/Coordinator/NicknameCoordinator.swift index e2e93326..45cea929 100644 --- a/onboard-iOS/Coordinator/NicknameCoordinator.swift +++ b/onboard-iOS/Coordinator/NicknameCoordinator.swift @@ -7,6 +7,10 @@ import UIKit +protocol NicknameCoordinatorNavigateDelegate: AnyObject { + func showGroupSearch() +} + final class NicknameCoordinator: Coordinator { var childCoordinators: [Coordinator] = [] @@ -24,3 +28,12 @@ final class NicknameCoordinator: Coordinator { self.navigationController?.pushViewController(viewController, animated: true) } } + +extension NicknameCoordinator: NicknameCoordinatorNavigateDelegate { + func showGroupSearch() { + let coordinator = GroupSearchCoordinator( + navigationController: self.navigationController + ) + coordinator.start() + } +} diff --git a/onboard-iOS/Presentation/Login/LoginReactor.swift b/onboard-iOS/Presentation/Login/LoginReactor.swift index be3227e0..96410577 100644 --- a/onboard-iOS/Presentation/Login/LoginReactor.swift +++ b/onboard-iOS/Presentation/Login/LoginReactor.swift @@ -18,6 +18,8 @@ final class LoginReactor: Reactor { case google case kakao } + + enum Mutation { } struct State { var result: String = "" @@ -77,7 +79,9 @@ extension LoginReactor { self.coordinator.showNicknameSetting() } case .joinGroup: - // TODO: - group 설정 페이지 이동 + DispatchQueue.main.async { + self.coordinator.showGroupSearch() + } break } diff --git a/onboard-iOS/Presentation/SignUp/NicknameReactor.swift b/onboard-iOS/Presentation/SignUp/NicknameReactor.swift index 0afafd6f..2cff48d4 100644 --- a/onboard-iOS/Presentation/SignUp/NicknameReactor.swift +++ b/onboard-iOS/Presentation/SignUp/NicknameReactor.swift @@ -35,6 +35,7 @@ final class NicknameReactor: Reactor { switch action { case .confirm: + self.coordinator.showGroupSearch() return .empty() } } From 26980acbe9e0ac604c5ae4c4847ee6c4f81b0250 Mon Sep 17 00:00:00 2001 From: daye Date: Sat, 2 Dec 2023 17:45:53 +0900 Subject: [PATCH 11/17] =?UTF-8?q?#onb-55=20=EB=B2=84=ED=8A=BC=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=20=EA=B0=80=EB=8A=A5=20=EC=97=AC=EB=B6=80=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- onboard-iOS/DesignSystem/Values/BaseButton.swift | 4 ++++ .../Entity/{TermsAgreementEntity.swift => TermsEntity.swift} | 4 ++-- .../DTO/{TermsAgreementDTO.swift => TermsDTO.swift} | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) rename onboard-iOS/Domain/Entity/{TermsAgreementEntity.swift => TermsEntity.swift} (79%) rename onboard-iOS/Repository/DTO/{TermsAgreementDTO.swift => TermsDTO.swift} (88%) diff --git a/onboard-iOS/DesignSystem/Values/BaseButton.swift b/onboard-iOS/DesignSystem/Values/BaseButton.swift index 64de25ee..fbd85f2e 100644 --- a/onboard-iOS/DesignSystem/Values/BaseButton.swift +++ b/onboard-iOS/DesignSystem/Values/BaseButton.swift @@ -53,10 +53,14 @@ class BaseButton: UIButton { self.bgColor = Colors.Orange_10 self.textColor = Colors.Gray_2 self.typo = Font.Typography.label3_B + self.isEnabled = true + case .disabled: self.bgColor = Colors.Gray_4 self.textColor = Colors.Gray_7 self.typo = Font.Typography.label3_M + self.isEnabled = false + case .pressed: self.bgColor = Colors.Gray_15 self.textColor = Colors.Gray_1 diff --git a/onboard-iOS/Domain/Entity/TermsAgreementEntity.swift b/onboard-iOS/Domain/Entity/TermsEntity.swift similarity index 79% rename from onboard-iOS/Domain/Entity/TermsAgreementEntity.swift rename to onboard-iOS/Domain/Entity/TermsEntity.swift index 07024eda..ab0d1083 100644 --- a/onboard-iOS/Domain/Entity/TermsAgreementEntity.swift +++ b/onboard-iOS/Domain/Entity/TermsEntity.swift @@ -1,5 +1,5 @@ // -// TermsAgreementEntity.swift +// TermsEntity.swift // onboard-iOS // // Created by 윤다예 on 11/28/23. @@ -7,7 +7,7 @@ import Foundation -struct TermsAgreementEntity { +struct TermsEntity { let terms: [Term] struct Term { diff --git a/onboard-iOS/Repository/DTO/TermsAgreementDTO.swift b/onboard-iOS/Repository/DTO/TermsDTO.swift similarity index 88% rename from onboard-iOS/Repository/DTO/TermsAgreementDTO.swift rename to onboard-iOS/Repository/DTO/TermsDTO.swift index ef08b469..cbc42347 100644 --- a/onboard-iOS/Repository/DTO/TermsAgreementDTO.swift +++ b/onboard-iOS/Repository/DTO/TermsDTO.swift @@ -7,7 +7,7 @@ import Foundation -struct TermsAgreementDTO: Decodable { +struct TermsDTO: Decodable { let contents: [Term] struct Term: Decodable { @@ -17,3 +17,5 @@ struct TermsAgreementDTO: Decodable { let isRequired: Bool } } + +struct From 7c0bd9eada3bf59bfd108cc338cb0d71c0460b06 Mon Sep 17 00:00:00 2001 From: daye Date: Sun, 3 Dec 2023 11:57:59 +0900 Subject: [PATCH 12/17] =?UTF-8?q?#onb-55=20api=20=EC=A0=95=EB=A6=AC,=20url?= =?UTF-8?q?=20=EC=A3=BC=EC=86=8C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- onboard-iOS/Network/APIConstants.swift | 2 +- onboard-iOS/Network/OBRouter.swift | 86 ++++++++++++++++++++------ 2 files changed, 68 insertions(+), 20 deletions(-) diff --git a/onboard-iOS/Network/APIConstants.swift b/onboard-iOS/Network/APIConstants.swift index d4dcab9e..935800ee 100644 --- a/onboard-iOS/Network/APIConstants.swift +++ b/onboard-iOS/Network/APIConstants.swift @@ -9,7 +9,7 @@ import Foundation import Alamofire enum API { - static let BASE_URL = "http://sandbox-api.onboardgame.co.kr/" + static let BASE_URL = "http://sandbox-api.onboardgame.co.kr/api/" } class APISession { diff --git a/onboard-iOS/Network/OBRouter.swift b/onboard-iOS/Network/OBRouter.swift index c783380a..b5143653 100644 --- a/onboard-iOS/Network/OBRouter.swift +++ b/onboard-iOS/Network/OBRouter.swift @@ -26,6 +26,7 @@ enum OBRouter: URLRequestConvertible { case testAPI case auth(body: Body) case terms + case agreementTerms(body: Body) case onboarding case groupList(params: Params) case addGroup(body: Body) @@ -34,10 +35,37 @@ enum OBRouter: URLRequestConvertible { var method: HTTPMethod { switch self { - case .testAPI, .groupList, .terms, .onboarding: + // Group + case .groupList, .addGroup: + return .get + + // Match + + // Terms + case .terms: return .get - case .auth, .addGroup: + + case .agreementTerms: + return .post + + // Auth + case .auth: return .post + + // Setting + + // User + case .onboarding: + return .get + + // Game + + // Member + + // Etc + case .testAPI: + return .get + } } @@ -45,16 +73,34 @@ enum OBRouter: URLRequestConvertible { var path: String { switch self { - case .testAPI: - return "v1/test" - case .auth: - return "v1/auth/login" - case .terms: - return "api/v1/terms" - case .onboarding: - return "api/v1/user/me/onboarding" - case .groupList, .addGroup: - return "v1/group" + // Group + case .groupList, .addGroup: + return "v1/group" + + // Match + + // Terms + case .terms, .agreementTerms: + return "v1/terms" + + // Auth + case .auth: + return "v1/auth/login" + + // Setting + + // User + case .onboarding: + return "v1/user/me/onboarding" + + // Game + + // Member + + // Etc + case .testAPI: + return "v1/test" + } } @@ -62,7 +108,7 @@ enum OBRouter: URLRequestConvertible { var header: Header? { switch self { - case .testAPI, .auth, .addGroup, .groupList, .terms, .onboarding: + default: return nil } } @@ -71,11 +117,13 @@ enum OBRouter: URLRequestConvertible { var body: Body? { switch self { - case .testAPI, .groupList, .terms, .onboarding: - return nil - - case let .auth(body), let .addGroup(body): + case let .auth(body), + let .agreementTerms(body), + let .addGroup(body): return body + + default: + return nil } } @@ -83,10 +131,10 @@ enum OBRouter: URLRequestConvertible { var params: Params? { switch self { - case .testAPI, .auth, .addGroup, .terms, .onboarding: - return nil case let .groupList(params): return params + default: + return nil } } From d9d042f51c418e90f08844ac4afc041257f53512 Mon Sep 17 00:00:00 2001 From: daye Date: Sun, 3 Dec 2023 11:59:22 +0900 Subject: [PATCH 13/17] =?UTF-8?q?#onb-55=20=EC=95=BD=EA=B4=80=20=EB=8F=99?= =?UTF-8?q?=EC=9D=98=20api=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TermsAgreementCoordinator.swift | 7 +- onboard-iOS/Domain/Entity/TermsEntity.swift | 7 ++ .../Domain/Login/AppleLoginUseCase.swift | 6 ++ .../Domain/Login/KakaoLoginUseCase.swift | 6 ++ .../Domain/Login/TermsAgreementUseCase.swift | 26 +++++-- .../Presentation/Login/LoginReactor.swift | 32 +++++--- .../SignUp/TermsAgreementReactor.swift | 75 ++++++++++++++++--- .../Auth/TermsAgreementRepository.swift | 37 +++++++-- onboard-iOS/Repository/DTO/TermsDTO.swift | 11 ++- 9 files changed, 170 insertions(+), 37 deletions(-) diff --git a/onboard-iOS/Coordinator/TermsAgreementCoordinator.swift b/onboard-iOS/Coordinator/TermsAgreementCoordinator.swift index 8900917f..fc4c22a4 100644 --- a/onboard-iOS/Coordinator/TermsAgreementCoordinator.swift +++ b/onboard-iOS/Coordinator/TermsAgreementCoordinator.swift @@ -29,9 +29,10 @@ final class TermsAgreementCoordinator: Coordinator { rootViewController: TermsAgreementViewController(reactor: reactor) ) viewController.modalPresentationStyle = .overFullScreen - - self.navigationController?.present(viewController, animated: false) - self.navigationController = viewController + DispatchQueue.main.async { + self.navigationController?.present(viewController, animated: false) + self.navigationController = viewController + } } func showTerms(url: String) { diff --git a/onboard-iOS/Domain/Entity/TermsEntity.swift b/onboard-iOS/Domain/Entity/TermsEntity.swift index ab0d1083..f3053b5d 100644 --- a/onboard-iOS/Domain/Entity/TermsEntity.swift +++ b/onboard-iOS/Domain/Entity/TermsEntity.swift @@ -17,3 +17,10 @@ struct TermsEntity { let isReuired: Bool } } + +enum TermsAgreementEntity { + struct Req { + let agreeList: [String] + let disagreeList: [String] + } +} diff --git a/onboard-iOS/Domain/Login/AppleLoginUseCase.swift b/onboard-iOS/Domain/Login/AppleLoginUseCase.swift index b93957a8..f687dd40 100644 --- a/onboard-iOS/Domain/Login/AppleLoginUseCase.swift +++ b/onboard-iOS/Domain/Login/AppleLoginUseCase.swift @@ -46,8 +46,14 @@ final class AppleLoginUseCaseImpl: AppleLoginUseCase { } func signIn() async { + self.removeKeychainData() self.appleLoginManager.excute(delegate: self) } + + private func removeKeychainData() { + self.keychainService.remove(forKey: .accessToken) + self.keychainService.remove(forKey: .refreshToken) + } } // MARK: - Apple login delegate diff --git a/onboard-iOS/Domain/Login/KakaoLoginUseCase.swift b/onboard-iOS/Domain/Login/KakaoLoginUseCase.swift index 21b24681..f17b2baa 100644 --- a/onboard-iOS/Domain/Login/KakaoLoginUseCase.swift +++ b/onboard-iOS/Domain/Login/KakaoLoginUseCase.swift @@ -37,8 +37,14 @@ final class KakaoLoginUseCaseImpl: KakaoLoginUseCase { } func signIn() async { + self.removeKeychainData() self.kakaoLoginManager.excute(delegate: self) } + + private func removeKeychainData() { + self.keychainService.remove(forKey: .accessToken) + self.keychainService.remove(forKey: .refreshToken) + } } // MARK: - Kakao Login delegate diff --git a/onboard-iOS/Domain/Login/TermsAgreementUseCase.swift b/onboard-iOS/Domain/Login/TermsAgreementUseCase.swift index 1481b9b8..0a945a0d 100644 --- a/onboard-iOS/Domain/Login/TermsAgreementUseCase.swift +++ b/onboard-iOS/Domain/Login/TermsAgreementUseCase.swift @@ -10,30 +10,44 @@ import Foundation import RxSwift protocol TermsAgreementUseCase { - var result: Observable<[TermsAgreementEntity.Term]> { get set } + var termsList: Observable<[TermsEntity.Term]> { get set } + var agreeResult: Observable { get set } func fetch() async + func agreeTerms(req: TermsAgreementEntity.Req) async } protocol TermsAgreementRepository { - func fetch() async throws -> [TermsAgreementEntity.Term] + func fetch() async throws -> [TermsEntity.Term] + func agreeTerms(req: TermsAgreementEntity.Req) async throws -> Bool } final class TermsAgreementUseCaseImpl: TermsAgreementUseCase { private let repository: TermsAgreementRepository - var result: Observable<[TermsAgreementEntity.Term]> - private let _result: PublishSubject<[TermsAgreementEntity.Term]> = .init() + var termsList: Observable<[TermsEntity.Term]> + private let _termsList: PublishSubject<[TermsEntity.Term]> = .init() + + var agreeResult: Observable + private let _agreeResult: PublishSubject = .init() init(repository: TermsAgreementRepository) { self.repository = repository - self.result = _result + self.termsList = _termsList + self.agreeResult = _agreeResult } func fetch() async { Task { let result = try await self.repository.fetch() - self._result.onNext(result) + self._termsList.onNext(result) + } + } + + func agreeTerms(req: TermsAgreementEntity.Req) async { + Task { + let result = try await self.repository.agreeTerms(req: req) + self._agreeResult.onNext(result) } } } diff --git a/onboard-iOS/Presentation/Login/LoginReactor.swift b/onboard-iOS/Presentation/Login/LoginReactor.swift index 96410577..2cdfd7dc 100644 --- a/onboard-iOS/Presentation/Login/LoginReactor.swift +++ b/onboard-iOS/Presentation/Login/LoginReactor.swift @@ -52,6 +52,23 @@ final class LoginReactor: Reactor { return self.excuteKakaoLogin() } } + + func transform(mutation: Observable) -> Observable { + + let appleMutation = self.mutation( + result: self.appleUseCase.result + ) + + let kakaoMutation = self.mutation( + result: self.kakaoUseCase.result + ) + + return Observable.merge([ + mutation, + appleMutation, + kakaoMutation + ]) + } } extension LoginReactor { @@ -71,18 +88,13 @@ extension LoginReactor { switch stage { case .terms, .updateTerms: - DispatchQueue.main.async { - self.coordinator.showTermsAgreementView() - } + self.coordinator.showTermsAgreementView() + case .nickname: - DispatchQueue.main.async { - self.coordinator.showNicknameSetting() - } + self.coordinator.showNicknameSetting() + case .joinGroup: - DispatchQueue.main.async { - self.coordinator.showGroupSearch() - } - break + self.coordinator.showGroupSearch() } return .empty() diff --git a/onboard-iOS/Presentation/SignUp/TermsAgreementReactor.swift b/onboard-iOS/Presentation/SignUp/TermsAgreementReactor.swift index cbccbfbe..50baaa22 100644 --- a/onboard-iOS/Presentation/SignUp/TermsAgreementReactor.swift +++ b/onboard-iOS/Presentation/SignUp/TermsAgreementReactor.swift @@ -36,6 +36,7 @@ final class TermsAgreementReactor: Reactor { let isRequired: Bool let url: String let isChecked: Bool + let code: String } } @@ -70,9 +71,7 @@ final class TermsAgreementReactor: Reactor { return .just(.updateAllAgreement) case .selectRegister: - self.coordinator.showNicknameSetting() - - return .empty() + return self.agreeTerms() } } @@ -100,11 +99,19 @@ final class TermsAgreementReactor: Reactor { func transform(mutation: Observable) -> Observable { - let loginMutation = self.mutation( - result: self.useCase.result + let termsListMutation = self.mutation( + termsList: self.useCase.termsList + ) + + let termsAgreementMutation = self.mutation( + agreeResult: self.useCase.agreeResult ) - return Observable.merge(mutation, loginMutation) + return Observable.merge([ + mutation, + termsListMutation, + termsAgreementMutation + ]) } } @@ -112,13 +119,27 @@ final class TermsAgreementReactor: Reactor { extension TermsAgreementReactor { private func mutation( - result: Observable<[TermsAgreementEntity.Term]> + termsList: Observable<[TermsEntity.Term]> ) -> Observable { - return result.flatMap { response -> Observable in + return termsList.flatMap { response -> Observable in return .just(.setTerms(self.toState(response))) } } + private func mutation( + agreeResult: Observable + ) -> Observable { + return agreeResult.flatMap { response -> Observable in + if response { + self.coordinator.showNicknameSetting() + } else { + // error + } + + return .empty() + } + } + private func fetch() -> Observable { return Observable.create { [weak self] observer in guard let self else { return Disposables.create() } @@ -131,14 +152,42 @@ extension TermsAgreementReactor { } } + private func agreeTerms() -> Observable { + return Observable.create { [weak self] observer in + guard let self else { return Disposables.create() } + Task { + do { + + let agreeList = self.currentState.terms + .filter { $0.isChecked } + .map { $0.code } + + let disagreeList = self.currentState.terms + .filter { !$0.isChecked } + .map { $0.code } + + await self.useCase.agreeTerms( + req: TermsAgreementEntity.Req( + agreeList: agreeList, + disagreeList: disagreeList + ) + ) + } + } + return Disposables.create() + } + } + + private func toState( - _ terms: [TermsAgreementEntity.Term] + _ terms: [TermsEntity.Term] ) -> [TermsAgreementReactor.State.Term] { return terms.map { TermsAgreementReactor.State.Term( title: $0.title, isRequired: $0.isReuired, url: $0.url, - isChecked: false + isChecked: false, + code: $0.code )} } @@ -154,7 +203,8 @@ extension TermsAgreementReactor { title: term.title, isRequired: term.isRequired, url: term.url, - isChecked: !term.isChecked + isChecked: !term.isChecked, + code: term.code ) let isAllAgreement = !terms.contains(where: { $0.isChecked == false }) @@ -171,7 +221,8 @@ extension TermsAgreementReactor { title: $0.title, isRequired: $0.isRequired, url: $0.url, - isChecked: !state.isAllAgreemented + isChecked: !state.isAllAgreemented, + code: $0.code ) }, isAllAgreemented: !state.isAllAgreemented diff --git a/onboard-iOS/Repository/Auth/TermsAgreementRepository.swift b/onboard-iOS/Repository/Auth/TermsAgreementRepository.swift index 8e8abfd7..382a5652 100644 --- a/onboard-iOS/Repository/Auth/TermsAgreementRepository.swift +++ b/onboard-iOS/Repository/Auth/TermsAgreementRepository.swift @@ -9,13 +9,13 @@ import Foundation final class TermsAgreementRepositoryImpl: TermsAgreementRepository { - func fetch() async throws -> [TermsAgreementEntity.Term] { + func fetch() async throws -> [TermsEntity.Term] { do { let result = try await OBNetworkManager .shared .asyncRequest( - object: TermsAgreementDTO.self, + object: TermsDTO.self, router: OBRouter.terms ) @@ -31,12 +31,39 @@ final class TermsAgreementRepositoryImpl: TermsAgreementRepository { throw error } } + + func agreeTerms(req: TermsAgreementEntity.Req) async throws -> Bool { + do { + let result = try await OBNetworkManager + .shared + .asyncRequest( + object: TermsAgreementDTO.self, + router: OBRouter.agreementTerms( + body: TermsAgreementRequest.Body( + agree: req.agreeList, + disagree: req.disagreeList + ).encode() + ) + ) + + guard let data = result.value else { + throw NetworkError.noExist + } + + return true + + } catch { + print(error.localizedDescription) + + throw error + } + } } -extension TermsAgreementDTO { - var toDomain: [TermsAgreementEntity.Term] { +extension TermsDTO { + var toDomain: [TermsEntity.Term] { return self.contents.map { - TermsAgreementEntity.Term( + TermsEntity.Term( code: $0.code, title: $0.title, url: $0.url, diff --git a/onboard-iOS/Repository/DTO/TermsDTO.swift b/onboard-iOS/Repository/DTO/TermsDTO.swift index cbc42347..4c63cd9f 100644 --- a/onboard-iOS/Repository/DTO/TermsDTO.swift +++ b/onboard-iOS/Repository/DTO/TermsDTO.swift @@ -18,4 +18,13 @@ struct TermsDTO: Decodable { } } -struct +enum TermsAgreementRequest { + struct Body: Encodable { + let agree: [String] + let disagree: [String] + } +} + +struct TermsAgreementDTO: Decodable { + let result: Bool? +} From c620f0d86176ca63f9f1ebfc97431e498b5ef03e Mon Sep 17 00:00:00 2001 From: daye Date: Sun, 3 Dec 2023 11:59:53 +0900 Subject: [PATCH 14/17] =?UTF-8?q?#onb-55=20push=20view=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=EC=8A=A4=EB=A0=88=EB=93=9C=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- onboard-iOS.xcodeproj/project.pbxproj | 16 ++++++++-------- .../Coordinator/GroupSearchCoordinator.swift | 4 +++- onboard-iOS/Coordinator/LoginCoordinator.swift | 4 +++- .../Coordinator/NicknameCoordinator.swift | 5 ++++- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/onboard-iOS.xcodeproj/project.pbxproj b/onboard-iOS.xcodeproj/project.pbxproj index cb304f52..49ef7bfc 100644 --- a/onboard-iOS.xcodeproj/project.pbxproj +++ b/onboard-iOS.xcodeproj/project.pbxproj @@ -37,8 +37,8 @@ 61342DAC2B1612AA00AE0268 /* NicknameCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61342DAB2B1612AA00AE0268 /* NicknameCoordinator.swift */; }; 61342DAE2B16170E00AE0268 /* OBRequestInterceptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61342DAD2B16170E00AE0268 /* OBRequestInterceptor.swift */; }; 61342DB02B1618EB00AE0268 /* TermsAgreementUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61342DAF2B1618EB00AE0268 /* TermsAgreementUseCase.swift */; }; - 61342DB22B1619BE00AE0268 /* TermsAgreementEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61342DB12B1619BE00AE0268 /* TermsAgreementEntity.swift */; }; - 61342DB42B1619DD00AE0268 /* TermsAgreementDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61342DB32B1619DD00AE0268 /* TermsAgreementDTO.swift */; }; + 61342DB22B1619BE00AE0268 /* TermsEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61342DB12B1619BE00AE0268 /* TermsEntity.swift */; }; + 61342DB42B1619DD00AE0268 /* TermsDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61342DB32B1619DD00AE0268 /* TermsDTO.swift */; }; 61342DB62B161A5900AE0268 /* TermsAgreementRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61342DB52B161A5900AE0268 /* TermsAgreementRepository.swift */; }; 6151A06F2AECFE92001D74AB /* TermsAgreementReactor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6151A06E2AECFE92001D74AB /* TermsAgreementReactor.swift */; }; 618175F52AC5722500B5E2A0 /* UILabel+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 618175F42AC5722500B5E2A0 /* UILabel+Extension.swift */; }; @@ -139,8 +139,8 @@ 61342DAB2B1612AA00AE0268 /* NicknameCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NicknameCoordinator.swift; sourceTree = ""; }; 61342DAD2B16170E00AE0268 /* OBRequestInterceptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OBRequestInterceptor.swift; sourceTree = ""; }; 61342DAF2B1618EB00AE0268 /* TermsAgreementUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsAgreementUseCase.swift; sourceTree = ""; }; - 61342DB12B1619BE00AE0268 /* TermsAgreementEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsAgreementEntity.swift; sourceTree = ""; }; - 61342DB32B1619DD00AE0268 /* TermsAgreementDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsAgreementDTO.swift; sourceTree = ""; }; + 61342DB12B1619BE00AE0268 /* TermsEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsEntity.swift; sourceTree = ""; }; + 61342DB32B1619DD00AE0268 /* TermsDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsDTO.swift; sourceTree = ""; }; 61342DB52B161A5900AE0268 /* TermsAgreementRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsAgreementRepository.swift; sourceTree = ""; }; 6151A06E2AECFE92001D74AB /* TermsAgreementReactor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsAgreementReactor.swift; sourceTree = ""; }; 618175F42AC5722500B5E2A0 /* UILabel+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILabel+Extension.swift"; sourceTree = ""; }; @@ -509,7 +509,7 @@ children = ( 61AC7FCD2AB6DDE300B0B6B5 /* TestDTO.swift */, AA7036012ADB8A1400B26537 /* GroupDTO.swift */, - 61342DB32B1619DD00AE0268 /* TermsAgreementDTO.swift */, + 61342DB32B1619DD00AE0268 /* TermsDTO.swift */, 61D95E2A2B1B06A5007F93D7 /* AuthDTO.swift */, 61D95E2C2B1B06BB007F93D7 /* OnboardingDTO.swift */, ); @@ -522,7 +522,7 @@ 61AC7FD02AB6DFBF00B0B6B5 /* TestEntity.swift */, 618176152AD2C21000B5E2A0 /* AuthEntity.swift */, AA7035FF2ADB85A500B26537 /* GroupListEntity.swift */, - 61342DB12B1619BE00AE0268 /* TermsAgreementEntity.swift */, + 61342DB12B1619BE00AE0268 /* TermsEntity.swift */, 61D95E282B1B062B007F93D7 /* OnboardingEntity.swift */, ); path = Entity; @@ -735,7 +735,7 @@ 618176352AD5902300B5E2A0 /* TermsAgreementViewController.swift in Sources */, 61342DAC2B1612AA00AE0268 /* NicknameCoordinator.swift in Sources */, 61D95E342B1B1417007F93D7 /* GroupSearchCoordinator.swift in Sources */, - 61342DB42B1619DD00AE0268 /* TermsAgreementDTO.swift in Sources */, + 61342DB42B1619DD00AE0268 /* TermsDTO.swift in Sources */, 618175F52AC5722500B5E2A0 /* UILabel+Extension.swift in Sources */, 611D8CEE2AC44EEA0074A55A /* UIView+SwiftUI+Extension.swift in Sources */, 611D8CEC2AC44D230074A55A /* TermsView.swift in Sources */, @@ -756,7 +756,7 @@ 61AC7F9F2AB6D4A300B0B6B5 /* AppDelegate.swift in Sources */, 618176202AD2C6EE00B5E2A0 /* LoginReactor.swift in Sources */, 1CA1BBC42ADABEBD000C5F7E /* TextField.swift in Sources */, - 61342DB22B1619BE00AE0268 /* TermsAgreementEntity.swift in Sources */, + 61342DB22B1619BE00AE0268 /* TermsEntity.swift in Sources */, AACCA91B2AE19A09000A4CDA /* NewGroupButton.swift in Sources */, 61CC3C242AEE876500AE8599 /* GoogleLoginManager.swift in Sources */, 61AC7FBC2AB6D72C00B0B6B5 /* TestView.swift in Sources */, diff --git a/onboard-iOS/Coordinator/GroupSearchCoordinator.swift b/onboard-iOS/Coordinator/GroupSearchCoordinator.swift index 081bfd7b..bd5164a6 100644 --- a/onboard-iOS/Coordinator/GroupSearchCoordinator.swift +++ b/onboard-iOS/Coordinator/GroupSearchCoordinator.swift @@ -23,6 +23,8 @@ final class GroupSearchCoordinator: Coordinator { let reactor = GroupSearchReactor(useCase: useCase) let viewController = GroupSearchViewController(reactor: reactor) - self.navigationController?.pushViewController(viewController, animated: true) + DispatchQueue.main.async { + self.navigationController?.pushViewController(viewController, animated: true) + } } } diff --git a/onboard-iOS/Coordinator/LoginCoordinator.swift b/onboard-iOS/Coordinator/LoginCoordinator.swift index a9b5f435..b787abe0 100644 --- a/onboard-iOS/Coordinator/LoginCoordinator.swift +++ b/onboard-iOS/Coordinator/LoginCoordinator.swift @@ -45,7 +45,9 @@ final class LoginCoordinator: Coordinator { ) let viewController = LoginViewController(reactor: reactor) - self.navigationController?.pushViewController(viewController, animated: true) + DispatchQueue.main.async { + self.navigationController?.pushViewController(viewController, animated: true) + } } } diff --git a/onboard-iOS/Coordinator/NicknameCoordinator.swift b/onboard-iOS/Coordinator/NicknameCoordinator.swift index 45cea929..42bc879c 100644 --- a/onboard-iOS/Coordinator/NicknameCoordinator.swift +++ b/onboard-iOS/Coordinator/NicknameCoordinator.swift @@ -25,7 +25,9 @@ final class NicknameCoordinator: Coordinator { let reactor = NicknameReactor(coordinator: self) let viewController = NicknameViewController(reactor: reactor) - self.navigationController?.pushViewController(viewController, animated: true) + DispatchQueue.main.async { + self.navigationController?.pushViewController(viewController, animated: true) + } } } @@ -34,6 +36,7 @@ extension NicknameCoordinator: NicknameCoordinatorNavigateDelegate { let coordinator = GroupSearchCoordinator( navigationController: self.navigationController ) + coordinator.start() } } From 42dc458a2d61d4d28cef09e7ce5671a4072333e3 Mon Sep 17 00:00:00 2001 From: daye Date: Sun, 3 Dec 2023 12:13:01 +0900 Subject: [PATCH 15/17] =?UTF-8?q?#onb-55=20=EB=8B=89=EB=84=A4=EC=9E=84=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EB=B2=84=ED=8A=BC=20=EC=95=A1=EC=85=98=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/SignUp/Views/NicknameView.swift | 10 ++++++++++ .../SignUp/Views/NicknameViewController.swift | 3 +++ .../Repository/Auth/TermsAgreementRepository.swift | 4 ++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/onboard-iOS/Presentation/SignUp/Views/NicknameView.swift b/onboard-iOS/Presentation/SignUp/Views/NicknameView.swift index 1c59c459..d3a72f7c 100644 --- a/onboard-iOS/Presentation/SignUp/Views/NicknameView.swift +++ b/onboard-iOS/Presentation/SignUp/Views/NicknameView.swift @@ -48,6 +48,8 @@ final class NicknameView: UIView { button.setTitle("확인", for: .normal) return button }() + + var selectConfirm: (() -> Void)? // MARK: - Initialize @@ -68,6 +70,14 @@ final class NicknameView: UIView { self.stackView.axis = .vertical self.stackView.spacing = 4 self.makeConstraints() + self.setConfirmButtonAction() + } + + private func setConfirmButtonAction() { + let action = UIAction(handler: { _ in + self.selectConfirm?() + }) + self.confirmButton.addAction(action, for: .touchUpInside) } private func makeConstraints() { diff --git a/onboard-iOS/Presentation/SignUp/Views/NicknameViewController.swift b/onboard-iOS/Presentation/SignUp/Views/NicknameViewController.swift index 2ad6a064..a375dd06 100644 --- a/onboard-iOS/Presentation/SignUp/Views/NicknameViewController.swift +++ b/onboard-iOS/Presentation/SignUp/Views/NicknameViewController.swift @@ -36,6 +36,9 @@ final class NicknameViewController: UIViewController, View { } private func bindAction(reactor: Reactor) { + self.nicknameView.selectConfirm = { + self.reactor?.action.onNext(.confirm) + } } private func bindState(reactor: Reactor) { diff --git a/onboard-iOS/Repository/Auth/TermsAgreementRepository.swift b/onboard-iOS/Repository/Auth/TermsAgreementRepository.swift index 382a5652..da8e2787 100644 --- a/onboard-iOS/Repository/Auth/TermsAgreementRepository.swift +++ b/onboard-iOS/Repository/Auth/TermsAgreementRepository.swift @@ -46,11 +46,11 @@ final class TermsAgreementRepositoryImpl: TermsAgreementRepository { ) ) - guard let data = result.value else { + guard let data = result.value?.result else { throw NetworkError.noExist } - return true + return data } catch { print(error.localizedDescription) From 2ec6573446416bd827649774b4b2495846ba91d2 Mon Sep 17 00:00:00 2001 From: daye Date: Mon, 4 Dec 2023 21:28:50 +0900 Subject: [PATCH 16/17] =?UTF-8?q?coordinator=20=EB=B7=B0=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20main=20thread=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- onboard-iOS/Coordinator/Coordinator.swift | 4 +- .../Coordinator/GroupSearchCoordinator.swift | 11 +++-- .../Coordinator/LoginCoordinator.swift | 49 +++++++++++-------- .../Coordinator/NicknameCoordinator.swift | 6 +-- .../TermsAgreementCoordinator.swift | 14 +++--- .../Domain/Login/GoogleLoginUseCase.swift | 8 +++ 6 files changed, 55 insertions(+), 37 deletions(-) create mode 100644 onboard-iOS/Domain/Login/GoogleLoginUseCase.swift diff --git a/onboard-iOS/Coordinator/Coordinator.swift b/onboard-iOS/Coordinator/Coordinator.swift index 61226236..ebe1a0ee 100644 --- a/onboard-iOS/Coordinator/Coordinator.swift +++ b/onboard-iOS/Coordinator/Coordinator.swift @@ -21,7 +21,9 @@ final class AppCoordinator: Coordinator { } func start() { - self.showLoginViewController() + DispatchQueue.main.async { + self.showLoginViewController() + } } private func showLoginViewController() { diff --git a/onboard-iOS/Coordinator/GroupSearchCoordinator.swift b/onboard-iOS/Coordinator/GroupSearchCoordinator.swift index bd5164a6..4b42ea5a 100644 --- a/onboard-iOS/Coordinator/GroupSearchCoordinator.swift +++ b/onboard-iOS/Coordinator/GroupSearchCoordinator.swift @@ -18,12 +18,13 @@ final class GroupSearchCoordinator: Coordinator { } func start() { - let repository = GroupRepositoryImpl() - let useCase = GroupSearchUseCaseImpl(groupRepository: repository) - let reactor = GroupSearchReactor(useCase: useCase) - let viewController = GroupSearchViewController(reactor: reactor) - DispatchQueue.main.async { + let repository = GroupRepositoryImpl() + let useCase = GroupSearchUseCaseImpl(groupRepository: repository) + let reactor = GroupSearchReactor(useCase: useCase) + let viewController = GroupSearchViewController(reactor: reactor) + + self.navigationController?.pushViewController(viewController, animated: true) } } diff --git a/onboard-iOS/Coordinator/LoginCoordinator.swift b/onboard-iOS/Coordinator/LoginCoordinator.swift index b787abe0..dec310f1 100644 --- a/onboard-iOS/Coordinator/LoginCoordinator.swift +++ b/onboard-iOS/Coordinator/LoginCoordinator.swift @@ -24,28 +24,35 @@ final class LoginCoordinator: Coordinator { } func start() { - let appleLoginManager = AppleLoginManagerImpl() - let authRepository = AuthRepositoryImpl() - let keychainService = KeychainServiceImpl() - let appleLoginUseCase = AppleLoginUseCaseImpl( - appleLoginManager: appleLoginManager, - authRepository: authRepository, - keychainService: keychainService - ) - - let kakaoLoginManager = KakaoLoginManagerImpl() - let kakaoLoginUseCase = KakaoLoginUseCaseImpl( - kakaoLoginManager: kakaoLoginManager, - authRepository: authRepository - ) - let reactor = LoginReactor( - appleUseCase: appleLoginUseCase, - kakaoUseCase: kakaoLoginUseCase, - coordinator: self - ) - let viewController = LoginViewController(reactor: reactor) - DispatchQueue.main.async { + let appleLoginManager = AppleLoginManagerImpl() + let authRepository = AuthRepositoryImpl() + let keychainService = KeychainServiceImpl() + let appleLoginUseCase = AppleLoginUseCaseImpl( + appleLoginManager: appleLoginManager, + authRepository: authRepository, + keychainService: keychainService + ) + + let kakaoLoginManager = KakaoLoginManagerImpl() + let kakaoLoginUseCase = KakaoLoginUseCaseImpl( + kakaoLoginManager: kakaoLoginManager, + authRepository: authRepository + ) + + let googleLoginUseCase = GoogleLoginUseCaseImpl( + authRepository: authRepository, + keychainService: keychainService + ) + + let reactor = LoginReactor( + appleUseCase: appleLoginUseCase, + kakaoUseCase: kakaoLoginUseCase, + googleUseCase: googleLoginUseCase, + coordinator: self + ) + let viewController = LoginViewController(reactor: reactor) + self.navigationController?.pushViewController(viewController, animated: true) } } diff --git a/onboard-iOS/Coordinator/NicknameCoordinator.swift b/onboard-iOS/Coordinator/NicknameCoordinator.swift index 42bc879c..7b7560db 100644 --- a/onboard-iOS/Coordinator/NicknameCoordinator.swift +++ b/onboard-iOS/Coordinator/NicknameCoordinator.swift @@ -22,10 +22,10 @@ final class NicknameCoordinator: Coordinator { } func start() { - let reactor = NicknameReactor(coordinator: self) - let viewController = NicknameViewController(reactor: reactor) - DispatchQueue.main.async { + let reactor = NicknameReactor(coordinator: self) + let viewController = NicknameViewController(reactor: reactor) + self.navigationController?.pushViewController(viewController, animated: true) } } diff --git a/onboard-iOS/Coordinator/TermsAgreementCoordinator.swift b/onboard-iOS/Coordinator/TermsAgreementCoordinator.swift index fc4c22a4..2543e282 100644 --- a/onboard-iOS/Coordinator/TermsAgreementCoordinator.swift +++ b/onboard-iOS/Coordinator/TermsAgreementCoordinator.swift @@ -22,14 +22,14 @@ final class TermsAgreementCoordinator: Coordinator { } func start() { - let repository = TermsAgreementRepositoryImpl() - let useCase = TermsAgreementUseCaseImpl(repository: repository) - let reactor = TermsAgreementReactor(coordinator: self, useCase: useCase) - let viewController = UINavigationController( - rootViewController: TermsAgreementViewController(reactor: reactor) - ) - viewController.modalPresentationStyle = .overFullScreen DispatchQueue.main.async { + let repository = TermsAgreementRepositoryImpl() + let useCase = TermsAgreementUseCaseImpl(repository: repository) + let reactor = TermsAgreementReactor(coordinator: self, useCase: useCase) + let viewController = UINavigationController( + rootViewController: TermsAgreementViewController(reactor: reactor) + ) + viewController.modalPresentationStyle = .overFullScreen self.navigationController?.present(viewController, animated: false) self.navigationController = viewController } diff --git a/onboard-iOS/Domain/Login/GoogleLoginUseCase.swift b/onboard-iOS/Domain/Login/GoogleLoginUseCase.swift new file mode 100644 index 00000000..ce4211eb --- /dev/null +++ b/onboard-iOS/Domain/Login/GoogleLoginUseCase.swift @@ -0,0 +1,8 @@ +// +// GoogleLoginUseCase.swift +// onboard-iOS +// +// Created by 윤다예 on 12/3/23. +// + +import Foundation From d7f433fad17102cc6e8acabf095d863bceb0a644 Mon Sep 17 00:00:00 2001 From: daye Date: Mon, 4 Dec 2023 21:29:12 +0900 Subject: [PATCH 17/17] =?UTF-8?q?=EA=B5=AC=EA=B8=80=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- onboard-iOS.xcodeproj/project.pbxproj | 4 ++ .../Domain/Login/GoogleLoginUseCase.swift | 49 +++++++++++++++++ onboard-iOS/Info.plist | 42 +++++++-------- onboard-iOS/Network/OBNetworkManager.swift | 19 ------- .../Presentation/Login/LoginReactor.swift | 36 +++++++++++-- .../Login/LoginViewController.swift | 8 +++ .../SignUp/TermsAgreementReactor.swift | 6 +-- .../Test/TestViewController.swift | 4 -- .../SocialLogin/GoogleLoginManager.swift | 52 +++++++++++-------- onboard-iOS/SceneDelegate.swift | 7 +++ 10 files changed, 149 insertions(+), 78 deletions(-) diff --git a/onboard-iOS.xcodeproj/project.pbxproj b/onboard-iOS.xcodeproj/project.pbxproj index 49ef7bfc..a5b1998b 100644 --- a/onboard-iOS.xcodeproj/project.pbxproj +++ b/onboard-iOS.xcodeproj/project.pbxproj @@ -89,6 +89,7 @@ 61D95E2D2B1B06BB007F93D7 /* OnboardingDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D95E2C2B1B06BB007F93D7 /* OnboardingDTO.swift */; }; 61D95E322B1B0B5C007F93D7 /* OnboardingStage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D95E312B1B0B5C007F93D7 /* OnboardingStage.swift */; }; 61D95E342B1B1417007F93D7 /* GroupSearchCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D95E332B1B1417007F93D7 /* GroupSearchCoordinator.swift */; }; + 61D95E602B1C2B2A007F93D7 /* GoogleLoginUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D95E5F2B1C2B2A007F93D7 /* GoogleLoginUseCase.swift */; }; AA09C27A2ACBE9BC00F51A96 /* KakaoSDKAuth in Frameworks */ = {isa = PBXBuildFile; productRef = AA09C2792ACBE9BC00F51A96 /* KakaoSDKAuth */; }; AA09C27C2ACBE9BC00F51A96 /* KakaoSDKCommon in Frameworks */ = {isa = PBXBuildFile; productRef = AA09C27B2ACBE9BC00F51A96 /* KakaoSDKCommon */; }; AA09C27E2ACBE9BC00F51A96 /* KakaoSDKUser in Frameworks */ = {isa = PBXBuildFile; productRef = AA09C27D2ACBE9BC00F51A96 /* KakaoSDKUser */; }; @@ -188,6 +189,7 @@ 61D95E2C2B1B06BB007F93D7 /* OnboardingDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingDTO.swift; sourceTree = ""; }; 61D95E312B1B0B5C007F93D7 /* OnboardingStage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingStage.swift; sourceTree = ""; }; 61D95E332B1B1417007F93D7 /* GroupSearchCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupSearchCoordinator.swift; sourceTree = ""; }; + 61D95E5F2B1C2B2A007F93D7 /* GoogleLoginUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoogleLoginUseCase.swift; sourceTree = ""; }; AA09C27F2ACBEB0100F51A96 /* KakaoLoginUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KakaoLoginUseCase.swift; sourceTree = ""; }; AA09C2812ACBF18C00F51A96 /* KakaoLoginManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KakaoLoginManager.swift; sourceTree = ""; }; AA7035FA2ADB81C700B26537 /* GroupRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupRepository.swift; sourceTree = ""; }; @@ -308,6 +310,7 @@ 611D8CA12AB886B10074A55A /* AppleLoginUseCase.swift */, AA09C27F2ACBEB0100F51A96 /* KakaoLoginUseCase.swift */, 61342DAF2B1618EB00AE0268 /* TermsAgreementUseCase.swift */, + 61D95E5F2B1C2B2A007F93D7 /* GoogleLoginUseCase.swift */, ); path = Login; sourceTree = ""; @@ -810,6 +813,7 @@ 6181762D2AD3D66D00B5E2A0 /* BaseTableViewCell.swift in Sources */, 1CA1BBC72ADABFA3000C5F7E /* LinkButtonState.swift in Sources */, 61AC80052AB73A2800B0B6B5 /* Reactive+Extension.swift in Sources */, + 61D95E602B1C2B2A007F93D7 /* GoogleLoginUseCase.swift in Sources */, 611D8CA02AB884C10074A55A /* AppleLoginManager.swift in Sources */, AACCA9192AE193D3000A4CDA /* GroupSearchBar.swift in Sources */, AA7035FE2ADB820300B26537 /* GroupSearchUseCase.swift in Sources */, diff --git a/onboard-iOS/Domain/Login/GoogleLoginUseCase.swift b/onboard-iOS/Domain/Login/GoogleLoginUseCase.swift index ce4211eb..6ec9ae94 100644 --- a/onboard-iOS/Domain/Login/GoogleLoginUseCase.swift +++ b/onboard-iOS/Domain/Login/GoogleLoginUseCase.swift @@ -6,3 +6,52 @@ // import Foundation + +import RxSwift + +protocol GoogleLoginUseCase { + var result: Observable { get } + func signIn(token: String) async throws +} + +protocol GoogleLoginDelegate: AnyObject { + // 구글로그인 토큰 전달 + func success(token: String) +} + +final class GoogleLoginUseCaseImpl: GoogleLoginUseCase { + + private let authRepository: AuthRepository + private let keychainService: KeychainService + + var result: Observable + private let _result: PublishSubject = .init() + + init( + authRepository: AuthRepository, + keychainService: KeychainService + ) { + self.authRepository = authRepository + self.keychainService = keychainService + self.result = self._result + } + + func signIn(token: String) async throws { + self.removeKeychainData() + + let authResult = try await self.authRepository.signIn( + req: AuthEntity.Req(type: .google, token: token) + ) + self.keychainService.set(authResult.accessToken, forKey: .accessToken) + self.keychainService.set(authResult.refreshToken, forKey: .refreshToken) + + let onboardingResult = try await self.authRepository.onboarding() + + self._result.onNext(onboardingResult) + } + + private func removeKeychainData() { + self.keychainService.remove(forKey: .accessToken) + self.keychainService.remove(forKey: .refreshToken) + } +} diff --git a/onboard-iOS/Info.plist b/onboard-iOS/Info.plist index 67f05dfe..23a4201e 100644 --- a/onboard-iOS/Info.plist +++ b/onboard-iOS/Info.plist @@ -2,38 +2,39 @@ - UIAppFonts - - SpoqaHanSansNeo-Bold.ttf - SpoqaHanSansNeo-Medium.ttf - SpoqaHanSansNeo-Regular.ttf - SpoqaHanSansNeo-Light.ttf - SpoqaHanSansNeo-Thin.ttf - + GIDClientID + 407255596267-ug3kch0n6tnc8bmdjj87q0amckjkp7jt.apps.googleusercontent.com CFBundleURLTypes - CFBundleURLName - - CFBundleURLSchemes - - com.googleusercontent.apps.60961186546-rtf4h136vnreuooj193b19jhsgjsoba9 - - - GIDClientID - 60961186546-rtf4h136vnreuooj193b19jhsgjsoba9.apps.googleusercontent.com CFBundleTypeRole Editor + CFBundleURLName + CFBundleURLSchemes - kakao0fc9af67a72e49041aa31ec49dcd8bc0 + com.googleusercontent.apps.407255596267-ug3kch0n6tnc8bmdjj87q0amckjkp7jt + + + LSApplicationQueriesSchemes + + kakaokompassauth + kakaolink NSAppTransportSecurity NSAllowsArbitraryLoads + UIAppFonts + + SpoqaHanSansNeo-Bold.ttf + SpoqaHanSansNeo-Medium.ttf + SpoqaHanSansNeo-Regular.ttf + SpoqaHanSansNeo-Light.ttf + SpoqaHanSansNeo-Thin.ttf + UIApplicationSceneManifest UIApplicationSupportsMultipleScenes @@ -53,10 +54,5 @@ - LSApplicationQueriesSchemes - - kakaokompassauth - kakaolink - diff --git a/onboard-iOS/Network/OBNetworkManager.swift b/onboard-iOS/Network/OBNetworkManager.swift index 30887a1f..83777486 100644 --- a/onboard-iOS/Network/OBNetworkManager.swift +++ b/onboard-iOS/Network/OBNetworkManager.swift @@ -42,23 +42,4 @@ final class OBNetworkManager { return response } - - func googleLoginRequest(token: String) throws { - let googleLoginAPI = try OBRouter.auth( - body: AuthRequest.Body( - type: AuthEntity.Req.AuthType.google.rawValue, - token: token - ).encode() - ) - - APISession.session.request(googleLoginAPI) - .responseDecodable { (response: AFDataResponse) in - switch response.result { - case .success(let data): - print("Response Data: \(data)") - case .failure(let error): - print("Response Error: \(error)") - } - } - } } diff --git a/onboard-iOS/Presentation/Login/LoginReactor.swift b/onboard-iOS/Presentation/Login/LoginReactor.swift index 2cdfd7dc..fc962bb4 100644 --- a/onboard-iOS/Presentation/Login/LoginReactor.swift +++ b/onboard-iOS/Presentation/Login/LoginReactor.swift @@ -29,14 +29,17 @@ final class LoginReactor: Reactor { private let coordinator: LoginCoordinator private let appleUseCase: AppleLoginUseCase private let kakaoUseCase: KakaoLoginUseCase + private let googleUseCase: GoogleLoginUseCase init( appleUseCase: AppleLoginUseCase, kakaoUseCase: KakaoLoginUseCase, + googleUseCase: GoogleLoginUseCase, coordinator: LoginCoordinator ) { self.appleUseCase = appleUseCase self.kakaoUseCase = kakaoUseCase + self.googleUseCase = googleUseCase self.coordinator = coordinator } @@ -46,7 +49,7 @@ final class LoginReactor: Reactor { return self.excuteAppleLogin() case .google: - return self.googleLoginResult() + return .empty() case .kakao: return self.excuteKakaoLogin() @@ -62,11 +65,16 @@ final class LoginReactor: Reactor { let kakaoMutation = self.mutation( result: self.kakaoUseCase.result ) + + let googleMutation = self.mutation( + result: self.googleUseCase.result + ) return Observable.merge([ mutation, appleMutation, - kakaoMutation + kakaoMutation, + googleMutation ]) } } @@ -117,6 +125,7 @@ extension LoginReactor { private func excuteKakaoLogin() -> Observable { return Observable.create { [weak self] observer in guard let self else { return Disposables.create() } + Task { do { await self.kakaoUseCase.signIn() @@ -126,13 +135,30 @@ extension LoginReactor { } } - private func googleLoginResult() -> Observable { + private func googleLoginResult(token: String) -> Observable { return Observable.create { [weak self] observer in guard let self else { return Disposables.create() } + +// Task { +// do { +// try await self.googleUseCase.signIn(token: token) +// } +// } + return Disposables.create() + } + } +} - self.coordinator.showTermsAgreementView() +// MARK: - Google login delegate - return Disposables.create() +extension LoginReactor: GoogleLoginDelegate { + + func success(token: String) { + Task { + do { + try await self.googleUseCase.signIn(token: token) + } } } } + diff --git a/onboard-iOS/Presentation/Login/LoginViewController.swift b/onboard-iOS/Presentation/Login/LoginViewController.swift index b572a820..db283870 100644 --- a/onboard-iOS/Presentation/Login/LoginViewController.swift +++ b/onboard-iOS/Presentation/Login/LoginViewController.swift @@ -43,6 +43,14 @@ final class LoginViewController: UIViewController, View { private func bindAction(reactor: LoginReactor) { self.loginView.didTapGoogleButton = { + + let googleLoginManager = GoogleLoginManagerImpl() + + googleLoginManager.signIn( + presentingViewController: self, + delegate: self.reactor ?? nil + ) + reactor.action.onNext(.google) } diff --git a/onboard-iOS/Presentation/SignUp/TermsAgreementReactor.swift b/onboard-iOS/Presentation/SignUp/TermsAgreementReactor.swift index 50baaa22..a0a60fc9 100644 --- a/onboard-iOS/Presentation/SignUp/TermsAgreementReactor.swift +++ b/onboard-iOS/Presentation/SignUp/TermsAgreementReactor.swift @@ -130,11 +130,7 @@ extension TermsAgreementReactor { agreeResult: Observable ) -> Observable { return agreeResult.flatMap { response -> Observable in - if response { - self.coordinator.showNicknameSetting() - } else { - // error - } + self.coordinator.showNicknameSetting() return .empty() } diff --git a/onboard-iOS/Presentation/Test/TestViewController.swift b/onboard-iOS/Presentation/Test/TestViewController.swift index 8d29e8c6..33825e8b 100644 --- a/onboard-iOS/Presentation/Test/TestViewController.swift +++ b/onboard-iOS/Presentation/Test/TestViewController.swift @@ -134,8 +134,4 @@ final class TestViewController: UIViewController, View { }) .disposed(by: self.disposeBag) } - - @objc private func buttonAction() { - GoogleLoginManager.shared.signIn(withPresenting: self) - } } diff --git a/onboard-iOS/Repository/SocialLogin/GoogleLoginManager.swift b/onboard-iOS/Repository/SocialLogin/GoogleLoginManager.swift index 3e18e634..b53e66a9 100644 --- a/onboard-iOS/Repository/SocialLogin/GoogleLoginManager.swift +++ b/onboard-iOS/Repository/SocialLogin/GoogleLoginManager.swift @@ -8,31 +8,39 @@ import Foundation import GoogleSignIn -class GoogleLoginManager { +protocol GoogleLoginManager { + func signIn( + presentingViewController: UIViewController, + delegate: GoogleLoginDelegate? + ) +} + +class GoogleLoginManagerImpl: GoogleLoginManager { + + private var token: String = "" { + didSet { + self.delegate?.success(token: self.token) + } + } - static let shared = GoogleLoginManager() + weak var delegate: GoogleLoginDelegate? - func signIn(withPresenting presentingViewController: UIViewController) { - GIDSignIn.sharedInstance.signIn(withPresenting: presentingViewController) { signInResult, error in + func signIn( + presentingViewController: UIViewController, + delegate: GoogleLoginDelegate? + ) { + + self.delegate = delegate + + GIDSignIn.sharedInstance.signIn( + withPresenting: presentingViewController + ) { signInResult, error in + + guard error == nil, + let result = signInResult, + let idToken = result.user.idToken?.tokenString else { return } - if error == nil { - guard let signInResult = signInResult else { return } - let user = signInResult.user - - let idTokenString: GIDToken? = user.idToken - - if let idToken = idTokenString { - let networkManager = OBNetworkManager.shared - - do { - try networkManager.googleLoginRequest(token: idToken.tokenString) - } catch { - print(error.localizedDescription) - } - } - } else { - print("Google 로그인 실패: \(error?.localizedDescription ?? "Unknown error")") - } + self.token = idToken } } } diff --git a/onboard-iOS/SceneDelegate.swift b/onboard-iOS/SceneDelegate.swift index f07baf27..48c7a1eb 100644 --- a/onboard-iOS/SceneDelegate.swift +++ b/onboard-iOS/SceneDelegate.swift @@ -8,6 +8,7 @@ import UIKit import KakaoSDKAuth import KakaoSDKCommon +import GoogleSignIn class SceneDelegate: UIResponder, UIWindowSceneDelegate { @@ -50,6 +51,12 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { _ = AuthController.handleOpenUrl(url: url) } } + + guard let url = URLContexts.first?.url, + let scheme = url.scheme, + scheme.contains("com.googleusercontent.apps") else { return } + + GIDSignIn.sharedInstance.handle(url) } }