@@ -50,27 +50,31 @@ struct HomeFeature {
5050 case alert( PresentationAction < Never > )
5151 case sheet( PresentationAction < Sheet > )
5252 case fullScreenCover( PresentationAction < Never > )
53- case startObserving
54- case fetchData
55- case refreshRecentTodos
56- case networkStatusChanged( Bool )
57- case setSheet( SheetState ? )
58- case setPresentation( Presentation , Bool )
59- case setAlert( isPresented: Bool , type: AlertType ? = nil )
60- case refreshWebPages
61- case setWebPageHidden( URL , Bool )
62- case handleWebPageDeleteFailure( URL )
63- case finishDeleteWebPageToast( String )
64- case tapTodoCategory( TodoCategory )
65- case orderTodoCategory( [ TodoCategoryItem ] )
66- case updateWebPageURLInput( String )
67- case addWebPage
68- case deleteWebPage( WebPageItem )
69- case undoDeleteWebPage
53+ case view( ViewAction )
7054 case store( StoreAction )
7155 case loading( LoadingFeature . Action )
7256
57+ enum ViewAction : Equatable {
58+ case startObserving
59+ case fetchData
60+ case refreshRecentTodos
61+ case refreshWebPages
62+ case finishDeleteWebPageToast( String )
63+ case tapTodoCategory( TodoCategory )
64+ case orderTodoCategory( [ TodoCategoryItem ] )
65+ case updateWebPageURLInput( String )
66+ case addWebPage
67+ case deleteWebPage( WebPageItem )
68+ case undoDeleteWebPage
69+ }
70+
7371 enum StoreAction : Equatable {
72+ case networkStatusChanged( Bool )
73+ case setSheet( SheetState ? )
74+ case setPresentation( Presentation , Bool )
75+ case setAlert( isPresented: Bool , type: AlertType ? = nil )
76+ case setWebPageHidden( URL , Bool )
77+ case handleWebPageDeleteFailure( URL )
7478 case setTodoCategory( [ TodoCategoryItem ] )
7579 case updateRecentTodos( [ RecentTodoItem ] )
7680 case updateWebPages( [ WebPageItem ] )
@@ -193,82 +197,10 @@ struct HomeFeature {
193197 state. sheet = nil
194198 case . sheet:
195199 break
196- case . startObserving:
197- return observeNetworkConnectivityEffect ( )
198- case . fetchData:
199- return . merge(
200- fetchTodoCategoryPreferencesEffect ( ) ,
201- fetchRecentTodosEffect ( ) ,
202- fetchWebPagesEffect ( )
203- )
204- case . refreshRecentTodos:
205- return fetchRecentTodosEffect ( )
206- case . networkStatusChanged( let isConnected) :
207- state. isNetworkConnected = isConnected
208- case . setSheet( let sheet) :
209- state. sheet = sheet
210- case . setPresentation( let presentation, let isPresented) :
211- Self . setPresentation ( & state, presentation: presentation, isPresented: isPresented)
212- case . setAlert( let isPresented, let type) :
213- Self . setAlert ( & state, isPresented: isPresented, type: type)
214- case . refreshWebPages:
215- return fetchWebPagesEffect ( )
216- case . setWebPageHidden( let webPageURL, let isHidden) :
217- if let index = state. webPages. firstIndex ( where: { $0. id == webPageURL } ) {
218- state. webPages [ index] . isHidden = isHidden
219- }
220- case . handleWebPageDeleteFailure( let webPageURL) :
221- if let index = state. webPages. firstIndex ( where: { $0. id == webPageURL } ) {
222- state. webPages [ index] . isHidden = false
223- } else {
224- state. needsWebPageRefresh = true
225- }
226- case . finishDeleteWebPageToast( let urlString) :
227- state. webPages. removeAll { $0. url. absoluteString == urlString && $0. isHidden }
228- if state. deletedWebPageURLString == urlString {
229- state. deletedWebPageURLString = nil
230- }
231- case . tapTodoCategory( let category) :
232- state. selectedTodoCategory = category
233- state. sheet = nil
234- return delayedTodoEditorEffect ( )
235- case . orderTodoCategory( let preferences) :
236- state. preferences = preferences
237- state. recentTodos = Self . syncRecentTodos ( state. recentTodos, preferences: preferences)
238- state. sheet = nil
239- return updateTodoCategoryPreferencesEffect ( preferences)
240- case . updateWebPageURLInput( let text) :
241- state. webPageURLInput = text
242- case . addWebPage:
243- guard let normalizedURL = Self . normalizedWebPageURL ( state. webPageURLInput) else {
244- Self . setAlert ( & state, isPresented: true , type: . invalidURL)
245- return . none
246- }
247- state. sheet = nil
248- Self . setAlert ( & state, isPresented: false , type: nil )
249- return addWebPageEffect ( normalizedURL)
250- case . deleteWebPage( let page) :
251- guard let index = state. webPages. firstIndex ( where: { $0. id == page. id } ) else {
252- return . none
253- }
254- state. deletedWebPageURLString = page. url. absoluteString
255- state. webPages [ index] . isHidden = true
256- return deleteWebPageEffect ( page)
257- case . undoDeleteWebPage:
258- guard let urlString = state. deletedWebPageURLString else { return . none }
259- if let index = state. webPages. firstIndex ( where: { $0. url. absoluteString == urlString } ) {
260- state. webPages [ index] . isHidden = false
261- }
262- state. deletedWebPageURLString = nil
263- return undoDeleteWebPageEffect ( urlString)
264- case . store( . setTodoCategory( let preferences) ) :
265- state. preferences = preferences
266- state. recentTodos = Self . syncRecentTodos ( state. recentTodos, preferences: preferences)
267- case . store( . updateRecentTodos( let todos) ) :
268- state. recentTodos = todos
269- case . store( . updateWebPages( let pages) ) :
270- state. webPages = pages
271- state. needsWebPageRefresh = false
200+ case . view( let action) :
201+ return reduce ( action, state: & state)
202+ case . store( let action) :
203+ return reduce ( action, state: & state)
272204 case . loading:
273205 break
274206 }
@@ -282,6 +214,104 @@ struct HomeFeature {
282214 }
283215}
284216
217+ private extension HomeFeature {
218+ func reduce(
219+ _ action: Action . ViewAction ,
220+ state: inout State
221+ ) -> Effect < Action > {
222+ switch action {
223+ case . startObserving:
224+ return observeNetworkConnectivityEffect ( )
225+ case . fetchData:
226+ return . merge(
227+ fetchTodoCategoryPreferencesEffect ( ) ,
228+ fetchRecentTodosEffect ( ) ,
229+ fetchWebPagesEffect ( )
230+ )
231+ case . refreshRecentTodos:
232+ return fetchRecentTodosEffect ( )
233+ case . refreshWebPages:
234+ return fetchWebPagesEffect ( )
235+ case . finishDeleteWebPageToast( let urlString) :
236+ state. webPages. removeAll { $0. url. absoluteString == urlString && $0. isHidden }
237+ if state. deletedWebPageURLString == urlString {
238+ state. deletedWebPageURLString = nil
239+ }
240+ case . tapTodoCategory( let category) :
241+ state. selectedTodoCategory = category
242+ state. sheet = nil
243+ return delayedTodoEditorEffect ( )
244+ case . orderTodoCategory( let preferences) :
245+ state. preferences = preferences
246+ state. recentTodos = Self . syncRecentTodos ( state. recentTodos, preferences: preferences)
247+ state. sheet = nil
248+ return updateTodoCategoryPreferencesEffect ( preferences)
249+ case . updateWebPageURLInput( let text) :
250+ state. webPageURLInput = text
251+ case . addWebPage:
252+ guard let normalizedURL = Self . normalizedWebPageURL ( state. webPageURLInput) else {
253+ Self . setAlert ( & state, isPresented: true , type: . invalidURL)
254+ return . none
255+ }
256+ state. sheet = nil
257+ Self . setAlert ( & state, isPresented: false , type: nil )
258+ return addWebPageEffect ( normalizedURL)
259+ case . deleteWebPage( let page) :
260+ guard let index = state. webPages. firstIndex ( where: { $0. id == page. id } ) else {
261+ return . none
262+ }
263+ state. deletedWebPageURLString = page. url. absoluteString
264+ state. webPages [ index] . isHidden = true
265+ return deleteWebPageEffect ( page)
266+ case . undoDeleteWebPage:
267+ guard let urlString = state. deletedWebPageURLString else { return . none }
268+ if let index = state. webPages. firstIndex ( where: { $0. url. absoluteString == urlString } ) {
269+ state. webPages [ index] . isHidden = false
270+ }
271+ state. deletedWebPageURLString = nil
272+ return undoDeleteWebPageEffect ( urlString)
273+ }
274+
275+ return . none
276+ }
277+
278+ func reduce(
279+ _ action: Action . StoreAction ,
280+ state: inout State
281+ ) -> Effect < Action > {
282+ switch action {
283+ case . networkStatusChanged( let isConnected) :
284+ state. isNetworkConnected = isConnected
285+ case . setSheet( let sheet) :
286+ state. sheet = sheet
287+ case . setPresentation( let presentation, let isPresented) :
288+ Self . setPresentation ( & state, presentation: presentation, isPresented: isPresented)
289+ case . setAlert( let isPresented, let type) :
290+ Self . setAlert ( & state, isPresented: isPresented, type: type)
291+ case . setWebPageHidden( let webPageURL, let isHidden) :
292+ if let index = state. webPages. firstIndex ( where: { $0. id == webPageURL } ) {
293+ state. webPages [ index] . isHidden = isHidden
294+ }
295+ case . handleWebPageDeleteFailure( let webPageURL) :
296+ if let index = state. webPages. firstIndex ( where: { $0. id == webPageURL } ) {
297+ state. webPages [ index] . isHidden = false
298+ } else {
299+ state. needsWebPageRefresh = true
300+ }
301+ case . setTodoCategory( let preferences) :
302+ state. preferences = preferences
303+ state. recentTodos = Self . syncRecentTodos ( state. recentTodos, preferences: preferences)
304+ case . updateRecentTodos( let todos) :
305+ state. recentTodos = todos
306+ case . updateWebPages( let pages) :
307+ state. webPages = pages
308+ state. needsWebPageRefresh = false
309+ }
310+
311+ return . none
312+ }
313+ }
314+
285315private struct HomeSheetFeature : Reducer {
286316 typealias State = HomeFeature . SheetState
287317 typealias Action = HomeFeature . Sheet
0 commit comments