diff --git a/Poppool/CoreLayer/Infrastructure/Infrastructure/Service/KeyChainService.swift b/Poppool/CoreLayer/Infrastructure/Infrastructure/Service/KeyChainService.swift index 822263e7..1ce0a244 100644 --- a/Poppool/CoreLayer/Infrastructure/Infrastructure/Service/KeyChainService.swift +++ b/Poppool/CoreLayer/Infrastructure/Infrastructure/Service/KeyChainService.swift @@ -1,8 +1,6 @@ import Foundation import Security -import RxSwift - public final class KeyChainService { // KeyChain에서 발생할 수 있는 오류를 정의 @@ -60,6 +58,7 @@ public final class KeyChainService { /// - Parameter type: 저장하려는 토큰의 타입 (`accessToken` 또는 `refreshToken`) /// - Parameter value: 저장할 토큰의 값 /// - Returns: 완료 시 `Completable` + @discardableResult public func saveToken(type: TokenType, value: String) -> Result { // allowLossyConversion은 인코딩 과정에서 손실이 되는 것을 허용할 것인지 설정 guard let convertValue = value.data(using: .utf8, allowLossyConversion: false) else { @@ -95,6 +94,7 @@ public final class KeyChainService { /// KeyChain에서 특정 타입의 토큰을 삭제하는 메서드 /// - Parameter type: 삭제하려는 토큰의 타입 (`accessToken` 또는 `refreshToken`) /// - Returns: 완료 시 `Completable` + @discardableResult public func deleteToken(type: TokenType) -> Result { // 1. query 작성 let keyChainQuery: NSDictionary = [ diff --git a/Poppool/CoreLayer/Infrastructure/Infrastructure/Service/UserDefaultService.swift b/Poppool/CoreLayer/Infrastructure/Infrastructure/Service/UserDefaultService.swift index 52211c19..4a3f8fad 100644 --- a/Poppool/CoreLayer/Infrastructure/Infrastructure/Service/UserDefaultService.swift +++ b/Poppool/CoreLayer/Infrastructure/Infrastructure/Service/UserDefaultService.swift @@ -69,8 +69,11 @@ public final class UserDefaultService { // MARK: - Key base extension UserDefaultService { - public enum Key: String { + public enum Key: String, CaseIterable { case searchKeyword = "searchList" + case userID = "userID" + case socialType = "socialType" + case lastLogin = "lastLogin" } /// Userdefault 데이터 저장 메서드 diff --git a/Poppool/Poppool.xcodeproj/project.pbxproj b/Poppool/Poppool.xcodeproj/project.pbxproj index 37c8e70f..7759d420 100644 --- a/Poppool/Poppool.xcodeproj/project.pbxproj +++ b/Poppool/Poppool.xcodeproj/project.pbxproj @@ -33,6 +33,10 @@ 05734C6B2DCE05550093825D /* ReactorKit in Frameworks */ = {isa = PBXBuildFile; productRef = 05734C6A2DCE05550093825D /* ReactorKit */; }; 05734C6E2DCE05680093825D /* Tabman in Frameworks */ = {isa = PBXBuildFile; productRef = 05734C6D2DCE05680093825D /* Tabman */; }; 05734C712DCE059D0093825D /* Then in Frameworks */ = {isa = PBXBuildFile; productRef = 05734C702DCE059D0093825D /* Then */; }; + 05A7CBEB2E27D5FB0010F1CD /* LoginFeature.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7CBE92E27D5FB0010F1CD /* LoginFeature.framework */; }; + 05A7CBEC2E27D5FB0010F1CD /* LoginFeature.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7CBE92E27D5FB0010F1CD /* LoginFeature.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 05A7CBED2E27D5FB0010F1CD /* LoginFeatureInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7CBEA2E27D5FB0010F1CD /* LoginFeatureInterface.framework */; }; + 05A7CBEE2E27D5FB0010F1CD /* LoginFeatureInterface.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7CBEA2E27D5FB0010F1CD /* LoginFeatureInterface.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 05BBA73E2DB75DA60047A061 /* KakaoSDKUser in Frameworks */ = {isa = PBXBuildFile; productRef = 05BBA73D2DB75DA60047A061 /* KakaoSDKUser */; }; 4E15142A2D99480200DFD08F /* NMapsMap in Frameworks */ = {isa = PBXBuildFile; productRef = 4E1514292D99480200DFD08F /* NMapsMap */; }; 4E15142E2D994A3A00DFD08F /* KakaoSDKAuth in Frameworks */ = {isa = PBXBuildFile; productRef = 4E15142D2D994A3A00DFD08F /* KakaoSDKAuth */; }; @@ -52,9 +56,11 @@ 0543C5DF2DF86C830070BB93 /* SearchFeatureInterface.framework in Embed Frameworks */, 0543C5D92DF86C7F0070BB93 /* Presentation.framework in Embed Frameworks */, 0543C5D72DF86C7E0070BB93 /* Infrastructure.framework in Embed Frameworks */, + 05A7CBEE2E27D5FB0010F1CD /* LoginFeatureInterface.framework in Embed Frameworks */, 0543C5DD2DF86C810070BB93 /* SearchFeature.framework in Embed Frameworks */, 0543C5D52DF86C7C0070BB93 /* DomainInterface.framework in Embed Frameworks */, 0543C5D12DF86C790070BB93 /* DesignSystem.framework in Embed Frameworks */, + 05A7CBEC2E27D5FB0010F1CD /* LoginFeature.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -66,6 +72,8 @@ 05734C582DCDFAC20093825D /* SearchFeature.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SearchFeature.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 05734C592DCDFAC20093825D /* SearchFeatureInterface.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SearchFeatureInterface.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 05734C5E2DCE04CE0093825D /* PresentationInterface.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PresentationInterface.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 05A7CBE92E27D5FB0010F1CD /* LoginFeature.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LoginFeature.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 05A7CBEA2E27D5FB0010F1CD /* LoginFeatureInterface.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LoginFeatureInterface.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 05BDD3D52DB66E1700C1E192 /* DomainInterface.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = DomainInterface.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 05C1D6072DB53A4900508FFD /* Data.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Data.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 05C1D6082DB53A4900508FFD /* Domain.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Domain.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -107,6 +115,7 @@ buildActionMask = 2147483647; files = ( 0543C5D02DF86C790070BB93 /* DesignSystem.framework in Frameworks */, + 05A7CBEB2E27D5FB0010F1CD /* LoginFeature.framework in Frameworks */, 05734C662DCE05070093825D /* PanModal in Frameworks */, 0543C5D42DF86C7C0070BB93 /* DomainInterface.framework in Frameworks */, 0543C5D62DF86C7E0070BB93 /* Infrastructure.framework in Frameworks */, @@ -124,6 +133,7 @@ 4EE360FD2D91876300D2441D /* NMapsMap in Frameworks */, 0543C5DA2DF86C800070BB93 /* PresentationInterface.framework in Frameworks */, 05734C682DCE05240093825D /* SnapKit in Frameworks */, + 05A7CBED2E27D5FB0010F1CD /* LoginFeatureInterface.framework in Frameworks */, 0543C5CD2DF86C740070BB93 /* Data.framework in Frameworks */, 05734C632DCE04FA0093825D /* Pageboy in Frameworks */, 4E15142A2D99480200DFD08F /* NMapsMap in Frameworks */, @@ -136,6 +146,8 @@ 05C1D6062DB53A4900508FFD /* Frameworks */ = { isa = PBXGroup; children = ( + 05A7CBE92E27D5FB0010F1CD /* LoginFeature.framework */, + 05A7CBEA2E27D5FB0010F1CD /* LoginFeatureInterface.framework */, 05734C5E2DCE04CE0093825D /* PresentationInterface.framework */, 05734C582DCDFAC20093825D /* SearchFeature.framework */, 05734C592DCDFAC20093825D /* SearchFeatureInterface.framework */, @@ -212,7 +224,7 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1540; + LastSwiftUpdateCheck = 1640; LastUpgradeCheck = 1640; TargetAttributes = { BDCA41BC2CF35AC0005EECF6 = { diff --git a/Poppool/Poppool.xcworkspace/contents.xcworkspacedata b/Poppool/Poppool.xcworkspace/contents.xcworkspacedata index 67537ffe..dc27e306 100644 --- a/Poppool/Poppool.xcworkspace/contents.xcworkspacedata +++ b/Poppool/Poppool.xcworkspace/contents.xcworkspacedata @@ -21,6 +21,9 @@ + + diff --git a/Poppool/Poppool.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Poppool/Poppool.xcworkspace/xcshareddata/swiftpm/Package.resolved index 7bcd7a79..eedcb23b 100644 --- a/Poppool/Poppool.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Poppool/Poppool.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "e3308f4d8d004a111784c1f182de9af75f8c85dd7807e55541802130c4c227fb", + "originHash" : "a7f3b61af0b76d9c1de1a59a03a575ed7c287144c0d5f2019526285cd427e6a7", "pins" : [ { "identity" : "alamofire", @@ -24,8 +24,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/kakao/kakao-ios-sdk.git", "state" : { - "revision" : "2c780b70d4197be3f72deee2fd82ea3e3b767007", - "version" : "2.24.1" + "revision" : "394ccfc67b206894f55dcaf2dd15e06bf451c4d3", + "version" : "2.24.5" } }, { @@ -123,8 +123,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/navermaps/SPM-NMapsMap", "state" : { - "revision" : "ad89e53fdfec3b8d8994280fb0414b5a7b1c3e8e", - "version" : "3.21.0" + "revision" : "13a6d280a57c4ebab8320e2d5bf3ce89adacf95e", + "version" : "3.22.0" } }, { diff --git a/Poppool/Poppool/Application/AppDelegate.swift b/Poppool/Poppool/Application/AppDelegate.swift index 82d5d5a8..2fbf16ec 100644 --- a/Poppool/Poppool/Application/AppDelegate.swift +++ b/Poppool/Poppool/Application/AppDelegate.swift @@ -5,6 +5,8 @@ import Data import Domain import DomainInterface import Infrastructure +import LoginFeature +import LoginFeatureInterface import Presentation import PresentationInterface import SearchFeature @@ -100,5 +102,9 @@ extension AppDelegate { DIContainer.register(DetailFactory.self) { return DetailFactoryImpl() } DIContainer.register(CategorySelectorFactory.self) { return CategorySelectorFactoryImpl() } DIContainer.register(FilterSelectorFactory.self) { return FilterSelectorFactoryImpl() } + DIContainer.register(LoginFactory.self) { return LoginFactoryImpl() } + DIContainer.register(SignUpFactory.self) { return SignUpFactoryImpl() } + DIContainer.register(WaveTabbarFactory.self) { return WaveTabbarFactoryImpl() } + DIContainer.register(FAQFactory.self) { return FAQFactoryImpl() } } } diff --git a/Poppool/PresentationLayer/DesignSystem/DesignSystem/Components/PPLabel.swift b/Poppool/PresentationLayer/DesignSystem/DesignSystem/Components/PPLabel.swift index 32ce068f..d27c4daf 100644 --- a/Poppool/PresentationLayer/DesignSystem/DesignSystem/Components/PPLabel.swift +++ b/Poppool/PresentationLayer/DesignSystem/DesignSystem/Components/PPLabel.swift @@ -3,8 +3,8 @@ import UIKit public class PPLabel: UILabel { public init( - style: UIFont.FontStyle, - fontSize: CGFloat, + style: UIFont.FontStyle = .regular, + fontSize: CGFloat = 12, text: String = "", lineHeight: CGFloat = 1.2 ) { diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeature.xcodeproj/project.pbxproj b/Poppool/PresentationLayer/LoginFeature/LoginFeature.xcodeproj/project.pbxproj new file mode 100644 index 00000000..8ff84d77 --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeature.xcodeproj/project.pbxproj @@ -0,0 +1,983 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXBuildFile section */ + 055C24F02E28FD9800AD389C /* PresentationTesting.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 055C24EF2E28FD9800AD389C /* PresentationTesting.framework */; }; + 055C24F12E28FD9800AD389C /* PresentationTesting.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 055C24EF2E28FD9800AD389C /* PresentationTesting.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 05A7C1AF2E2679290010F1CD /* DesignSystem.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7C1AE2E2679290010F1CD /* DesignSystem.framework */; }; + 05A7C1B22E26799A0010F1CD /* LoginFeature.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7C15F2E26768A0010F1CD /* LoginFeature.framework */; }; + 05A7C1B32E26799A0010F1CD /* LoginFeature.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7C15F2E26768A0010F1CD /* LoginFeature.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 05A7C1B62E26799A0010F1CD /* LoginFeatureInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7C16E2E2676E60010F1CD /* LoginFeatureInterface.framework */; }; + 05A7C1B72E26799A0010F1CD /* LoginFeatureInterface.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7C16E2E2676E60010F1CD /* LoginFeatureInterface.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 05A7C1BC2E2679FC0010F1CD /* Infrastructure.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7C1BB2E2679FC0010F1CD /* Infrastructure.framework */; }; + 05A7C1BD2E2679FC0010F1CD /* Infrastructure.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7C1BB2E2679FC0010F1CD /* Infrastructure.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 05A7C1BE2E267A120010F1CD /* LoginFeatureInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7C16E2E2676E60010F1CD /* LoginFeatureInterface.framework */; }; + 05A7C1D32E267AF80010F1CD /* ReactorKit in Frameworks */ = {isa = PBXBuildFile; productRef = 05A7C1D22E267AF80010F1CD /* ReactorKit */; }; + 05A7C1D62E267B130010F1CD /* RxCocoa in Frameworks */ = {isa = PBXBuildFile; productRef = 05A7C1D52E267B130010F1CD /* RxCocoa */; }; + 05A7C1D82E267B130010F1CD /* RxSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 05A7C1D72E267B130010F1CD /* RxSwift */; }; + 05A7CBB92E277AE30010F1CD /* Then in Frameworks */ = {isa = PBXBuildFile; productRef = 05A7CBB82E277AE30010F1CD /* Then */; }; + 05A7CBD32E27D0700010F1CD /* PresentationInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7CBD22E27D0700010F1CD /* PresentationInterface.framework */; }; + 05A7CBD42E27D0700010F1CD /* PresentationInterface.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7CBD22E27D0700010F1CD /* PresentationInterface.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 05A7CBDA2E27D3510010F1CD /* PresentationInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7CBD72E27D3510010F1CD /* PresentationInterface.framework */; }; + 05A7CBDB2E27D3510010F1CD /* PresentationInterface.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7CBD72E27D3510010F1CD /* PresentationInterface.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 05A7CBDF2E27D44F0010F1CD /* Data.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7CBDC2E27D44F0010F1CD /* Data.framework */; }; + 05A7CBE02E27D44F0010F1CD /* Data.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7CBDC2E27D44F0010F1CD /* Data.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 05A7CBE12E27D44F0010F1CD /* Domain.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7CBDD2E27D44F0010F1CD /* Domain.framework */; }; + 05A7CBE22E27D44F0010F1CD /* Domain.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7CBDD2E27D44F0010F1CD /* Domain.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 05A7CBE32E27D44F0010F1CD /* DomainInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7CBDE2E27D44F0010F1CD /* DomainInterface.framework */; }; + 05A7CBE42E27D44F0010F1CD /* DomainInterface.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7CBDE2E27D44F0010F1CD /* DomainInterface.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 05A7CBE62E27D5390010F1CD /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 05A7CBE52E27D5390010F1CD /* SnapKit */; }; + 05A7CBE82E27D5400010F1CD /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 05A7CBE72E27D5400010F1CD /* SnapKit */; }; + 05A7CBF72E27DBB30010F1CD /* DesignSystem.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7C1AE2E2679290010F1CD /* DesignSystem.framework */; }; + 05A7CBF82E27DBB30010F1CD /* DesignSystem.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 05A7C1AE2E2679290010F1CD /* DesignSystem.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 05A7CBFA2E27DBDE0010F1CD /* ReactorKit in Frameworks */ = {isa = PBXBuildFile; productRef = 05A7CBF92E27DBDE0010F1CD /* ReactorKit */; }; + 05A7CBFC2E27DBDE0010F1CD /* RxCocoa in Frameworks */ = {isa = PBXBuildFile; productRef = 05A7CBFB2E27DBDE0010F1CD /* RxCocoa */; }; + 05A7CBFE2E27DBDE0010F1CD /* RxSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 05A7CBFD2E27DBDE0010F1CD /* RxSwift */; }; + 05A7CC002E27DBDE0010F1CD /* Then in Frameworks */ = {isa = PBXBuildFile; productRef = 05A7CBFF2E27DBDE0010F1CD /* Then */; }; + 05A7CC032E27DC130010F1CD /* Pageboy in Frameworks */ = {isa = PBXBuildFile; productRef = 05A7CC022E27DC130010F1CD /* Pageboy */; }; + 05A7CC0E2E28EC150010F1CD /* KakaoSDKAuth in Frameworks */ = {isa = PBXBuildFile; productRef = 05A7CC0D2E28EC150010F1CD /* KakaoSDKAuth */; }; + 05A7CC102E28EC150010F1CD /* KakaoSDKUser in Frameworks */ = {isa = PBXBuildFile; productRef = 05A7CC0F2E28EC150010F1CD /* KakaoSDKUser */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 05A7C1B42E26799A0010F1CD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 05A7C1562E26768A0010F1CD /* Project object */; + proxyType = 1; + remoteGlobalIDString = 05A7C15E2E26768A0010F1CD; + remoteInfo = LoginFeature; + }; + 05A7C1B82E26799A0010F1CD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 05A7C1562E26768A0010F1CD /* Project object */; + proxyType = 1; + remoteGlobalIDString = 05A7C16D2E2676E60010F1CD; + remoteInfo = LoginFeatureInterface; + }; + 05A7C1C02E267A120010F1CD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 05A7C1562E26768A0010F1CD /* Project object */; + proxyType = 1; + remoteGlobalIDString = 05A7C16D2E2676E60010F1CD; + remoteInfo = LoginFeatureInterface; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 05A7C1BA2E26799A0010F1CD /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 055C24F12E28FD9800AD389C /* PresentationTesting.framework in Embed Frameworks */, + 05A7C1BD2E2679FC0010F1CD /* Infrastructure.framework in Embed Frameworks */, + 05A7C1B32E26799A0010F1CD /* LoginFeature.framework in Embed Frameworks */, + 05A7C1B72E26799A0010F1CD /* LoginFeatureInterface.framework in Embed Frameworks */, + 05A7CBF82E27DBB30010F1CD /* DesignSystem.framework in Embed Frameworks */, + 05A7CBE22E27D44F0010F1CD /* Domain.framework in Embed Frameworks */, + 05A7CBE02E27D44F0010F1CD /* Data.framework in Embed Frameworks */, + 05A7CBE42E27D44F0010F1CD /* DomainInterface.framework in Embed Frameworks */, + 05A7CBDB2E27D3510010F1CD /* PresentationInterface.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + 05A7CBD52E27D0700010F1CD /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 05A7CBD42E27D0700010F1CD /* PresentationInterface.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 055C24EF2E28FD9800AD389C /* PresentationTesting.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PresentationTesting.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 05A7C15F2E26768A0010F1CD /* LoginFeature.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LoginFeature.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 05A7C16E2E2676E60010F1CD /* LoginFeatureInterface.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LoginFeatureInterface.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 05A7C1922E26771A0010F1CD /* LoginFeatureDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LoginFeatureDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 05A7C1AE2E2679290010F1CD /* DesignSystem.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = DesignSystem.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 05A7C1BB2E2679FC0010F1CD /* Infrastructure.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Infrastructure.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 05A7CBD22E27D0700010F1CD /* PresentationInterface.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PresentationInterface.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 05A7CBD62E27D3510010F1CD /* Presentation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Presentation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 05A7CBD72E27D3510010F1CD /* PresentationInterface.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PresentationInterface.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 05A7CBDC2E27D44F0010F1CD /* Data.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Data.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 05A7CBDD2E27D44F0010F1CD /* Domain.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Domain.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 05A7CBDE2E27D44F0010F1CD /* DomainInterface.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = DomainInterface.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 05A7CC072E27DC8E0010F1CD /* SearchFeatureInterface.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SearchFeatureInterface.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + 05A7C1A32E26771B0010F1CD /* Exceptions for "LoginFeatureDemo" folder in "LoginFeatureDemo" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Resource/Info.plist, + ); + target = 05A7C1912E26771A0010F1CD /* LoginFeatureDemo */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 05A7C1612E26768A0010F1CD /* LoginFeature */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = LoginFeature; + sourceTree = ""; + }; + 05A7C16F2E2676E60010F1CD /* LoginFeatureInterface */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = LoginFeatureInterface; + sourceTree = ""; + }; + 05A7C1932E26771A0010F1CD /* LoginFeatureDemo */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + 05A7C1A32E26771B0010F1CD /* Exceptions for "LoginFeatureDemo" folder in "LoginFeatureDemo" target */, + ); + path = LoginFeatureDemo; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + 05A7C15C2E26768A0010F1CD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 05A7CBB92E277AE30010F1CD /* Then in Frameworks */, + 05A7CBD32E27D0700010F1CD /* PresentationInterface.framework in Frameworks */, + 05A7C1D62E267B130010F1CD /* RxCocoa in Frameworks */, + 05A7CBE62E27D5390010F1CD /* SnapKit in Frameworks */, + 05A7C1D32E267AF80010F1CD /* ReactorKit in Frameworks */, + 05A7C1D82E267B130010F1CD /* RxSwift in Frameworks */, + 05A7C1BE2E267A120010F1CD /* LoginFeatureInterface.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 05A7C16B2E2676E60010F1CD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 05A7C1AF2E2679290010F1CD /* DesignSystem.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 05A7C18F2E26771A0010F1CD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 05A7CC032E27DC130010F1CD /* Pageboy in Frameworks */, + 05A7C1BC2E2679FC0010F1CD /* Infrastructure.framework in Frameworks */, + 05A7C1B22E26799A0010F1CD /* LoginFeature.framework in Frameworks */, + 05A7CBFA2E27DBDE0010F1CD /* ReactorKit in Frameworks */, + 05A7CC002E27DBDE0010F1CD /* Then in Frameworks */, + 05A7C1B62E26799A0010F1CD /* LoginFeatureInterface.framework in Frameworks */, + 05A7CC102E28EC150010F1CD /* KakaoSDKUser in Frameworks */, + 05A7CC0E2E28EC150010F1CD /* KakaoSDKAuth in Frameworks */, + 05A7CBE12E27D44F0010F1CD /* Domain.framework in Frameworks */, + 05A7CBFE2E27DBDE0010F1CD /* RxSwift in Frameworks */, + 055C24F02E28FD9800AD389C /* PresentationTesting.framework in Frameworks */, + 05A7CBFC2E27DBDE0010F1CD /* RxCocoa in Frameworks */, + 05A7CBDF2E27D44F0010F1CD /* Data.framework in Frameworks */, + 05A7CBE82E27D5400010F1CD /* SnapKit in Frameworks */, + 05A7CBF72E27DBB30010F1CD /* DesignSystem.framework in Frameworks */, + 05A7CBE32E27D44F0010F1CD /* DomainInterface.framework in Frameworks */, + 05A7CBDA2E27D3510010F1CD /* PresentationInterface.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 05A7C1552E26768A0010F1CD = { + isa = PBXGroup; + children = ( + 05A7C1612E26768A0010F1CD /* LoginFeature */, + 05A7C16F2E2676E60010F1CD /* LoginFeatureInterface */, + 05A7C1932E26771A0010F1CD /* LoginFeatureDemo */, + 05A7C1AD2E2679290010F1CD /* Frameworks */, + 05A7C1602E26768A0010F1CD /* Products */, + ); + sourceTree = ""; + }; + 05A7C1602E26768A0010F1CD /* Products */ = { + isa = PBXGroup; + children = ( + 05A7C15F2E26768A0010F1CD /* LoginFeature.framework */, + 05A7C16E2E2676E60010F1CD /* LoginFeatureInterface.framework */, + 05A7C1922E26771A0010F1CD /* LoginFeatureDemo.app */, + ); + name = Products; + sourceTree = ""; + }; + 05A7C1AD2E2679290010F1CD /* Frameworks */ = { + isa = PBXGroup; + children = ( + 055C24EF2E28FD9800AD389C /* PresentationTesting.framework */, + 05A7CC072E27DC8E0010F1CD /* SearchFeatureInterface.framework */, + 05A7CBDC2E27D44F0010F1CD /* Data.framework */, + 05A7CBDD2E27D44F0010F1CD /* Domain.framework */, + 05A7CBDE2E27D44F0010F1CD /* DomainInterface.framework */, + 05A7CBD62E27D3510010F1CD /* Presentation.framework */, + 05A7CBD72E27D3510010F1CD /* PresentationInterface.framework */, + 05A7CBD22E27D0700010F1CD /* PresentationInterface.framework */, + 05A7C1BB2E2679FC0010F1CD /* Infrastructure.framework */, + 05A7C1AE2E2679290010F1CD /* DesignSystem.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 05A7C15A2E26768A0010F1CD /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 05A7C1692E2676E60010F1CD /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 05A7C15E2E26768A0010F1CD /* LoginFeature */ = { + isa = PBXNativeTarget; + buildConfigurationList = 05A7C1662E26768A0010F1CD /* Build configuration list for PBXNativeTarget "LoginFeature" */; + buildPhases = ( + 05A7C15A2E26768A0010F1CD /* Headers */, + 05A7C15B2E26768A0010F1CD /* Sources */, + 05A7C15C2E26768A0010F1CD /* Frameworks */, + 05A7C15D2E26768A0010F1CD /* Resources */, + 05A7CBD52E27D0700010F1CD /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 05A7C1C12E267A120010F1CD /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + 05A7C1612E26768A0010F1CD /* LoginFeature */, + ); + name = LoginFeature; + packageProductDependencies = ( + 05A7C1D22E267AF80010F1CD /* ReactorKit */, + 05A7C1D52E267B130010F1CD /* RxCocoa */, + 05A7C1D72E267B130010F1CD /* RxSwift */, + 05A7CBB82E277AE30010F1CD /* Then */, + 05A7CBE52E27D5390010F1CD /* SnapKit */, + ); + productName = LoginFeature; + productReference = 05A7C15F2E26768A0010F1CD /* LoginFeature.framework */; + productType = "com.apple.product-type.framework"; + }; + 05A7C16D2E2676E60010F1CD /* LoginFeatureInterface */ = { + isa = PBXNativeTarget; + buildConfigurationList = 05A7C1722E2676E60010F1CD /* Build configuration list for PBXNativeTarget "LoginFeatureInterface" */; + buildPhases = ( + 05A7C1692E2676E60010F1CD /* Headers */, + 05A7C16A2E2676E60010F1CD /* Sources */, + 05A7C16B2E2676E60010F1CD /* Frameworks */, + 05A7C16C2E2676E60010F1CD /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 05A7C16F2E2676E60010F1CD /* LoginFeatureInterface */, + ); + name = LoginFeatureInterface; + packageProductDependencies = ( + ); + productName = LoginFeatureInterface; + productReference = 05A7C16E2E2676E60010F1CD /* LoginFeatureInterface.framework */; + productType = "com.apple.product-type.framework"; + }; + 05A7C1912E26771A0010F1CD /* LoginFeatureDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 05A7C1A42E26771B0010F1CD /* Build configuration list for PBXNativeTarget "LoginFeatureDemo" */; + buildPhases = ( + 05A7C18E2E26771A0010F1CD /* Sources */, + 05A7C18F2E26771A0010F1CD /* Frameworks */, + 05A7C1902E26771A0010F1CD /* Resources */, + 05A7C1BA2E26799A0010F1CD /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 05A7C1B52E26799A0010F1CD /* PBXTargetDependency */, + 05A7C1B92E26799A0010F1CD /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + 05A7C1932E26771A0010F1CD /* LoginFeatureDemo */, + ); + name = LoginFeatureDemo; + packageProductDependencies = ( + 05A7CBE72E27D5400010F1CD /* SnapKit */, + 05A7CBF92E27DBDE0010F1CD /* ReactorKit */, + 05A7CBFB2E27DBDE0010F1CD /* RxCocoa */, + 05A7CBFD2E27DBDE0010F1CD /* RxSwift */, + 05A7CBFF2E27DBDE0010F1CD /* Then */, + 05A7CC022E27DC130010F1CD /* Pageboy */, + 05A7CC0D2E28EC150010F1CD /* KakaoSDKAuth */, + 05A7CC0F2E28EC150010F1CD /* KakaoSDKUser */, + ); + productName = LoginFeatureDemo; + productReference = 05A7C1922E26771A0010F1CD /* LoginFeatureDemo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 05A7C1562E26768A0010F1CD /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1640; + LastUpgradeCheck = 1640; + TargetAttributes = { + 05A7C15E2E26768A0010F1CD = { + CreatedOnToolsVersion = 16.4; + }; + 05A7C16D2E2676E60010F1CD = { + CreatedOnToolsVersion = 16.4; + }; + 05A7C1912E26771A0010F1CD = { + CreatedOnToolsVersion = 16.4; + }; + }; + }; + buildConfigurationList = 05A7C1592E26768A0010F1CD /* Build configuration list for PBXProject "LoginFeature" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 05A7C1552E26768A0010F1CD; + minimizedProjectReferenceProxies = 1; + packageReferences = ( + 05A7C1D12E267AF80010F1CD /* XCRemoteSwiftPackageReference "ReactorKit" */, + 05A7C1D42E267B130010F1CD /* XCRemoteSwiftPackageReference "RxSwift" */, + 05A7CBB42E277AD20010F1CD /* XCRemoteSwiftPackageReference "SnapKit" */, + 05A7CBB72E277AE30010F1CD /* XCRemoteSwiftPackageReference "Then" */, + 05A7CC012E27DC130010F1CD /* XCRemoteSwiftPackageReference "Pageboy" */, + 05A7CC042E27DC5E0010F1CD /* XCRemoteSwiftPackageReference "SPM-NMapsMap" */, + 05A7CC0A2E28EC030010F1CD /* XCRemoteSwiftPackageReference "kakao-ios-sdk" */, + ); + preferredProjectObjectVersion = 77; + productRefGroup = 05A7C1602E26768A0010F1CD /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 05A7C15E2E26768A0010F1CD /* LoginFeature */, + 05A7C16D2E2676E60010F1CD /* LoginFeatureInterface */, + 05A7C1912E26771A0010F1CD /* LoginFeatureDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 05A7C15D2E26768A0010F1CD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 05A7C16C2E2676E60010F1CD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 05A7C1902E26771A0010F1CD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 05A7C15B2E26768A0010F1CD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 05A7C16A2E2676E60010F1CD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 05A7C18E2E26771A0010F1CD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 05A7C1B52E26799A0010F1CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 05A7C15E2E26768A0010F1CD /* LoginFeature */; + targetProxy = 05A7C1B42E26799A0010F1CD /* PBXContainerItemProxy */; + }; + 05A7C1B92E26799A0010F1CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 05A7C16D2E2676E60010F1CD /* LoginFeatureInterface */; + targetProxy = 05A7C1B82E26799A0010F1CD /* PBXContainerItemProxy */; + }; + 05A7C1C12E267A120010F1CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 05A7C16D2E2676E60010F1CD /* LoginFeatureInterface */; + targetProxy = 05A7C1C02E267A120010F1CD /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 05A7C1642E26768A0010F1CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 05A7C1652E26768A0010F1CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 05A7C1672E26768A0010F1CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = NO; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = com.poppoolIOS.poppool.LoginFeature; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + 05A7C1682E26768A0010F1CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = NO; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = com.poppoolIOS.poppool.LoginFeature; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; + 05A7C1732E2676E60010F1CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = NO; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = com.poppoolIOS.poppool.LoginFeatureInterface; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + 05A7C1742E2676E60010F1CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = NO; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = com.poppoolIOS.poppool.LoginFeatureInterface; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; + 05A7C1A52E26771B0010F1CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 9JZYRP3D46; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = LoginFeatureDemo/Resource/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.poppoolIOS.poppool.LoginFeatureDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development com.poppoolIOS.*"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + 05A7C1A62E26771B0010F1CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 9JZYRP3D46; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = LoginFeatureDemo/Resource/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.poppoolIOS.poppool.LoginFeatureDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.poppoolIOS.*"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 05A7C1592E26768A0010F1CD /* Build configuration list for PBXProject "LoginFeature" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 05A7C1642E26768A0010F1CD /* Debug */, + 05A7C1652E26768A0010F1CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 05A7C1662E26768A0010F1CD /* Build configuration list for PBXNativeTarget "LoginFeature" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 05A7C1672E26768A0010F1CD /* Debug */, + 05A7C1682E26768A0010F1CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 05A7C1722E2676E60010F1CD /* Build configuration list for PBXNativeTarget "LoginFeatureInterface" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 05A7C1732E2676E60010F1CD /* Debug */, + 05A7C1742E2676E60010F1CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 05A7C1A42E26771B0010F1CD /* Build configuration list for PBXNativeTarget "LoginFeatureDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 05A7C1A52E26771B0010F1CD /* Debug */, + 05A7C1A62E26771B0010F1CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 05A7C1D12E267AF80010F1CD /* XCRemoteSwiftPackageReference "ReactorKit" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/ReactorKit/ReactorKit"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 3.2.0; + }; + }; + 05A7C1D42E267B130010F1CD /* XCRemoteSwiftPackageReference "RxSwift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/ReactiveX/RxSwift"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 6.9.0; + }; + }; + 05A7CBB42E277AD20010F1CD /* XCRemoteSwiftPackageReference "SnapKit" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/SnapKit/SnapKit"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 5.7.1; + }; + }; + 05A7CBB72E277AE30010F1CD /* XCRemoteSwiftPackageReference "Then" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/devxoul/Then"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 3.0.0; + }; + }; + 05A7CC012E27DC130010F1CD /* XCRemoteSwiftPackageReference "Pageboy" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/uias/Pageboy"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 4.2.0; + }; + }; + 05A7CC042E27DC5E0010F1CD /* XCRemoteSwiftPackageReference "SPM-NMapsMap" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/navermaps/SPM-NMapsMap"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 3.22.0; + }; + }; + 05A7CC0A2E28EC030010F1CD /* XCRemoteSwiftPackageReference "kakao-ios-sdk" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/kakao/kakao-ios-sdk"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.24.5; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 05A7C1D22E267AF80010F1CD /* ReactorKit */ = { + isa = XCSwiftPackageProductDependency; + package = 05A7C1D12E267AF80010F1CD /* XCRemoteSwiftPackageReference "ReactorKit" */; + productName = ReactorKit; + }; + 05A7C1D52E267B130010F1CD /* RxCocoa */ = { + isa = XCSwiftPackageProductDependency; + package = 05A7C1D42E267B130010F1CD /* XCRemoteSwiftPackageReference "RxSwift" */; + productName = RxCocoa; + }; + 05A7C1D72E267B130010F1CD /* RxSwift */ = { + isa = XCSwiftPackageProductDependency; + package = 05A7C1D42E267B130010F1CD /* XCRemoteSwiftPackageReference "RxSwift" */; + productName = RxSwift; + }; + 05A7CBB82E277AE30010F1CD /* Then */ = { + isa = XCSwiftPackageProductDependency; + package = 05A7CBB72E277AE30010F1CD /* XCRemoteSwiftPackageReference "Then" */; + productName = Then; + }; + 05A7CBE52E27D5390010F1CD /* SnapKit */ = { + isa = XCSwiftPackageProductDependency; + package = 05A7CBB42E277AD20010F1CD /* XCRemoteSwiftPackageReference "SnapKit" */; + productName = SnapKit; + }; + 05A7CBE72E27D5400010F1CD /* SnapKit */ = { + isa = XCSwiftPackageProductDependency; + package = 05A7CBB42E277AD20010F1CD /* XCRemoteSwiftPackageReference "SnapKit" */; + productName = SnapKit; + }; + 05A7CBF92E27DBDE0010F1CD /* ReactorKit */ = { + isa = XCSwiftPackageProductDependency; + package = 05A7C1D12E267AF80010F1CD /* XCRemoteSwiftPackageReference "ReactorKit" */; + productName = ReactorKit; + }; + 05A7CBFB2E27DBDE0010F1CD /* RxCocoa */ = { + isa = XCSwiftPackageProductDependency; + package = 05A7C1D42E267B130010F1CD /* XCRemoteSwiftPackageReference "RxSwift" */; + productName = RxCocoa; + }; + 05A7CBFD2E27DBDE0010F1CD /* RxSwift */ = { + isa = XCSwiftPackageProductDependency; + package = 05A7C1D42E267B130010F1CD /* XCRemoteSwiftPackageReference "RxSwift" */; + productName = RxSwift; + }; + 05A7CBFF2E27DBDE0010F1CD /* Then */ = { + isa = XCSwiftPackageProductDependency; + package = 05A7CBB72E277AE30010F1CD /* XCRemoteSwiftPackageReference "Then" */; + productName = Then; + }; + 05A7CC022E27DC130010F1CD /* Pageboy */ = { + isa = XCSwiftPackageProductDependency; + package = 05A7CC012E27DC130010F1CD /* XCRemoteSwiftPackageReference "Pageboy" */; + productName = Pageboy; + }; + 05A7CC0D2E28EC150010F1CD /* KakaoSDKAuth */ = { + isa = XCSwiftPackageProductDependency; + package = 05A7CC0A2E28EC030010F1CD /* XCRemoteSwiftPackageReference "kakao-ios-sdk" */; + productName = KakaoSDKAuth; + }; + 05A7CC0F2E28EC150010F1CD /* KakaoSDKUser */ = { + isa = XCSwiftPackageProductDependency; + package = 05A7CC0A2E28EC030010F1CD /* XCRemoteSwiftPackageReference "kakao-ios-sdk" */; + productName = KakaoSDKUser; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 05A7C1562E26768A0010F1CD /* Project object */; +} diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeature.xcodeproj/xcshareddata/xcschemes/LoginFeatureDemo.xcscheme b/Poppool/PresentationLayer/LoginFeature/LoginFeature.xcodeproj/xcshareddata/xcschemes/LoginFeatureDemo.xcscheme new file mode 100644 index 00000000..28ce13b8 --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeature.xcodeproj/xcshareddata/xcschemes/LoginFeatureDemo.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeature/Factory/LoginFactory.swift b/Poppool/PresentationLayer/LoginFeature/LoginFeature/Factory/LoginFactory.swift new file mode 100644 index 00000000..1f87be78 --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeature/Factory/LoginFactory.swift @@ -0,0 +1,27 @@ +import UIKit + +import DesignSystem +import DomainInterface +import Infrastructure +import LoginFeatureInterface + +public final class LoginFactoryImpl: LoginFactory { + + public init() { } + + public func make( + _ loginSceneType: LoginSceneType, + text: String + ) -> BaseViewController { + let viewController = LoginViewController(loginSceneType: loginSceneType, text: text) + + viewController.reactor = LoginReactor( + for: loginSceneType, + authAPIUseCase: DIContainer.resolve(AuthAPIUseCase.self), + kakaoLoginUseCase: DIContainer.resolve(KakaoLoginUseCase.self), + appleLoginUseCase: DIContainer.resolve(AppleLoginUseCase.self) + ) + + return viewController + } +} diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/LastLoginView.swift b/Poppool/PresentationLayer/LoginFeature/LoginFeature/Login/LastLoginView.swift similarity index 93% rename from Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/LastLoginView.swift rename to Poppool/PresentationLayer/LoginFeature/LoginFeature/Login/LastLoginView.swift index eeebbd5a..7a43ada4 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/LastLoginView.swift +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeature/Login/LastLoginView.swift @@ -1,10 +1,3 @@ -// -// LastLoginView.swift -// Poppool -// -// Created by SeoJunYoung on 1/16/25. -// - import UIKit import SnapKit @@ -189,18 +182,24 @@ extension LastLoginView { layer.shadowRadius = 5 // 섀도우를 그릴 때 드는 리소스를 줄이기 위해 캐시를 적용하는 방식 -// layer.shadowPath = UIBezierPath(rect: self.bounds).cgPath + // layer.shadowPath = UIBezierPath(rect: self.bounds).cgPath layer.shouldRasterize = true layer.rasterizationScale = UIScreen.main.scale } } extension UIView { - func showToolTip(color: LastLoginView.TipColor, direction: LastLoginView.TipDirection, text: String? = "최근에 이 방법으로 로그인했어요") { + func showToolTip( + color: LastLoginView.TipColor, + direction: LastLoginView.TipDirection, + text: String? = "최근에 이 방법으로 로그인했어요" + ) { // 호출하는 컴포넌트 위 또는 아래에 생성되기 위해 superview를 구합니다 guard let superview = self.superview else { return } let toolTip = LastLoginView(colorType: color, direction: direction, text: text) + let beforeToolTip = superview.subviews.filter { $0 is LastLoginView } + beforeToolTip.forEach { $0.removeFromSuperview() } superview.addSubview(toolTip) toolTip.snp.makeConstraints { make in diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeature/Login/LoginReactor.swift b/Poppool/PresentationLayer/LoginFeature/LoginFeature/Login/LoginReactor.swift new file mode 100644 index 00000000..de8ff39a --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeature/Login/LoginReactor.swift @@ -0,0 +1,227 @@ +import DesignSystem +import DomainInterface +import Infrastructure +import LoginFeatureInterface +import PresentationInterface + +import ReactorKit +import RxCocoa +import RxSwift + +final class LoginReactor: Reactor { + + // MARK: - Reactor + enum Action { + case viewWillAppear + case kakaoButtonTapped + case appleButtonTapped + case guestButtonTapped + case xmarkButtonTapped + case inquiryButtonTapped + } + + enum Mutation { + case moveToSignUpScene(from: LoginSceneType, authorizationCode: String?) + case moveToHomeScene + case moveToBeforeScene + case moveToInquiryScene + case showTooltip(of: TooltipType?) + } + + struct State { + var tooltipType: TooltipType? + @Pulse var present: PresentTarget? + } + + enum PresentTarget { + case signUp(isFirstResponder: Bool, authorizationCode: String?) + case home + case dismiss + case inquiry + } + + enum TooltipType: String { + case kakao, apple + } + + // MARK: - properties + + var initialState: State + var disposeBag = DisposeBag() + + private let loginSceneType: LoginSceneType + private let authAPIUseCase: AuthAPIUseCase + private let kakaoLoginUseCase: KakaoLoginUseCase + private let appleLoginUseCase: AppleLoginUseCase + + @Dependency private var keyChainService: KeyChainService + @Dependency private var userDefaultService: UserDefaultService + + // MARK: - init + init( + for loginSceneType: LoginSceneType, + authAPIUseCase: AuthAPIUseCase, + kakaoLoginUseCase: KakaoLoginUseCase, + appleLoginUseCase: AppleLoginUseCase + ) { + self.initialState = State() + self.loginSceneType = loginSceneType + self.authAPIUseCase = authAPIUseCase + self.kakaoLoginUseCase = kakaoLoginUseCase + self.appleLoginUseCase = appleLoginUseCase + } + + // MARK: - Reactor Methods + func mutate(action: Action) -> Observable { + switch action { + case .viewWillAppear: + return updateTooltip() + + case .kakaoButtonTapped: + return loginWithKakao() + + case .appleButtonTapped: + return loginWithApple() + + case .guestButtonTapped: + keyChainService.deleteToken(type: .accessToken) + keyChainService.deleteToken(type: .refreshToken) + return Observable.just(.moveToHomeScene) + + case .xmarkButtonTapped: + return Observable.just(.moveToBeforeScene) + + case .inquiryButtonTapped: + return Observable.just(.moveToInquiryScene) + } + } + + func reduce(state: State, mutation: Mutation) -> State { + var newState = state + + switch mutation { + case .showTooltip(let tooltipType): + newState.tooltipType = tooltipType + + case .moveToSignUpScene(let loginSceneType, let authorizationCode): + newState.present = .signUp( + isFirstResponder: loginSceneType == .main, + authorizationCode: authorizationCode + ) + + case .moveToHomeScene: + newState.present = .home + + case .moveToBeforeScene: + newState.present = .dismiss + + case .moveToInquiryScene: + newState.present = .inquiry + } + + return newState + } + + func loginWithKakao() -> Observable { + return kakaoLoginUseCase.fetchUserCredential() + .withUnretained(self) + .flatMap { (owner, authServiceResponse) in + return owner.authAPIUseCase.postTryLogin( + userCredential: authServiceResponse, + socialType: "kakao" + ) + } + .withUnretained(self) + .do { (owner, loginResponse) in + owner.userDefaultService.save(keyType: .userID, value: loginResponse.userId) + owner.userDefaultService.save(keyType: .socialType, value: loginResponse.socialType) + owner.keyChainService.saveToken(type: .refreshToken, value: loginResponse.refreshToken) + } + .flatMap { (owner, loginResponse) -> Observable in + let accessTokenResult = owner.keyChainService.saveToken( + type: .accessToken, + value: loginResponse.accessToken + ) + + switch accessTokenResult { + case .success: + switch loginResponse.isRegisteredUser { + case true: + owner.userDefaultService.save(keyType: .lastLogin, value: "kakao") + return Observable.just( + owner.loginSceneType == .main ? .moveToHomeScene : .moveToBeforeScene + ) + + case false: + return Observable.just( + .moveToSignUpScene( + from: owner.loginSceneType, + authorizationCode: nil + ) + ) + } + + case .failure(let error): + // TODO: 로거 개선 후 로그인 실패 에러 남기기 + return Observable.empty() + } + } + } + + func loginWithApple() -> Observable { + return appleLoginUseCase.fetchUserCredential() + .withUnretained(self) + .flatMap { (owner, authServiceResponse) -> Observable<(String?, LoginResponse)> in + return owner.authAPIUseCase.postTryLogin( + userCredential: authServiceResponse, + socialType: "apple" + ) + .map { (authServiceResponse.authorizationCode, $0) } + } + .withUnretained(self) + .do { (owner, tuple) in + let loginResponse = tuple.1 + owner.userDefaultService.save(keyType: .userID, value: loginResponse.userId) + owner.userDefaultService.save(keyType: .socialType, value: loginResponse.socialType) + owner.keyChainService.saveToken(type: .refreshToken, value: loginResponse.refreshToken) + } + .flatMap { (owner, tuple) -> Observable in + let (authCode, loginResponse) = tuple + + let accessResult = owner.keyChainService.saveToken( + type: .accessToken, + value: loginResponse.accessToken + ) + switch accessResult { + case .success: + switch loginResponse.isRegisteredUser { + case true: + owner.userDefaultService.save(keyType: .lastLogin, value: "apple") + return .just(owner.loginSceneType == .main ? .moveToHomeScene : .moveToBeforeScene) + + case false: + return .just( + .moveToSignUpScene( + from: owner.loginSceneType, + authorizationCode: authCode + ) + ) + } + + case .failure: + // TODO: 로거 개선 후 로그인 실패 에러 남기기 + return .empty() + } + } + } +} + +extension LoginReactor { + private func updateTooltip() -> Observable { + if let lastLogin = userDefaultService.fetch(keyType: .lastLogin) { + return .just(.showTooltip(of: TooltipType(rawValue: lastLogin))) + } else { + return .empty() + } + } +} diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeature/Login/LoginView.swift b/Poppool/PresentationLayer/LoginFeature/LoginFeature/Login/LoginView.swift new file mode 100644 index 00000000..e24e2273 --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeature/Login/LoginView.swift @@ -0,0 +1,159 @@ +import UIKit + +import DesignSystem +import LoginFeatureInterface + +import SnapKit +import Then + +final class LoginView: UIView { + + // MARK: - Components + let guestButton = UIButton(type: .system).then { + $0.setTitle("둘러보기", for: .normal) + $0.titleLabel?.font = .korFont(style: .regular, size: 14) + $0.setTitleColor(.g1000, for: .normal) + $0.isHidden = true + } + + let xmarkButton = UIButton(type: .system).then { + $0.setImage(UIImage(named: "icon_xmark"), for: .normal) + $0.tintColor = .g1000 + $0.isHidden = true + } + + private let logoImageView = UIImageView().then { + $0.image = UIImage(named: "image_login_logo") + $0.contentMode = .scaleAspectFit + } + + let titleLabel = PPLabel() + + let kakaoButton = PPButton(style: .kakao, text: "카카오톡으로 로그인") + + private let kakaoImageView = UIImageView().then { + $0.image = UIImage(named: "icon_login_kakao") + } + + let appleButton = PPButton(style: .apple, text: "Apple로 로그인") + + private let appleImageView = UIImageView().then { + $0.image = UIImage(named: "icon_login_apple") + } + + let inquiryButton = UIButton(type: .system).then { + $0.setTitle("로그인이 어려우신가요?", for: .normal) + $0.titleLabel?.font = .korFont(style: .regular, size: 12) + $0.setTitleColor(.g1000, for: .normal) + } + + // MARK: - init + init() { + super.init(frame: .zero) + + self.addViews() + self.setupConstraints() + } + + required init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } + + deinit { + print("DEINIT DEBUG: \(#file)") + } +} + +// MARK: - SetUp +private extension LoginView { + + func addViews() { + [guestButton, xmarkButton, logoImageView, titleLabel, kakaoButton, appleButton, inquiryButton].forEach { + self.addSubview($0) + } + + [kakaoImageView].forEach { + kakaoButton.addSubview($0) + } + + [appleImageView].forEach { + appleButton.addSubview($0) + } + } + + func setupConstraints() { + guestButton.snp.makeConstraints { make in + make.top.equalTo(safeAreaLayoutGuide).inset(11) + make.trailing.equalToSuperview().inset(20) + } + + xmarkButton.snp.makeConstraints { make in + make.top.equalTo(safeAreaLayoutGuide).inset(11) + make.trailing.equalToSuperview().inset(20) + make.size.equalTo(32) + } + + logoImageView.snp.makeConstraints { make in + make.height.equalTo(90) + make.width.equalTo(70) + make.top.equalTo(guestButton.snp.bottom).offset(75) + make.centerX.equalToSuperview() + } + + titleLabel.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.top.equalTo(logoImageView.snp.bottom).offset(28) + } + + kakaoButton.snp.makeConstraints { make in + make.top.equalTo(titleLabel.snp.bottom).offset(156) + make.leading.trailing.equalToSuperview().inset(20) + make.height.equalTo(50) + } + + kakaoImageView.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.leading.equalToSuperview().inset(20) + make.size.equalTo(22) + } + + appleButton.snp.makeConstraints { make in + make.top.equalTo(kakaoButton.snp.bottom).offset(16) + make.leading.trailing.equalToSuperview().inset(20) + make.height.equalTo(50) + } + + appleImageView.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.leading.equalToSuperview().inset(20) + make.size.equalTo(22) + } + + inquiryButton.snp.makeConstraints { make in + make.bottom.equalToSuperview().inset(56) + make.centerX.equalToSuperview() + } + } +} + +extension LoginView { + func setTitle(_ title: String) { + self.titleLabel.setLineHeightText( + text: title, + font: .korFont(style: .bold, size: 16), + lineHeight: 1.3 + ) + self.titleLabel.numberOfLines = 0 + self.titleLabel.textAlignment = .center + } + + func setCloseButton(for loginSceneType: LoginSceneType) { + switch loginSceneType { + case .main: + self.guestButton.isHidden = false + + case .sub: + self.xmarkButton.isHidden = false + } + } +} diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeature/Login/LoginViewController.swift b/Poppool/PresentationLayer/LoginFeature/LoginFeature/Login/LoginViewController.swift new file mode 100644 index 00000000..eb6d46e2 --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeature/Login/LoginViewController.swift @@ -0,0 +1,145 @@ +import UIKit + +import DesignSystem +import Infrastructure +import LoginFeatureInterface +import PresentationInterface +import ReactorKit +import RxCocoa +import RxSwift +import SnapKit + +/// 다른 처리가 뭐가 있을까 +/// 1. 코멘트 타이틀 +/// 1-1. 외부로부터 주입(상황에 맞춰 적절한 코멘트를 띄우기 위함) +/// 2. 우상단 버튼의 형태 +/// 2-1. 둘러보기/xmark +/// 2-2. 버튼의 타입만 전달받도록? +/// 2-3. 사이즈가 달라서 어려움이 있다고 봄 +/// 3. 우상단 버튼의 동작 -> 클로저로 넘긴다면 Reactor로 어떻게 처리? +/// 3-1. 일단 받아두고 reactor로부터 명령이 오면 실행 +/// 3-2. 이러면 viewController를 만들 때 클로저를 넣어줘야됨. -> factory, init 변경 +/// 4. 배경 색상 +/// 4-1. g50 -> subLogin +/// 4-2. w100 -> main login + +final class LoginViewController: BaseViewController, View { + + typealias Reactor = LoginReactor + + // MARK: - Properties + var disposeBag = DisposeBag() + + private var mainView = LoginView() + + public convenience init( + loginSceneType: LoginSceneType, + text: String + ) { + self.init() + + self.mainView.setCloseButton(for: loginSceneType) + self.mainView.setTitle(text) + } + + private override init() { + super.init() + } + + public required init?(coder: NSCoder) { + fatalError("\(#file), \(#function) Error") + } + + override func loadView() { + self.view = mainView + } +} + +extension LoginViewController { + func bind(reactor: Reactor) { + bindInput(reactor: reactor) + bindOutput(reactor: reactor) + } + + private func bindInput(reactor: Reactor) { + rx.viewWillAppear + .map { Reactor.Action.viewWillAppear } + .bind(to: reactor.action) + .disposed(by: disposeBag) + + mainView.guestButton.rx.tap + .map { Reactor.Action.guestButtonTapped } + .bind(to: reactor.action) + .disposed(by: disposeBag) + + mainView.xmarkButton.rx.tap + .map { Reactor.Action.xmarkButtonTapped } + .bind(to: reactor.action) + .disposed(by: disposeBag) + + mainView.kakaoButton.rx.tap + .map { Reactor.Action.kakaoButtonTapped } + .bind(to: reactor.action) + .disposed(by: disposeBag) + + mainView.inquiryButton.rx.tap + .map { Reactor.Action.inquiryButtonTapped } + .bind(to: reactor.action) + .disposed(by: disposeBag) + + mainView.appleButton.rx.tap + .map { Reactor.Action.appleButtonTapped } + .bind(to: reactor.action) + .disposed(by: disposeBag) + } + + private func bindOutput(reactor: Reactor) { + reactor.pulse(\.$present) + .skip(1) + .withUnretained(self) + .subscribe { (owner, target) in + switch target! { + case .signUp(let isFirstResponder, let authorizationCode): + @Dependency var factory: SignUpFactory + owner.navigationController?.pushViewController( + factory.make( + isFirstResponder: isFirstResponder, + authorizationCode: authorizationCode + ), + animated: true + ) + + case .home: + @Dependency var factory: WaveTabbarFactory + owner.view.window?.rootViewController = factory.make() + + case .dismiss: + owner.dismiss(animated: true) + + case .inquiry: + @Dependency var factory: FAQFactory + owner.navigationController?.pushViewController( + factory.make(), + animated: true + ) + } + } + .disposed(by: disposeBag) + + reactor.state.distinctUntilChanged(\.tooltipType) + .skip(1) + .map { $0.tooltipType } + .withUnretained(self) + .subscribe { (owner, type) in + switch type { + case .kakao: + owner.mainView.kakaoButton.showToolTip(color: .w100, direction: .pointDown) + case .apple: + owner.mainView.appleButton.showToolTip(color: .w100, direction: .pointUp) + case .none: + return + } + } + .disposed(by: disposeBag) + } +} diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/App/AppDelegate.swift b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/App/AppDelegate.swift new file mode 100644 index 00000000..a940ebaa --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/App/AppDelegate.swift @@ -0,0 +1,62 @@ +import UIKit + +import Data +import Domain +import DomainInterface +import Infrastructure +import LoginFeature +import LoginFeatureInterface +import PresentationInterface +import PresentationTesting + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + + self.registerDependencies() + self.registerFactory() + + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } +} + +extension AppDelegate { + private func registerDependencies() { + // MARK: Register Service + DIContainer.register(Provider.self) { return ProviderImpl() } + DIContainer.register(UserDefaultService.self) { return UserDefaultService() } + DIContainer.register(KeyChainService.self) { return KeyChainService() } + + // MARK: Resolve service + @Dependency var provider: Provider + + // MARK: Register repository + DIContainer.register(AuthAPIRepository.self) { return AuthAPIRepositoryImpl(provider: provider) } + DIContainer.register(KakaoLoginRepository.self) { return KakaoLoginRepositoryImpl() } + DIContainer.register(AppleLoginRepository.self) { return AppleLoginRepositoryImpl() } + + // MARK: Resolve repository + @Dependency var authAPIRepository: AuthAPIRepository + @Dependency var kakaoLoginRepository: KakaoLoginRepository + @Dependency var appleLoginRepository: AppleLoginRepository + + // MARK: Register UseCase + DIContainer.register(AuthAPIUseCase.self) { return AuthAPIUseCaseImpl(repository: authAPIRepository) } + DIContainer.register(KakaoLoginUseCase.self) { return KakaoLoginUseCaseImpl(repository: kakaoLoginRepository) } + DIContainer.register(AppleLoginUseCase.self) { return AppleLoginUseCaseImpl(repository: appleLoginRepository) } + } + + private func registerFactory() { + DIContainer.register(LoginFactory.self) { return LoginFactoryImpl() } + DIContainer.register(SignUpFactory.self) { return SignUpFactoryMock() } + DIContainer.register(WaveTabbarFactory.self) { return WaveTabbarFactoryMock() } + DIContainer.register(FAQFactory.self) { return FAQFactoryMock() } + } +} diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/App/SceneDelegate.swift b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/App/SceneDelegate.swift new file mode 100644 index 00000000..01261a1f --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/App/SceneDelegate.swift @@ -0,0 +1,26 @@ +import UIKit + +import Infrastructure +import LoginFeatureInterface + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + guard let windowScene = (scene as? UIWindowScene) else { return } + + window = UIWindow(windowScene: windowScene) + + let navigationController = UINavigationController() + @Dependency var factory: LoginFactory + + navigationController.pushViewController( + factory.make(.main, text: "간편하게 SNS 로그인하고\n팝풀 서비스를 이용해보세요"), + animated: false + ) + + window?.rootViewController = navigationController + window?.makeKeyAndVisible() + } +} diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/AccentColor.colorset/Contents.json b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/AppIcon.appiconset/Contents.json b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..23058801 --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,35 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/Contents.json b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/icon_login_apple.imageset/Contents.json b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/icon_login_apple.imageset/Contents.json new file mode 100644 index 00000000..ad42a58d --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/icon_login_apple.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "logo.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/icon_login_apple.imageset/logo.svg b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/icon_login_apple.imageset/logo.svg new file mode 100644 index 00000000..6c6013b4 --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/icon_login_apple.imageset/logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/icon_login_kakao.imageset/Contents.json b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/icon_login_kakao.imageset/Contents.json new file mode 100644 index 00000000..ad42a58d --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/icon_login_kakao.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "logo.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/icon_login_kakao.imageset/logo.svg b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/icon_login_kakao.imageset/logo.svg new file mode 100644 index 00000000..be2acd8b --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/icon_login_kakao.imageset/logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/image_login_logo.imageset/Contents.json b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/image_login_logo.imageset/Contents.json new file mode 100644 index 00000000..ad42a58d --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/image_login_logo.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "logo.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/image_login_logo.imageset/logo.svg b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/image_login_logo.imageset/logo.svg new file mode 100644 index 00000000..2b64374f --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Assets.xcassets/image_login_logo.imageset/logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Base.lproj/LaunchScreen.storyboard b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..865e9329 --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Info.plist b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Info.plist new file mode 100644 index 00000000..0eb786dc --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeatureDemo/Resource/Info.plist @@ -0,0 +1,23 @@ + + + + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + + + + + + diff --git a/Poppool/PresentationLayer/LoginFeature/LoginFeatureInterface/Source/Factory/LoginFactory.swift b/Poppool/PresentationLayer/LoginFeature/LoginFeatureInterface/Source/Factory/LoginFactory.swift new file mode 100644 index 00000000..86367e1b --- /dev/null +++ b/Poppool/PresentationLayer/LoginFeature/LoginFeatureInterface/Source/Factory/LoginFactory.swift @@ -0,0 +1,15 @@ +import UIKit + +import DesignSystem + +public enum LoginSceneType { + case main + case sub +} + +public protocol LoginFactory { + func make( + _ type: LoginSceneType, + text: String + ) -> BaseViewController +} diff --git a/Poppool/PresentationLayer/Presentation/Presentation.xcodeproj/project.pbxproj b/Poppool/PresentationLayer/Presentation/Presentation.xcodeproj/project.pbxproj index 75b55bd5..c92cebc1 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation.xcodeproj/project.pbxproj +++ b/Poppool/PresentationLayer/Presentation/Presentation.xcodeproj/project.pbxproj @@ -11,6 +11,8 @@ 05125BA12DB6275C001342A2 /* PanModal in Frameworks */ = {isa = PBXBuildFile; productRef = 05125BA02DB6275C001342A2 /* PanModal */; }; 051631302DC3D1FD00A6C0D1 /* DesignSystem.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0516312F2DC3D1FD00A6C0D1 /* DesignSystem.framework */; }; 0522C1E12DB67C8300B141FF /* RxSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 0522C1E02DB67C8300B141FF /* RxSwift */; }; + 055C24D72E28FC6200AD389C /* PresentationInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05734C352DCDF6EC0093825D /* PresentationInterface.framework */; }; + 055C24E32E28FCA000AD389C /* DesignSystem.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0516312F2DC3D1FD00A6C0D1 /* DesignSystem.framework */; }; 05734C3C2DCDF6FE0093825D /* PresentationInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05734C352DCDF6EC0093825D /* PresentationInterface.framework */; }; 05734C412DCDF7190093825D /* SearchFeatureInterface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05734C402DCDF7190093825D /* SearchFeatureInterface.framework */; }; 05734C492DCDF7960093825D /* DesignSystem.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05734C482DCDF7960093825D /* DesignSystem.framework */; }; @@ -30,6 +32,13 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 055C24D92E28FC6200AD389C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 058CC8FB2DB537960084221A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 05734C342DCDF6EC0093825D; + remoteInfo = PresentationInterface; + }; 05734C3E2DCDF6FE0093825D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 058CC8FB2DB537960084221A /* Project object */; @@ -41,6 +50,7 @@ /* Begin PBXFileReference section */ 0516312F2DC3D1FD00A6C0D1 /* DesignSystem.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = DesignSystem.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 055C24D02E28FC3800AD389C /* PresentationTesting.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PresentationTesting.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 05734C352DCDF6EC0093825D /* PresentationInterface.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PresentationInterface.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 05734C402DCDF7190093825D /* SearchFeatureInterface.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SearchFeatureInterface.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 05734C482DCDF7960093825D /* DesignSystem.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = DesignSystem.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -50,6 +60,11 @@ /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedRootGroup section */ + 055C24D12E28FC3800AD389C /* PresentationTesting */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = PresentationTesting; + sourceTree = ""; + }; 05734C362DCDF6EC0093825D /* PresentationInterface */ = { isa = PBXFileSystemSynchronizedRootGroup; path = PresentationInterface; @@ -63,6 +78,15 @@ /* End PBXFileSystemSynchronizedRootGroup section */ /* Begin PBXFrameworksBuildPhase section */ + 055C24CD2E28FC3800AD389C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 055C24D72E28FC6200AD389C /* PresentationInterface.framework in Frameworks */, + 055C24E32E28FCA000AD389C /* DesignSystem.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 05734C322DCDF6EC0093825D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -105,6 +129,7 @@ children = ( 058CC9062DB537960084221A /* Presentation */, 05734C362DCDF6EC0093825D /* PresentationInterface */, + 055C24D12E28FC3800AD389C /* PresentationTesting */, 05C1D6292DB53A8200508FFD /* Frameworks */, 058CC9052DB537960084221A /* Products */, ); @@ -115,6 +140,7 @@ children = ( 058CC9042DB537960084221A /* Presentation.framework */, 05734C352DCDF6EC0093825D /* PresentationInterface.framework */, + 055C24D02E28FC3800AD389C /* PresentationTesting.framework */, ); name = Products; sourceTree = ""; @@ -134,6 +160,13 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ + 055C24CB2E28FC3800AD389C /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 05734C302DCDF6EC0093825D /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -151,6 +184,30 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + 055C24CF2E28FC3800AD389C /* PresentationTesting */ = { + isa = PBXNativeTarget; + buildConfigurationList = 055C24D62E28FC3800AD389C /* Build configuration list for PBXNativeTarget "PresentationTesting" */; + buildPhases = ( + 055C24CB2E28FC3800AD389C /* Headers */, + 055C24CC2E28FC3800AD389C /* Sources */, + 055C24CD2E28FC3800AD389C /* Frameworks */, + 055C24CE2E28FC3800AD389C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 055C24DA2E28FC6200AD389C /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + 055C24D12E28FC3800AD389C /* PresentationTesting */, + ); + name = PresentationTesting; + packageProductDependencies = ( + ); + productName = PresentationTesting; + productReference = 055C24D02E28FC3800AD389C /* PresentationTesting.framework */; + productType = "com.apple.product-type.framework"; + }; 05734C342DCDF6EC0093825D /* PresentationInterface */ = { isa = PBXNativeTarget; buildConfigurationList = 05734C3B2DCDF6EC0093825D /* Build configuration list for PBXNativeTarget "PresentationInterface" */; @@ -219,9 +276,12 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1630; + LastSwiftUpdateCheck = 1640; LastUpgradeCheck = 1630; TargetAttributes = { + 055C24CF2E28FC3800AD389C = { + CreatedOnToolsVersion = 16.4; + }; 05734C342DCDF6EC0093825D = { CreatedOnToolsVersion = 16.3; }; @@ -261,11 +321,19 @@ targets = ( 058CC9032DB537960084221A /* Presentation */, 05734C342DCDF6EC0093825D /* PresentationInterface */, + 055C24CF2E28FC3800AD389C /* PresentationTesting */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 055C24CE2E28FC3800AD389C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 05734C332DCDF6EC0093825D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -283,6 +351,13 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 055C24CC2E28FC3800AD389C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 05734C312DCDF6EC0093825D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -300,6 +375,11 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 055C24DA2E28FC6200AD389C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 05734C342DCDF6EC0093825D /* PresentationInterface */; + targetProxy = 055C24D92E28FC6200AD389C /* PBXContainerItemProxy */; + }; 05734C3F2DCDF6FE0093825D /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 05734C342DCDF6EC0093825D /* PresentationInterface */; @@ -308,6 +388,80 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ + 055C24D42E28FC3800AD389C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = NO; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = com.poppoolIOS.poppool.PresentationTesting; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + 055C24D52E28FC3800AD389C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = NO; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = com.poppoolIOS.poppool.PresentationTesting; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; 05734C392DCDF6EC0093825D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -584,6 +738,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 055C24D62E28FC3800AD389C /* Build configuration list for PBXNativeTarget "PresentationTesting" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 055C24D42E28FC3800AD389C /* Debug */, + 055C24D52E28FC3800AD389C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 05734C3B2DCDF6EC0093825D /* Build configuration list for PBXNativeTarget "PresentationInterface" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Detail/DetailReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Detail/DetailReactor.swift index e6626483..45d30d19 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Detail/DetailReactor.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Detail/DetailReactor.swift @@ -3,6 +3,7 @@ import UIKit import DesignSystem import DomainInterface import Infrastructure +import LoginFeatureInterface import LinkPresentation import ReactorKit @@ -167,13 +168,10 @@ final class DetailReactor: Reactor { ) controller.navigationController?.pushViewController(commentController, animated: true) } else { - let loginController = SubLoginController() - loginController.reactor = SubLoginReactor( - authAPIUseCase: DIContainer.resolve(AuthAPIUseCase.self), - kakaoLoginUseCase: DIContainer.resolve(KakaoLoginUseCase.self), - appleLoginUseCase: DIContainer.resolve(AppleLoginUseCase.self) + @Dependency var factory: LoginFactory + let nextController = UINavigationController( + rootViewController: factory.make(.sub, text: "간편하게 SNS 로그인하고\n다른 코멘트를 확인해볼까요?") ) - let nextController = UINavigationController(rootViewController: loginController) nextController.modalPresentationStyle = .fullScreen controller.present(nextController, animated: true) } @@ -207,13 +205,10 @@ final class DetailReactor: Reactor { ) controller.navigationController?.pushViewController(nextController, animated: true) } else { - let loginController = SubLoginController() - loginController.reactor = SubLoginReactor( - authAPIUseCase: DIContainer.resolve(AuthAPIUseCase.self), - kakaoLoginUseCase: DIContainer.resolve(KakaoLoginUseCase.self), - appleLoginUseCase: DIContainer.resolve(AppleLoginUseCase.self) + @Dependency var factory: LoginFactory + let nextController = UINavigationController( + rootViewController: factory.make(.sub, text: "간편하게 SNS 로그인하고\n다른 코멘트를 확인해볼까요?") ) - let nextController = UINavigationController(rootViewController: loginController) nextController.modalPresentationStyle = .fullScreen controller.present(nextController, animated: true) } @@ -246,13 +241,10 @@ final class DetailReactor: Reactor { case .moveToRecentScene(let controller): controller.navigationController?.popViewController(animated: true) case .moveToLoginScene(let controller): - let loginController = SubLoginController() - loginController.reactor = SubLoginReactor( - authAPIUseCase: DIContainer.resolve(AuthAPIUseCase.self), - kakaoLoginUseCase: DIContainer.resolve(KakaoLoginUseCase.self), - appleLoginUseCase: DIContainer.resolve(AppleLoginUseCase.self) + @Dependency var factory: LoginFactory + let nextController = UINavigationController( + rootViewController: factory.make(.sub, text: "간편하게 SNS 로그인하고\n다른 코멘트를 확인해볼까요?") ) - let nextController = UINavigationController(rootViewController: loginController) nextController.modalPresentationStyle = .fullScreen controller.present(nextController, animated: true) case .moveToImageDetailScene(let controller, let cellRow, let imageRow): diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Main/LoginController.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Main/LoginController.swift deleted file mode 100644 index b24a556f..00000000 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Main/LoginController.swift +++ /dev/null @@ -1,88 +0,0 @@ -import UIKit - -import DesignSystem -import Infrastructure - -import ReactorKit -import RxCocoa -import RxSwift -import SnapKit - -final class LoginController: BaseViewController, View { - - typealias Reactor = LoginReactor - - // MARK: - Properties - var disposeBag = DisposeBag() - - private var mainView = LoginView() -} - -// MARK: - Life Cycle -extension LoginController { - override func viewDidLoad() { - super.viewDidLoad() - setUp() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - if let lastLogin = reactor?.userDefaultService.fetch(key: "lastLogin") { - switch lastLogin { - case "kakao": - mainView.kakaoButton.showToolTip(color: .w100, direction: .pointDown, text: "최근에 이 방법으로 로그인했어요") - case "apple": - mainView.appleButton.showToolTip(color: .w100, direction: .pointUp, text: "최근에 이 방법으로 로그인했어요") - default: - break - } - } - } -} - -// MARK: - SetUp -private extension LoginController { - func setUp() { - view.addSubview(mainView) - mainView.snp.makeConstraints { make in - make.edges.equalTo(view.safeAreaLayoutGuide) - } - } -} - -// MARK: - Methods -extension LoginController { - func bind(reactor: Reactor) { - mainView.guestButton.rx.tap - .withUnretained(self) - .map { (owner, _) in - Reactor.Action.guestButtonTapped(controller: owner) - } - .bind(to: reactor.action) - .disposed(by: disposeBag) - - mainView.kakaoButton.rx.tap - .withUnretained(self) - .map { (owner, _) in - Reactor.Action.kakaoButtonTapped(controller: owner) - } - .bind(to: reactor.action) - .disposed(by: disposeBag) - - mainView.inquiryButton.rx.tap - .withUnretained(self) - .map { (owner, _) in - Reactor.Action.inquiryButtonTapped(controller: owner) - } - .bind(to: reactor.action) - .disposed(by: disposeBag) - - mainView.appleButton.rx.tap - .withUnretained(self) - .map { (owner, _) in - Reactor.Action.appleButtonTapped(controller: owner) - } - .bind(to: reactor.action) - .disposed(by: disposeBag) - } -} diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Main/LoginReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Main/LoginReactor.swift deleted file mode 100644 index 56fcff23..00000000 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Main/LoginReactor.swift +++ /dev/null @@ -1,148 +0,0 @@ -import DesignSystem -import DomainInterface -import Infrastructure - -import ReactorKit -import RxCocoa -import RxSwift - -final class LoginReactor: Reactor { - - // MARK: - Reactor - enum Action { - case kakaoButtonTapped(controller: BaseViewController) - case appleButtonTapped(controller: BaseViewController) - case guestButtonTapped(controller: BaseViewController) - case inquiryButtonTapped(controller: BaseViewController) - } - - enum Mutation { - case moveToSignUpScene(controller: BaseViewController) - case moveToHomeScene(controller: BaseViewController) - case loadView - case moveToInquiryScene(controller: BaseViewController) - } - - struct State { - } - - // MARK: - properties - - var initialState: State - var disposeBag = DisposeBag() - - private var authrizationCode: String? - - private let authAPIUseCase: AuthAPIUseCase - private let kakaoLoginUseCase: KakaoLoginUseCase - private let appleLoginUseCase: AppleLoginUseCase - - @Dependency private var keyChainService: KeyChainService - let userDefaultService = UserDefaultService() - - // MARK: - init - init( - authAPIUseCase: AuthAPIUseCase, - kakaoLoginUseCase: KakaoLoginUseCase, - appleLoginUseCase: AppleLoginUseCase - ) { - self.authAPIUseCase = authAPIUseCase - self.kakaoLoginUseCase = kakaoLoginUseCase - self.appleLoginUseCase = appleLoginUseCase - self.initialState = State() - } - - // MARK: - Reactor Methods - func mutate(action: Action) -> Observable { - switch action { - case .kakaoButtonTapped(let controller): - return loginWithKakao(controller: controller) - case .appleButtonTapped(let controller): - return loginWithApple(controller: controller) - case .guestButtonTapped(let controller): - _ = keyChainService.deleteToken(type: .accessToken) - _ = keyChainService.deleteToken(type: .refreshToken) - return Observable.just(.moveToHomeScene(controller: controller)) - case .inquiryButtonTapped(let controller): - return Observable.just(.moveToInquiryScene(controller: controller)) - } - } - - func reduce(state: State, mutation: Mutation) -> State { - switch mutation { - case .moveToSignUpScene(let controller): - let signUpController = SignUpMainController() - signUpController.reactor = SignUpMainReactor( - isFirstResponderCase: true, - authrizationCode: authrizationCode, - signUpAPIUseCase: DIContainer.resolve(SignUpAPIUseCase.self) - ) - controller.navigationController?.pushViewController(signUpController, animated: true) - case .moveToHomeScene(let controller): - let homeTabbar = WaveTabBarController() - controller.view.window?.rootViewController = homeTabbar - case .loadView: - break - case .moveToInquiryScene(let controller): - let nextController = FAQController() - nextController.reactor = FAQReactor() - controller.navigationController?.pushViewController(nextController, animated: true) - } - return state - } - - func loginWithKakao(controller: BaseViewController) -> Observable { - return kakaoLoginUseCase.fetchUserCredential() - .withUnretained(self) - .flatMap { owner, response in - return owner.authAPIUseCase.postTryLogin(userCredential: response, socialType: "kakao") - } - .withUnretained(self) - .map { [weak controller] (owner, loginResponse) in - guard let controller = controller else { return .loadView } - owner.userDefaultService.save(key: "userID", value: loginResponse.userId) - owner.userDefaultService.save(key: "socialType", value: loginResponse.socialType) - let accessTokenResult = owner.keyChainService.saveToken(type: .accessToken, value: loginResponse.accessToken) - let refreshTokenResult = owner.keyChainService.saveToken(type: .refreshToken, value: loginResponse.refreshToken) - switch accessTokenResult { - case .success: - owner.userDefaultService.save(key: "lastLogin", value: "kakao") - if loginResponse.isRegisteredUser { - return .moveToHomeScene(controller: controller) - } else { - return .moveToSignUpScene(controller: controller) - } - case .failure: - return .loadView - } - } - } - - func loginWithApple(controller: BaseViewController) -> Observable { - return appleLoginUseCase.fetchUserCredential() - .withUnretained(self) - .flatMap { owner, response in - owner.authrizationCode = response.authorizationCode - return owner.authAPIUseCase.postTryLogin(userCredential: response, socialType: "apple") - } - .withUnretained(self) - .map({ [weak controller] (owner, loginResponse) in - guard let controller = controller else { return .loadView } - owner.userDefaultService.save(key: "userID", value: loginResponse.userId) - owner.userDefaultService.save(key: "socialType", value: loginResponse.socialType) - let accessTokenResult = owner.keyChainService.saveToken(type: .accessToken, value: loginResponse.accessToken) - let refreshTokenResult = owner.keyChainService.saveToken(type: .refreshToken, value: loginResponse.refreshToken) - switch accessTokenResult { - case .success: - owner.userDefaultService.save(key: "lastLogin", value: "apple") - if loginResponse.isRegisteredUser { - return .moveToHomeScene(controller: controller) - } else { - return .moveToSignUpScene(controller: controller) - } - case .failure: - return .loadView - } - }) - } -} diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Main/LoginView.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Main/LoginView.swift deleted file mode 100644 index 62d5b8ad..00000000 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Main/LoginView.swift +++ /dev/null @@ -1,129 +0,0 @@ -import UIKit - -import DesignSystem - -import SnapKit - -final class LoginView: UIView { - - // MARK: - Components - let guestButton: UIButton = { - let button = UIButton(type: .system) - button.setTitle("둘러보기", for: .normal) - button.titleLabel?.font = .korFont(style: .regular, size: 14) - button.setTitleColor(.g1000, for: .normal) - return button - }() - - private let logoImageView: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "image_login_logo") - view.contentMode = .scaleAspectFit - return view - }() - - private let titleLabel: PPLabel = { - let label = PPLabel(style: .bold, fontSize: 16, text: "간편하게 SNS 로그인하고\n팝풀 서비스를 이용해보세요") - label.numberOfLines = 0 - label.textAlignment = .center - return label - }() - - let kakaoButton: PPButton = { - return PPButton(style: .kakao, text: "카카오톡으로 로그인") - }() - - private let kakaoImageView: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "icon_login_kakao") - return view - }() - - let appleButton: PPButton = { - return PPButton(style: .apple, text: "Apple로 로그인") - }() - - private let appleImageView: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "icon_login_apple") - return view - }() - - let inquiryButton: UIButton = { - let button = UIButton(type: .system) - button.setTitle("로그인이 어려우신가요?", for: .normal) - button.titleLabel?.font = .korFont(style: .regular, size: 12) - button.setTitleColor(.g1000, for: .normal) - return button - }() - - // MARK: - init - init() { - super.init(frame: .zero) - setUpConstraints() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} - -// MARK: - SetUp -private extension LoginView { - - func setUpConstraints() { - self.addSubview(guestButton) - guestButton.snp.makeConstraints { make in - make.top.equalToSuperview().inset(11) - make.trailing.equalToSuperview().inset(20) - } - - self.addSubview(logoImageView) - logoImageView.snp.makeConstraints { make in - make.height.equalTo(90) - make.width.equalTo(70) - make.top.equalTo(guestButton.snp.bottom).offset(75) - make.centerX.equalToSuperview() - } - - self.addSubview(titleLabel) - titleLabel.snp.makeConstraints { make in - make.centerX.equalToSuperview() - make.top.equalTo(logoImageView.snp.bottom).offset(28) - } - - self.addSubview(kakaoButton) - kakaoButton.snp.makeConstraints { make in - make.top.equalTo(titleLabel.snp.bottom).offset(156) - make.leading.trailing.equalToSuperview().inset(20) - make.height.equalTo(50) - } - - kakaoButton.addSubview(kakaoImageView) - kakaoImageView.snp.makeConstraints { make in - make.centerY.equalToSuperview() - make.leading.equalToSuperview().inset(20) - make.size.equalTo(22) - } - - self.addSubview(appleButton) - appleButton.snp.makeConstraints { make in - make.top.equalTo(kakaoButton.snp.bottom).offset(16) - make.leading.trailing.equalToSuperview().inset(20) - make.height.equalTo(50) - } - - appleButton.addSubview(appleImageView) - appleImageView.snp.makeConstraints { make in - make.centerY.equalToSuperview() - make.leading.equalToSuperview().inset(20) - make.size.equalTo(22) - } - - self.addSubview(inquiryButton) - inquiryButton.snp.makeConstraints { make in - make.bottom.equalToSuperview().inset(56) - make.centerX.equalToSuperview() - } - } -} diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Sub/SubLoginController.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Sub/SubLoginController.swift deleted file mode 100644 index f1d42ee9..00000000 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Sub/SubLoginController.swift +++ /dev/null @@ -1,88 +0,0 @@ -import UIKit - -import DesignSystem - -import ReactorKit -import RxCocoa -import RxSwift -import SnapKit - -final class SubLoginController: BaseViewController, View { - - typealias Reactor = SubLoginReactor - - // MARK: - Properties - var disposeBag = DisposeBag() - - private var mainView = SubLoginView() -} - -// MARK: - Life Cycle -extension SubLoginController { - override func viewDidLoad() { - super.viewDidLoad() - setUp() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - if let lastLogin = reactor?.userDefaultService.fetch(key: "lastLogin") { - switch lastLogin { - case "kakao": - mainView.kakaoButton.showToolTip(color: .w100, direction: .pointDown, text: "최근에 이 방법으로 로그인했어요") - case "apple": - mainView.appleButton.showToolTip(color: .w100, direction: .pointUp, text: "최근에 이 방법으로 로그인했어요") - default: - break - } - } - } -} - -// MARK: - SetUp -private extension SubLoginController { - func setUp() { - view.backgroundColor = .g50 - view.addSubview(mainView) - mainView.snp.makeConstraints { make in - make.edges.equalTo(view.safeAreaLayoutGuide) - } - } -} - -// MARK: - Methods -extension SubLoginController { - func bind(reactor: Reactor) { - mainView.xmarkButton.rx.tap - .withUnretained(self) - .map { (owner, _) in - Reactor.Action.xmarkButtonTapped(controller: owner) - } - .bind(to: reactor.action) - .disposed(by: disposeBag) - - mainView.kakaoButton.rx.tap - .withUnretained(self) - .map { (owner, _) in - Reactor.Action.kakaoButtonTapped(controller: owner) - } - .bind(to: reactor.action) - .disposed(by: disposeBag) - - mainView.inquiryButton.rx.tap - .withUnretained(self) - .map { (owner, _) in - Reactor.Action.inquiryButtonTapped(controller: owner) - } - .bind(to: reactor.action) - .disposed(by: disposeBag) - - mainView.appleButton.rx.tap - .withUnretained(self) - .map { (owner, _) in - Reactor.Action.appleButtonTapped(controller: owner) - } - .bind(to: reactor.action) - .disposed(by: disposeBag) - } -} diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Sub/SubLoginReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Sub/SubLoginReactor.swift deleted file mode 100644 index ce0c960b..00000000 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Sub/SubLoginReactor.swift +++ /dev/null @@ -1,144 +0,0 @@ -import DesignSystem -import DomainInterface -import Infrastructure - -import ReactorKit -import RxCocoa -import RxSwift - -final class SubLoginReactor: Reactor { - - // MARK: - Reactor - enum Action { - case kakaoButtonTapped(controller: BaseViewController) - case appleButtonTapped(controller: BaseViewController) - case xmarkButtonTapped(controller: BaseViewController) - case inquiryButtonTapped(controller: BaseViewController) - } - - enum Mutation { - case moveToSignUpScene(controller: BaseViewController) - case dismissScene(controller: BaseViewController) - case loadView - case moveToInquiryScene(controller: BaseViewController) - } - - struct State { - } - - // MARK: - properties - - var initialState: State - var disposeBag = DisposeBag() - - private var authrizationCode: String? - - private let authAPIUseCase: AuthAPIUseCase - private let kakaoLoginUseCase: KakaoLoginUseCase - private let appleLoginUseCase: AppleLoginUseCase - @Dependency private var keyChainService: KeyChainService - let userDefaultService = UserDefaultService() - - // MARK: - init - init( - authAPIUseCase: AuthAPIUseCase, - kakaoLoginUseCase: KakaoLoginUseCase, - appleLoginUseCase: AppleLoginUseCase - ) { - self.authAPIUseCase = authAPIUseCase - self.kakaoLoginUseCase = kakaoLoginUseCase - self.appleLoginUseCase = appleLoginUseCase - self.initialState = State() - } - - // MARK: - Reactor Methods - func mutate(action: Action) -> Observable { - switch action { - case .kakaoButtonTapped(let controller): - return loginWithKakao(controller: controller) - case .appleButtonTapped(let controller): - return loginWithApple(controller: controller) - case .xmarkButtonTapped(let controller): - return Observable.just(.dismissScene(controller: controller)) - case .inquiryButtonTapped(let controller): - return Observable.just(.moveToInquiryScene(controller: controller)) - } - } - - func reduce(state: State, mutation: Mutation) -> State { - switch mutation { - case .moveToSignUpScene(let controller): - let signUpController = SignUpMainController() - signUpController.reactor = SignUpMainReactor( - isFirstResponderCase: false, - authrizationCode: authrizationCode, - signUpAPIUseCase: DIContainer.resolve(SignUpAPIUseCase.self) - ) - controller.navigationController?.pushViewController(signUpController, animated: true) - case .dismissScene(let controller): - controller.dismiss(animated: true) - case .loadView: - break - case .moveToInquiryScene(let controller): - let nextController = FAQController() - nextController.reactor = FAQReactor() - controller.navigationController?.pushViewController(nextController, animated: true) - } - return state - } - - func loginWithKakao(controller: BaseViewController) -> Observable { - return kakaoLoginUseCase.fetchUserCredential() - .withUnretained(self) - .flatMap { owner, response in - owner.authAPIUseCase.postTryLogin(userCredential: response, socialType: "kakao") - } - .withUnretained(self) - .map { [weak controller] (owner, loginResponse) in - guard let controller = controller else { return .loadView } - owner.userDefaultService.save(key: "userID", value: loginResponse.userId) - owner.userDefaultService.save(key: "socialType", value: loginResponse.socialType) - let accessTokenResult = owner.keyChainService.saveToken(type: .accessToken, value: loginResponse.accessToken) - let refreshTokenResult = owner.keyChainService.saveToken(type: .refreshToken, value: loginResponse.refreshToken) - switch accessTokenResult { - case .success: - owner.userDefaultService.save(key: "lastLogin", value: "kakao") - if loginResponse.isRegisteredUser { - return .dismissScene(controller: controller) - } else { - return .moveToSignUpScene(controller: controller) - } - case .failure: - return .loadView - } - } - } - - func loginWithApple(controller: BaseViewController) -> Observable { - return appleLoginUseCase.fetchUserCredential() - .withUnretained(self) - .flatMap { owner, response in - owner.authrizationCode = response.authorizationCode - return owner.authAPIUseCase.postTryLogin(userCredential: response, socialType: "apple") - } - .withUnretained(self) - .map { [weak controller] (owner, loginResponse) in - guard let controller = controller else { return .loadView } - owner.userDefaultService.save(key: "userID", value: loginResponse.userId) - owner.userDefaultService.save(key: "socialType", value: loginResponse.socialType) - let accessTokenResult = owner.keyChainService.saveToken(type: .accessToken, value: loginResponse.accessToken) - let refreshTokenResult = owner.keyChainService.saveToken(type: .refreshToken, value: loginResponse.refreshToken) - switch accessTokenResult { - case .success: - owner.userDefaultService.save(key: "lastLogin", value: "apple") - if loginResponse.isRegisteredUser { - return .dismissScene(controller: controller) - } else { - return .moveToSignUpScene(controller: controller) - } - case .failure: - return .loadView - } - } - } -} diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Sub/SubLoginView.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Sub/SubLoginView.swift deleted file mode 100644 index cea96869..00000000 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Login/Sub/SubLoginView.swift +++ /dev/null @@ -1,130 +0,0 @@ -import UIKit - -import DesignSystem - -import SnapKit - -final class SubLoginView: UIView { - - // MARK: - Components - let xmarkButton: UIButton = { - let button = UIButton(type: .system) - button.setImage(UIImage(named: "icon_xmark"), for: .normal) - button.tintColor = .g1000 - return button - }() - - private let logoImageView: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "image_login_logo") - view.contentMode = .scaleAspectFit - return view - }() - - private let titleLabel: PPLabel = { - let label = PPLabel(style: .bold, fontSize: 16, text: "간편하게 SNS 로그인하고\n공감가는 코멘트에 반응해볼까요?\n다른 코멘트를 확인해볼까요?") - label.setLineHeightText(text: "간편하게 SNS 로그인하고\n공감가는 코멘트에 반응해볼까요?\n다른 코멘트를 확인해볼까요?", font: .korFont(style: .bold, size: 16), lineHeight: 1.3) - label.numberOfLines = 0 - label.textAlignment = .center - return label - }() - - let kakaoButton: PPButton = { - return PPButton(style: .kakao, text: "카카오톡으로 로그인") - }() - - private let kakaoImageView: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "icon_login_kakao") - return view - }() - - let appleButton: PPButton = { - return PPButton(style: .apple, text: "Apple로 로그인") - }() - - private let appleImageView: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "icon_login_apple") - return view - }() - - let inquiryButton: UIButton = { - let button = UIButton(type: .system) - button.setTitle("로그인이 어려우신가요?", for: .normal) - button.titleLabel?.font = .korFont(style: .regular, size: 12) - button.setTitleColor(.g1000, for: .normal) - return button - }() - - // MARK: - init - init() { - super.init(frame: .zero) - setUpConstraints() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} - -// MARK: - SetUp -private extension SubLoginView { - - func setUpConstraints() { - self.addSubview(xmarkButton) - xmarkButton.snp.makeConstraints { make in - make.top.equalToSuperview().inset(11) - make.trailing.equalToSuperview().inset(20) - make.size.equalTo(32) - } - - self.addSubview(logoImageView) - logoImageView.snp.makeConstraints { make in - make.height.equalTo(90) - make.width.equalTo(70) - make.top.equalTo(xmarkButton.snp.bottom).offset(75) - make.centerX.equalToSuperview() - } - - self.addSubview(titleLabel) - titleLabel.snp.makeConstraints { make in - make.centerX.equalToSuperview() - make.top.equalTo(logoImageView.snp.bottom).offset(28) - } - - self.addSubview(kakaoButton) - kakaoButton.snp.makeConstraints { make in - make.top.equalTo(titleLabel.snp.bottom).offset(156) - make.leading.trailing.equalToSuperview().inset(20) - make.height.equalTo(50) - } - - kakaoButton.addSubview(kakaoImageView) - kakaoImageView.snp.makeConstraints { make in - make.centerY.equalToSuperview() - make.leading.equalToSuperview().inset(20) - make.size.equalTo(22) - } - - self.addSubview(appleButton) - appleButton.snp.makeConstraints { make in - make.top.equalTo(kakaoButton.snp.bottom).offset(16) - make.leading.trailing.equalToSuperview().inset(20) - make.height.equalTo(50) - } - - appleButton.addSubview(appleImageView) - appleImageView.snp.makeConstraints { make in - make.centerY.equalToSuperview() - make.leading.equalToSuperview().inset(20) - make.size.equalTo(22) - } - - self.addSubview(inquiryButton) - inquiryButton.snp.makeConstraints { make in - make.bottom.equalToSuperview().inset(56) - make.centerX.equalToSuperview() - } - } -} diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/MyPage/FAQ/FactoryImpl/FAQFactoryImpl.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/MyPage/FAQ/FactoryImpl/FAQFactoryImpl.swift new file mode 100644 index 00000000..2ed5471c --- /dev/null +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/MyPage/FAQ/FactoryImpl/FAQFactoryImpl.swift @@ -0,0 +1,13 @@ +import DesignSystem +import PresentationInterface + +public final class FAQFactoryImpl: FAQFactory { + public init() { } + + public func make() -> BaseViewController { + let viewController = FAQController() + viewController.reactor = FAQReactor() + + return viewController + } +} diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/MyPage/Main/MyPageReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/MyPage/Main/MyPageReactor.swift index 70fa8dbb..e731d238 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/MyPage/Main/MyPageReactor.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/MyPage/Main/MyPageReactor.swift @@ -3,6 +3,7 @@ import UIKit import DesignSystem import DomainInterface import Infrastructure +import LoginFeatureInterface import ReactorKit import RxCocoa @@ -45,6 +46,8 @@ final class MyPageReactor: Reactor { private let userAPIUseCase: UserAPIUseCase + @Dependency private var userDefaultService: UserDefaultService + lazy var compositionalLayout: UICollectionViewCompositionalLayout = { UICollectionViewCompositionalLayout { [weak self] section, env in guard let self = self else { @@ -161,7 +164,13 @@ final class MyPageReactor: Reactor { case .logoutButtonTapped: // 로그아웃 API return userAPIUseCase.postLogout() + .do(onCompleted: { [weak self] in + UserDefaultService.Key.allCases + .filter { $0 != .lastLogin } + .forEach { self?.userDefaultService.delete(keyType: $0) } + }) .andThen(Observable.just(.logout)) + .catch { _ in Observable.empty() } case .adminMenuTapped(let controller): // 별도의 액션으로도 관리자 메뉴로 이동 가능 @@ -188,8 +197,9 @@ final class MyPageReactor: Reactor { case .logout: @Dependency var keyChainService: KeyChainService - _ = keyChainService.deleteToken(type: .accessToken) - _ = keyChainService.deleteToken(type: .refreshToken) + keyChainService.deleteToken(type: .accessToken) + keyChainService.deleteToken(type: .refreshToken) + ToastMaker.createToast(message: "로그아웃 되었어요") DispatchQueue.main.async { [weak self] in self?.action.onNext(.viewWillAppear) @@ -267,13 +277,10 @@ final class MyPageReactor: Reactor { controller.navigationController?.pushViewController(nextController, animated: true) case .moveToLoginScene(let controller): - let nextController = SubLoginController() - nextController.reactor = SubLoginReactor( - authAPIUseCase: DIContainer.resolve(AuthAPIUseCase.self), - kakaoLoginUseCase: DIContainer.resolve(KakaoLoginUseCase.self), - appleLoginUseCase: DIContainer.resolve(AppleLoginUseCase.self) + @Dependency var factory: LoginFactory + let navigationController = UINavigationController( + rootViewController: factory.make(.sub, text: "간편하게 SNS 로그인하고\n팝풀 서비스를 이용해보세요") ) - let navigationController = UINavigationController(rootViewController: nextController) navigationController.modalPresentationStyle = .fullScreen controller.present(navigationController, animated: true) case .moveToMyCommentScene(let controller): diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/MyPage/Withdrawl/SelectedReason/WithdrawlReasonReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/MyPage/Withdrawl/SelectedReason/WithdrawlReasonReactor.swift index a27dc32c..27e690b9 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/MyPage/Withdrawl/SelectedReason/WithdrawlReasonReactor.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/MyPage/Withdrawl/SelectedReason/WithdrawlReasonReactor.swift @@ -109,8 +109,8 @@ final class WithdrawlReasonReactor: Reactor { case .moveToCompleteScene(let controller): keyChainService.deleteToken(type: .accessToken) keyChainService.deleteToken(type: .refreshToken) - userDefaultService.delete(key: "lastLogin") - userDefaultService.delete(key: "searchList") + UserDefaultService.Key.allCases.forEach { userDefaultService.delete(keyType: $0) } + let nextController = WithdrawlCompleteController() nextController.mainView.checkButton.rx.tap .withUnretained(nextController) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/SignUp/FactoryImpl/SignUpFactoryImpl.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/SignUp/FactoryImpl/SignUpFactoryImpl.swift new file mode 100644 index 00000000..c52ffa26 --- /dev/null +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/SignUp/FactoryImpl/SignUpFactoryImpl.swift @@ -0,0 +1,23 @@ +import UIKit + +import DesignSystem +import DomainInterface +import Infrastructure +import PresentationInterface + +public final class SignUpFactoryImpl: SignUpFactory { + + public init() { } + + public func make(isFirstResponder: Bool, authorizationCode: String?) -> DesignSystem.BaseTabmanController { + let viewController = SignUpMainController() + + viewController.reactor = SignUpMainReactor( + isFirstResponderCase: isFirstResponder, + authorizationCode: authorizationCode, + signUpAPIUseCase: DIContainer.resolve(SignUpAPIUseCase.self) + ) + + return viewController + } +} diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/SignUp/Main/SignUpMainReactor.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/SignUp/Main/SignUpMainReactor.swift index 3c5bafe2..f6dd0093 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/SignUp/Main/SignUpMainReactor.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/SignUp/Main/SignUpMainReactor.swift @@ -55,7 +55,7 @@ final class SignUpMainReactor: Reactor { var initialState: State var disposeBag = DisposeBag() - private var authrizationCode: String? + private var authorizationCode: String? private let signUpAPIUseCase: SignUpAPIUseCase private let userDefaultService = UserDefaultService() @@ -64,11 +64,11 @@ final class SignUpMainReactor: Reactor { // MARK: - init init( isFirstResponderCase: Bool, - authrizationCode: String?, + authorizationCode: String?, signUpAPIUseCase: SignUpAPIUseCase ) { self.initialState = State() - self.authrizationCode = authrizationCode + self.authorizationCode = authorizationCode self.isFirstResponderCase = isFirstResponderCase self.signUpAPIUseCase = signUpAPIUseCase } @@ -131,10 +131,15 @@ final class SignUpMainReactor: Reactor { socialEmail: "", socialType: socialType, interests: newState.categorys, - appleAuthorizationCode: authrizationCode + appleAuthorizationCode: authorizationCode ) .subscribe { [weak self, weak controller] in guard let self = self else { return } + self.userDefaultService.save( + keyType: .lastLogin, + value: authorizationCode != nil ? "apple" : "kakao" + ) + let completeController = SignUpCompleteController() completeController.reactor = SignUpCompleteReactor( nickName: nickName, diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Splash/SplashController.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Splash/SplashController.swift index 006b1446..ca7a4e9f 100644 --- a/Poppool/PresentationLayer/Presentation/Presentation/Scene/Splash/SplashController.swift +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/Splash/SplashController.swift @@ -3,6 +3,8 @@ import UIKit import DesignSystem import DomainInterface import Infrastructure +import LoginFeatureInterface +import PresentationInterface import ReactorKit import RxCocoa @@ -53,22 +55,21 @@ private extension SplashController { func setRootview() { authAPIUseCase.postTokenReissue() .withUnretained(self) - .subscribe(onNext: { (owner, response) in - let newAccessToken = response.accessToken ?? "" - let newRefreshToken = response.refreshToken ?? "" - _ = owner.keyChainService.saveToken(type: .accessToken, value: newAccessToken) - _ = owner.keyChainService.saveToken(type: .refreshToken, value: newRefreshToken) - let navigationController = WaveTabBarController() - owner.rootViewController = navigationController - }, onError: { [weak self] _ in - guard let self = self else { return } - let loginViewController = LoginController() - loginViewController.reactor = LoginReactor( - authAPIUseCase: authAPIUseCase, - kakaoLoginUseCase: DIContainer.resolve(KakaoLoginUseCase.self), - appleLoginUseCase: DIContainer.resolve(AppleLoginUseCase.self) - ) - let loginNavigationController = UINavigationController(rootViewController: loginViewController) + .subscribe( + onNext: { (owner, response) in + let newAccessToken = response.accessToken ?? "" + let newRefreshToken = response.refreshToken ?? "" + owner.keyChainService.saveToken(type: .accessToken, value: newAccessToken) + owner.keyChainService.saveToken(type: .refreshToken, value: newRefreshToken) + @Dependency var factory: WaveTabbarFactory + owner.rootViewController = factory.make() + }, + onError: { [weak self] _ in + guard let self = self else { return } + @Dependency var factory: LoginFactory + let loginNavigationController = UINavigationController( + rootViewController: factory.make(.main, text: "간편하게 SNS 로그인하고\n팝풀 서비스를 이용해보세요") + ) rootViewController = loginNavigationController }) .disposed(by: disposeBag) diff --git a/Poppool/PresentationLayer/Presentation/Presentation/Scene/TabbarController/FactoryImpl/WaveTabbarFactoryImpl.swift b/Poppool/PresentationLayer/Presentation/Presentation/Scene/TabbarController/FactoryImpl/WaveTabbarFactoryImpl.swift new file mode 100644 index 00000000..36cc5a42 --- /dev/null +++ b/Poppool/PresentationLayer/Presentation/Presentation/Scene/TabbarController/FactoryImpl/WaveTabbarFactoryImpl.swift @@ -0,0 +1,11 @@ +import UIKit + +import PresentationInterface + +public final class WaveTabbarFactoryImpl: WaveTabbarFactory { + public init() { } + + public func make() -> UITabBarController { + return WaveTabBarController() + } +} diff --git a/Poppool/PresentationLayer/Presentation/PresentationInterface/Factory/FAQFactory.swift b/Poppool/PresentationLayer/Presentation/PresentationInterface/Factory/FAQFactory.swift new file mode 100644 index 00000000..81d685f4 --- /dev/null +++ b/Poppool/PresentationLayer/Presentation/PresentationInterface/Factory/FAQFactory.swift @@ -0,0 +1,5 @@ +import DesignSystem + +public protocol FAQFactory { + func make() -> BaseViewController +} diff --git a/Poppool/PresentationLayer/Presentation/PresentationInterface/Factory/SignUpFactory.swift b/Poppool/PresentationLayer/Presentation/PresentationInterface/Factory/SignUpFactory.swift new file mode 100644 index 00000000..58bec50d --- /dev/null +++ b/Poppool/PresentationLayer/Presentation/PresentationInterface/Factory/SignUpFactory.swift @@ -0,0 +1,5 @@ +import DesignSystem + +public protocol SignUpFactory { + func make(isFirstResponder: Bool, authorizationCode: String?) -> BaseTabmanController +} diff --git a/Poppool/PresentationLayer/Presentation/PresentationInterface/Factory/WaveTabbarFactory.swift b/Poppool/PresentationLayer/Presentation/PresentationInterface/Factory/WaveTabbarFactory.swift new file mode 100644 index 00000000..42d75bd8 --- /dev/null +++ b/Poppool/PresentationLayer/Presentation/PresentationInterface/Factory/WaveTabbarFactory.swift @@ -0,0 +1,5 @@ +import UIKit + +public protocol WaveTabbarFactory { + func make() -> UITabBarController +} diff --git a/Poppool/PresentationLayer/Presentation/PresentationTesting/Factory/FAQFactoryMock.swift b/Poppool/PresentationLayer/Presentation/PresentationTesting/Factory/FAQFactoryMock.swift new file mode 100644 index 00000000..a2fcd7e9 --- /dev/null +++ b/Poppool/PresentationLayer/Presentation/PresentationTesting/Factory/FAQFactoryMock.swift @@ -0,0 +1,11 @@ +import DesignSystem +import PresentationInterface + +public final class FAQFactoryMock: FAQFactory { + + public init() { } + + public func make() -> BaseViewController { + return BaseViewController() + } +} diff --git a/Poppool/PresentationLayer/Presentation/PresentationTesting/Factory/SignUpFactoryMock.swift b/Poppool/PresentationLayer/Presentation/PresentationTesting/Factory/SignUpFactoryMock.swift new file mode 100644 index 00000000..81ce3c56 --- /dev/null +++ b/Poppool/PresentationLayer/Presentation/PresentationTesting/Factory/SignUpFactoryMock.swift @@ -0,0 +1,11 @@ +import DesignSystem +import PresentationInterface + +public final class SignUpFactoryMock: SignUpFactory { + + public init() { } + + public func make(isFirstResponder: Bool = false, authorizationCode: String? = nil) -> BaseTabmanController { + return BaseTabmanController() + } +} diff --git a/Poppool/PresentationLayer/Presentation/PresentationTesting/Factory/WaveTabbarFactoryMock.swift b/Poppool/PresentationLayer/Presentation/PresentationTesting/Factory/WaveTabbarFactoryMock.swift new file mode 100644 index 00000000..2cfda98a --- /dev/null +++ b/Poppool/PresentationLayer/Presentation/PresentationTesting/Factory/WaveTabbarFactoryMock.swift @@ -0,0 +1,12 @@ +import UIKit + +import DesignSystem +import PresentationInterface + +public final class WaveTabbarFactoryMock: WaveTabbarFactory { + public init() {} + + public func make() -> UITabBarController { + return UITabBarController() + } +} diff --git a/Poppool/PresentationLayer/SearchFeature/SearchFeature.xcodeproj/project.pbxproj b/Poppool/PresentationLayer/SearchFeature/SearchFeature.xcodeproj/project.pbxproj index 3575ab6f..b2cc794d 100644 --- a/Poppool/PresentationLayer/SearchFeature/SearchFeature.xcodeproj/project.pbxproj +++ b/Poppool/PresentationLayer/SearchFeature/SearchFeature.xcodeproj/project.pbxproj @@ -714,7 +714,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_SKIP_APP_STORE_DEPLOYMENT = NO; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = ""; @@ -735,7 +735,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.poppoolIOS.poppool.SearchFeatureDemo; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match Development com.poppoolIOS.*"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.poppoolIOS.*"; SKIP_INSTALL = NO; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; diff --git a/Poppool/fastlane/Matchfile b/Poppool/fastlane/Matchfile index 0811e00d..dff1856f 100644 --- a/Poppool/fastlane/Matchfile +++ b/Poppool/fastlane/Matchfile @@ -4,5 +4,5 @@ storage_mode("git") type("development") # The default type, can be: appstore, adhoc, enterprise or development -app_identifier(["com.poppoolIOS.poppool", "com.poppoolIOS.*", "com.poppoolIOS.poppool.LoginFeatureDemo"]) +app_identifier(["com.poppoolIOS.poppool", "com.poppoolIOS.*"]) username("thddudgns972@gmail.com") \ No newline at end of file