@@ -8,7 +8,9 @@ import Foundation
88
99import ComposableArchitecture
1010import CoreKit
11+ import Domain
1112import Util
13+ import UIKit
1214
1315@Reducer
1416public struct SplashFeature {
@@ -21,10 +23,13 @@ public struct SplashFeature {
2123 var authClient
2224 @Dependency ( KeychainClient . self)
2325 var keychain
26+ @Dependency ( VersionClient . self)
27+ var versionClient
2428 /// - State
2529 @ObservableState
26- public struct State : Equatable {
30+ public struct State {
2731 @Shared ( . appStorage( " isNeedSessionDeleted " ) ) var isNeedSessionDeleted : Bool = true
32+ @Presents var alert : AlertState < Action . Alert > ?
2833 public init ( ) { }
2934 }
3035 /// - Action
@@ -36,18 +41,26 @@ public struct SplashFeature {
3641 case delegate( DelegateAction )
3742
3843 @CasePathable
39- public enum View : Equatable {
44+ public enum View : BindableAction , Equatable {
45+ case binding( BindingAction < State > )
4046 case onAppear
4147 }
4248 public enum InnerAction : Equatable {
4349 case 키_제거
50+ case 앱스토어_알림_활성화( trackId: Int )
51+ }
52+ public enum AsyncAction : Equatable { case 없음 }
53+ @CasePathable
54+ public enum ScopeAction {
55+ case alert( PresentationAction < Alert > )
4456 }
45- public enum AsyncAction : Equatable { case doNothing }
46- public enum ScopeAction : Equatable { case doNothing }
4757 public enum DelegateAction : Equatable {
4858 case loginNeeded
4959 case autoLoginSuccess
5060 }
61+ public enum Alert {
62+ case 앱스토어_이동( trackId: Int )
63+ }
5164 }
5265 /// initiallizer
5366 public init ( ) { }
@@ -73,17 +86,34 @@ public struct SplashFeature {
7386 }
7487 /// - Reducer body
7588 public var body : some ReducerOf < Self > {
89+ BindingReducer ( action: \. view)
7690 Reduce ( self . core)
91+ . ifLet ( \. $alert, action: \. scope. alert)
7792 }
7893}
7994//MARK: - FeatureAction Effect
8095private extension SplashFeature {
8196 /// - View Effect
8297 func handleViewAction( _ action: Action . View , state: inout State ) -> Effect < Action > {
8398 switch action {
99+ case . binding:
100+ return . none
101+
84102 case . onAppear:
85103 return . run { [ isNeedSessionDeleted = state. isNeedSessionDeleted] send in
86104 try await self . clock. sleep ( for: . milliseconds( 2000 ) )
105+ /// Version Check
106+ let response = try await versionClient. 버전체크 ( ) . toDomain ( )
107+ guard
108+ let info = Bundle . main. infoDictionary,
109+ let currentVersion = info [ " CFBundleShortVersionString " ] as? String else { return }
110+ let appStoreVersion = response
111+ let nowVersion = Version ( currentVersion, trackId: response. trackId)
112+
113+ if nowVersion < appStoreVersion {
114+ await send ( . inner( . 앱스토어_알림_활성화( trackId: response. trackId) ) )
115+ return
116+ }
87117 if isNeedSessionDeleted {
88118 guard let platform = userDefaults. stringKey ( . authPlatform) else {
89119 print ( " platform이 없어서 벗어남 " )
@@ -161,6 +191,18 @@ private extension SplashFeature {
161191 await userDefaults. removeString ( . authPlatform)
162192 await isNeedSessionDeleted. withLock { $0 = false }
163193 }
194+
195+ case let . 앱스토어_알림_활성화( trackId) :
196+ state. alert = . init( title: {
197+ TextState ( " 업데이트 " )
198+ } , actions: {
199+ ButtonState ( role: . none, action: . 앱스토어_이동( trackId: trackId) ) {
200+ TextState ( " 앱스토어 이동 " )
201+ }
202+ } , message: {
203+ TextState ( " 최신버전의 포킷으로 업데이트가 필요합니다. " )
204+ } )
205+ return . none
164206 }
165207 }
166208 /// - Async Effect
@@ -169,10 +211,25 @@ private extension SplashFeature {
169211 }
170212 /// - Scope Effect
171213 func handleScopeAction( _ action: Action . ScopeAction , state: inout State ) -> Effect < Action > {
214+ switch action {
215+ case let . alert( . presented( . 앱스토어_이동( trackId) ) ) :
216+ if let url = URL ( string: " https://apps.apple.com/app/id \( trackId) " ) ,
217+ UIApplication . shared. canOpenURL ( url) {
218+ UIApplication . shared. open ( url, options: [ : ] , completionHandler: nil )
219+ }
220+ return . none
221+
222+ case . alert:
223+ return . none
224+ }
172225 return . none
173226 }
174227 /// - Delegate Effect
175228 func handleDelegateAction( _ action: Action . DelegateAction , state: inout State ) -> Effect < Action > {
176229 return . none
177230 }
231+
232+ func versionCheck( ) -> Effect < Action > {
233+ return . none
234+ }
178235}
0 commit comments