@@ -22,6 +22,7 @@ final class PushNotificationViewModel: Store {
2222 var sortOption : SortOption
2323 var timeFilter : TimeFilter
2424 var showUnreadOnly : Bool
25+ var selectedTodoID : TodoIDItem ?
2526 }
2627
2728 enum Action {
@@ -38,10 +39,12 @@ final class PushNotificationViewModel: Store {
3839 case setTimeFilter( TimeFilter )
3940 case toggleUnreadOnly
4041 case resetFilters
42+ case tapNotification( PushNotification )
43+ case setSelectedTodoID( TodoIDItem ? )
4144 }
4245
4346 enum SideEffect {
44- case fetch
47+ case fetchNotifications
4548 case delete( PushNotification )
4649 case toggleRead( String )
4750 }
@@ -116,7 +119,7 @@ final class PushNotificationViewModel: Store {
116119 }
117120
118121 @Published private( set) var state : State
119- private let fetchUseCase : FetchPushNotificationsUseCase
122+ private let fetchNotificationUseCase : FetchPushNotificationsUseCase
120123 private let deleteUseCase : DeletePushNotificationUseCase
121124 private let toggleReadUseCase : TogglePushNotificationReadUseCase
122125 private let userDefaults : UserDefaults
@@ -133,7 +136,7 @@ final class PushNotificationViewModel: Store {
133136 toggleReadUseCase: TogglePushNotificationReadUseCase ,
134137 userDefaults: UserDefaults = . standard
135138 ) {
136- self . fetchUseCase = fetchUseCase
139+ self . fetchNotificationUseCase = fetchUseCase
137140 self . deleteUseCase = deleteUseCase
138141 self . toggleReadUseCase = toggleReadUseCase
139142 self . userDefaults = userDefaults
@@ -180,51 +183,15 @@ final class PushNotificationViewModel: Store {
180183 var effects : [ SideEffect ] = [ ]
181184
182185 switch action {
183- case . fetchNotifications:
184- effects = [ . fetch]
185- case . deleteNotification( let item) :
186- guard let index = state. notifications. firstIndex ( where: { $0. id == item. id } ) else {
187- break
188- }
189- state. pendingTask = ( item, index)
190- state. notifications. remove ( at: index)
191- setToast ( & state, isPresented: true , for: . delete)
192- case . toggleRead( let item) :
193- if let index = state. notifications. firstIndex ( where: { $0. id == item. id } ) {
194- state. notifications [ index] . isRead. toggle ( )
195- effects = [ . toggleRead( item. todoID) ]
196- }
197- case . undoDelete:
198- guard let ( item, index) = state. pendingTask else { break }
199- state. notifications. insert ( item, at: index)
200- state. pendingTask = nil
201- case . confirmDelete:
202- guard let ( item, _ ) = state. pendingTask else { break }
203- effects = [ . delete( item) ]
204- case . setAlert( let isPresented, let type) :
205- setAlert ( & state, isPresented: isPresented, for: type)
206- case . setToast( let isPresented, let type) :
207- setToast ( & state, isPresented: isPresented, for: type)
208- case . setLoading( let value) :
209- state. isLoading = value
210- case . setNotifications( let notifications) :
211- state. notifications = notifications
212- case . toggleSortOption:
213- state. sortOption = state. sortOption == . latest ? . oldest : . latest
214- saveSortOption ( state. sortOption)
215- case . setTimeFilter( let filter) :
216- state. timeFilter = filter
217- saveTimeFilter ( filter)
218- case . toggleUnreadOnly:
219- state. showUnreadOnly. toggle ( )
220- userDefaults. set ( state. showUnreadOnly, forKey: DefaultsKey . showUnreadOnly)
221- case . resetFilters:
222- state. sortOption = . latest
223- state. timeFilter = . none
224- state. showUnreadOnly = false
225- saveSortOption ( . latest)
226- saveTimeFilter ( . none)
227- userDefaults. set ( false , forKey: DefaultsKey . showUnreadOnly)
186+ case . deleteNotification, . toggleRead, . undoDelete, . setAlert, . toggleSortOption,
187+ . setTimeFilter, . toggleUnreadOnly, . resetFilters, . tapNotification:
188+ effects = reduceByUser ( action, state: & state)
189+
190+ case . fetchNotifications, . confirmDelete, . setToast, . setSelectedTodoID:
191+ effects = reduceByView ( action, state: & state)
192+
193+ case . setLoading, . setNotifications:
194+ effects = reduceByRun ( action, state: & state)
228195 }
229196
230197 self . state = state
@@ -233,12 +200,12 @@ final class PushNotificationViewModel: Store {
233200
234201 func run( _ effect: SideEffect ) {
235202 switch effect {
236- case . fetch :
203+ case . fetchNotifications :
237204 Task {
238205 do {
239206 defer { send ( . setLoading( false ) ) }
240207 send ( . setLoading( true ) )
241- let notifications = try await fetchUseCase . execute ( )
208+ let notifications = try await fetchNotificationUseCase . execute ( )
242209 send ( . setNotifications( notifications) )
243210 } catch {
244211 send ( . setAlert( isPresented: true , type: . error) )
@@ -264,6 +231,81 @@ final class PushNotificationViewModel: Store {
264231 }
265232}
266233
234+ // MARK: - Reduce Methods
235+ private extension PushNotificationViewModel {
236+ func reduceByUser( _ action: Action , state: inout State ) -> [ SideEffect ] {
237+ switch action {
238+ case . deleteNotification( let item) :
239+ if let index = state. notifications. firstIndex ( where: { $0. id == item. id } ) {
240+ state. pendingTask = ( item, index)
241+ state. notifications. remove ( at: index)
242+ setToast ( & state, isPresented: true , for: . delete)
243+ }
244+ case . toggleRead( let item) :
245+ if let index = state. notifications. firstIndex ( where: { $0. id == item. id } ) {
246+ state. notifications [ index] . isRead. toggle ( )
247+ return [ . toggleRead( item. todoID) ]
248+ }
249+ case . undoDelete:
250+ guard let ( item, index) = state. pendingTask else { return [ ] }
251+ state. notifications. insert ( item, at: index)
252+ state. pendingTask = nil
253+ case . setAlert( let isPresented, let type) :
254+ setAlert ( & state, isPresented: isPresented, for: type)
255+ case . toggleSortOption:
256+ state. sortOption = state. sortOption == . latest ? . oldest : . latest
257+ saveSortOption ( state. sortOption)
258+ case . setTimeFilter( let filter) :
259+ state. timeFilter = filter
260+ saveTimeFilter ( filter)
261+ case . toggleUnreadOnly:
262+ state. showUnreadOnly. toggle ( )
263+ userDefaults. set ( state. showUnreadOnly, forKey: DefaultsKey . showUnreadOnly)
264+ case . resetFilters:
265+ state. sortOption = . latest
266+ state. timeFilter = . none
267+ state. showUnreadOnly = false
268+ saveSortOption ( . latest)
269+ saveTimeFilter ( . none)
270+ userDefaults. set ( false , forKey: DefaultsKey . showUnreadOnly)
271+ case . tapNotification( let notification) :
272+ state. selectedTodoID = TodoIDItem ( id: notification. todoID)
273+ default :
274+ break
275+ }
276+ return [ ]
277+ }
278+
279+ func reduceByView( _ action: Action , state: inout State ) -> [ SideEffect ] {
280+ switch action {
281+ case . fetchNotifications:
282+ return [ . fetchNotifications]
283+ case . confirmDelete:
284+ guard let ( item, _ ) = state. pendingTask else { return [ ] }
285+ return [ . delete( item) ]
286+ case . setToast( let isPresented, let type) :
287+ setToast ( & state, isPresented: isPresented, for: type)
288+ case . setSelectedTodoID( let todoID) :
289+ state. selectedTodoID = todoID
290+ default :
291+ break
292+ }
293+ return [ ]
294+ }
295+
296+ func reduceByRun( _ action: Action , state: inout State ) -> [ SideEffect ] {
297+ switch action {
298+ case . setLoading( let value) :
299+ state. isLoading = value
300+ case . setNotifications( let notifications) :
301+ state. notifications = notifications
302+ default :
303+ break
304+ }
305+ return [ ]
306+ }
307+ }
308+
267309private extension PushNotificationViewModel {
268310 func setAlert(
269311 _ state: inout State ,
0 commit comments