diff --git a/Projects/App/Sources/AppDelegate.swift b/Projects/App/Sources/AppDelegate.swift index 1a599a09..1b193461 100644 --- a/Projects/App/Sources/AppDelegate.swift +++ b/Projects/App/Sources/AppDelegate.swift @@ -44,7 +44,7 @@ extension AppDelegate: UNUserNotificationCenterDelegate { Log.debug("fcm token: \(fcmToken ?? "NO TOKEN")") if let fcmToken { // TODO: user defaults 설정 방법 변경 - UserDefaults.standard.set(fcmToken, forKey: "fcmToken") + store.send(.appDelegate(.didReceivedFcmToken(fcmToken: fcmToken))) } } diff --git a/Projects/Domain/Auth/Sources/AuthClient.swift b/Projects/Domain/Auth/Sources/AuthClient.swift index 581a331e..d0c0b081 100644 --- a/Projects/Domain/Auth/Sources/AuthClient.swift +++ b/Projects/Domain/Auth/Sources/AuthClient.swift @@ -8,6 +8,8 @@ import Foundation import DomainAuthInterface +import DomainUser + import CoreNetwork import CoreLoggerInterface @@ -19,12 +21,13 @@ extension AuthClient: DependencyKey { private static func live() -> AuthClient { @Dependency(\.network) var networkManager @Dependency(\.loginManager) var loginManager - + @Dependency(\.userClient) var userClient return .init( signInWithKakao: { let signInResult = try await loginManager.signIn(loginType: .kakao) let accessToken = signInResult.accessToken - guard let fcmToken = UserDefaults.standard.string(forKey: "fcmToken") + let fcmToken = userClient.fetchFcmToken() + guard let fcmToken = fcmToken else { Log.fault("no fcm token") fatalError() @@ -40,8 +43,8 @@ extension AuthClient: DependencyKey { let signInResult = try await loginManager.signIn(loginType: .apple) let accessToken = signInResult.accessToken let userName = signInResult.userName - - guard let fcmToken = UserDefaults.standard.string(forKey: "fcmToken") + let fcmToken = userClient.fetchFcmToken() + guard let fcmToken = fcmToken else { Log.fault("no fcm token") fatalError() @@ -62,7 +65,8 @@ extension AuthClient: DependencyKey { try await networkManager.reqeust(api: .apiType(AuthAPI.withdraw)) }, logout: { - guard let fcmToken = UserDefaults.standard.string(forKey: "fcmToken") + let fcmToken = userClient.fetchFcmToken() + guard let fcmToken = fcmToken else { Log.fault("no fcm token") return diff --git a/Projects/Domain/User/Interface/Sources/UserClient.swift b/Projects/Domain/User/Interface/Sources/UserClient.swift index c140a255..dadc0abd 100644 --- a/Projects/Domain/User/Interface/Sources/UserClient.swift +++ b/Projects/Domain/User/Interface/Sources/UserClient.swift @@ -10,19 +10,25 @@ import Foundation public struct UserClient { private let _isLoggedIn: () -> Bool private let _isAppDeleted: () -> Bool + private let _fetchFcmToken: () -> String? private let updateLoginState: (Bool) -> Void private let updateDeleteState: (Bool) -> Void + private let updateFcmToken: (String) -> Void public init( isLoggedIn: @escaping () -> Bool, isAppDeleted: @escaping () -> Bool, + fetchFcmToken: @escaping () -> String?, updateLoginState: @escaping (Bool) -> Void, - updateDeleteState: @escaping (Bool) -> Void + updateDeleteState: @escaping (Bool) -> Void, + updateFcmToken: @escaping (String) -> Void ) { self._isLoggedIn = isLoggedIn self._isAppDeleted = isAppDeleted + self._fetchFcmToken = fetchFcmToken self.updateLoginState = updateLoginState self.updateDeleteState = updateDeleteState + self.updateFcmToken = updateFcmToken } public func isLoggedIn() -> Bool { @@ -33,6 +39,10 @@ public struct UserClient { _isAppDeleted() } + public func fetchFcmToken() -> String? { + _fetchFcmToken() + } + public func updateLoginState(isLoggedIn: Bool) { updateLoginState(isLoggedIn) } @@ -40,4 +50,8 @@ public struct UserClient { public func updateDeleteState(isDelete: Bool) { updateDeleteState(isDelete) } + + public func updateFcmToken(fcmToken: String) { + updateFcmToken(fcmToken) + } } diff --git a/Projects/Domain/User/Sources/UserClient.swift b/Projects/Domain/User/Sources/UserClient.swift index 96f0107f..6df5fad8 100644 --- a/Projects/Domain/User/Sources/UserClient.swift +++ b/Projects/Domain/User/Sources/UserClient.swift @@ -26,12 +26,20 @@ extension UserClient: DependencyKey { return !UserDefaults.standard.bool(forKey: "deleteState") }, + fetchFcmToken: { + return UserDefaults.standard.string(forKey: "fcmToken") + }, + updateLoginState: { isLoggedIn in UserDefaults.standard.set(isLoggedIn, forKey: "loginState") }, updateDeleteState: { isDelete in UserDefaults.standard.set(!isDelete, forKey: "deleteState") + }, + + updateFcmToken: { fcmToken in + UserDefaults.standard.set(fcmToken, forKey: "fcmToken") } ) } diff --git a/Projects/Feature/Login/Interface/Sources/Login/LoginFeature.swift b/Projects/Feature/Login/Interface/Sources/Login/LoginFeature.swift index 5d0b7fbe..2bd4b617 100644 --- a/Projects/Feature/Login/Interface/Sources/Login/LoginFeature.swift +++ b/Projects/Feature/Login/Interface/Sources/Login/LoginFeature.swift @@ -150,8 +150,8 @@ extension LoginFeature { case let .path(.element(id: _, action: .startGuide(.delegate(delegate)))): switch delegate { case .doneButtonDidTapped: - return goToOboarding(state: &state) - + return goToOboarding(state: &state) + } // appleLogin Delegate case let .path(.element(id: _, action: .appleLogin(.delegate(delegate)))): diff --git a/Projects/Feature/Login/Interface/Sources/Login/LoginView.swift b/Projects/Feature/Login/Interface/Sources/Login/LoginView.swift index 612efd83..3b585f70 100644 --- a/Projects/Feature/Login/Interface/Sources/Login/LoginView.swift +++ b/Projects/Feature/Login/Interface/Sources/Login/LoginView.swift @@ -28,41 +28,40 @@ public struct LoginView: View { public var body: some View { WithPerceptionTracking { NavigationStack(path: $store.scope(state: \.path, action: \.path)) { - VStack(spacing: 0) { - Spacer() - .frame(height: 52) - whiteLogo - .padding(.top, 52) - .padding(.bottom, .xl) - - mainText - - Spacer() - - VStack(spacing: 30.0) { - signInWithKakaoButton - snsLoginButton - } - .padding(.bottom, 30.0) + VStack(spacing: 0) { + Spacer() + .frame(height: 52) + whiteLogo + .padding(.top, 52) + .padding(.bottom, .xl) + + mainText + + Spacer() + + VStack(spacing: 30.0) { + signInWithKakaoButton + snsLoginButton } - .background { - BottleImageView( - type: .local(bottleImageSystem: .illustraition(.loginBackground)) - ) - } - .edgesIgnoringSafeArea([.top, .bottom]) - .sheet( - isPresented: $store.isPresentTermView, - content: { - TermsWebView(url: store.termURL) - } + .padding(.bottom, 30.0) + } + .background { + BottleImageView( + type: .local(bottleImageSystem: .illustraition(.loginBackground)) ) - .overlay { - if store.isLoading { - LoadingIndicator() - } + } + .edgesIgnoringSafeArea([.top, .bottom]) + .sheet( + isPresented: $store.isPresentTermView, + content: { + TermsWebView(url: store.termURL) } - + ) + .overlay { + if store.isLoading { + LoadingIndicator() + } + } } destination: { store in WithPerceptionTracking { switch store.state { @@ -70,12 +69,12 @@ public struct LoginView: View { if let store = store.scope(state: \.generalLogin, action: \.generalLogin) { GeneralLogInView(store: store) } - + case .onBoarding: if let store = store.scope(state: \.onBoarding, action: \.onBoarding) { OnboardingView(store: store) } - + case .generalSignUp: if let store = store.scope(state: \.generalSignUp, action: \.generalSignUp) { GeneralSignUpView(store: store) @@ -99,11 +98,12 @@ public struct LoginView: View { case .startGuide: if let store = store.scope(state: \.startGuide, action: \.startGuide) { StartGuideView(store: store) - } - + } + case .appleLogin: if let store = store.scope(state: \.appleLogin, action: \.appleLogin) { AppleLoginView(store: store) + } } } } diff --git a/Projects/Feature/Sources/App/AppDelegateFeature.swift b/Projects/Feature/Sources/App/AppDelegateFeature.swift index d2ec159c..4233bede 100644 --- a/Projects/Feature/Sources/App/AppDelegateFeature.swift +++ b/Projects/Feature/Sources/App/AppDelegateFeature.swift @@ -19,6 +19,14 @@ public struct AppDelegateFeature { public enum Action { case didFinishLunching + case didReceivedFcmToken(fcmToken: String) + + // Delegate + case delegate(Delegate) + + public enum Delegate { + case fcmTokenDidRecevied(fcmToken: String) + } } public var body: some ReducerOf { @@ -37,6 +45,14 @@ public struct AppDelegateFeature { KakaoSDK.initSDK(appKey: kakaoAppKey) return .none + + case let .didReceivedFcmToken(fcmToken): + return .run { send in + await send(.delegate(.fcmTokenDidRecevied(fcmToken: fcmToken))) + } + + default: + return .none } } } diff --git a/Projects/Feature/Sources/App/AppFeature.swift b/Projects/Feature/Sources/App/AppFeature.swift index a20dcc19..a5454124 100644 --- a/Projects/Feature/Sources/App/AppFeature.swift +++ b/Projects/Feature/Sources/App/AppFeature.swift @@ -52,6 +52,7 @@ public struct AppFeature { case login(LoginFeature.Action) case onboarding(OnboardingFeature.Action) + case checkUserLoginState case sceneDidActive case appleUserIdDidRevoked case loginCheckCompleted(isLoggedIn: Bool) @@ -85,7 +86,7 @@ public struct AppFeature { action: Action ) -> EffectOf { switch action { - case .onAppear: + case .checkUserLoginState: let isAppDeleted = userClient.isAppDeleted() let isLoggedIn = authClient.checkTokenIsExist() @@ -120,6 +121,14 @@ public struct AppFeature { return changeRoot(.Onboarding, state: &state) } + // AppDelegate Delegate + case let .appDelegate(.delegate(delegate)): + switch delegate { + case let .fcmTokenDidRecevied(fcmToken): + userClient.updateFcmToken(fcmToken: fcmToken) + return .send(.checkUserLoginState) + } + // Login Delegate case let .login(.delegate(delegate)): switch delegate { diff --git a/Tuist/ProjectDescriptionHelpers/InfoPlist+Templates.swift b/Tuist/ProjectDescriptionHelpers/InfoPlist+Templates.swift index 0efc57b9..91930e50 100644 --- a/Tuist/ProjectDescriptionHelpers/InfoPlist+Templates.swift +++ b/Tuist/ProjectDescriptionHelpers/InfoPlist+Templates.swift @@ -10,8 +10,8 @@ import ProjectDescription public extension InfoPlist { static var app: InfoPlist { return .extendingDefault(with: [ - "CFBundleShortVersionString": "1.0.2", - "CFBundleVersion": "21", + "CFBundleShortVersionString": "1.0.3", + "CFBundleVersion": "23", "UIUserInterfaceStyle": "Light", "CFBundleName": "보틀", "UILaunchScreen": [ @@ -39,8 +39,8 @@ public extension InfoPlist { static var example: InfoPlist { return .extendingDefault(with: [ - "CFBundleShortVersionString": "1.0.2", - "CFBundleVersion": "21", + "CFBundleShortVersionString": "1.0.3", + "CFBundleVersion": "23", "UIUserInterfaceStyle": "Light", "UILaunchScreen": [:], "UISupportedInterfaceOrientations": [