88import SwiftUI
99
1010struct TodayView : View {
11- @Environment ( NavigationRouter< TodayRoute> . self ) private var router
12- @State var viewModel : TodayViewModel
11+ let coordinator : TodayViewCoordinator
1312 let isCompactLayout : Bool
1413
1514 var body : some View {
1615 List {
1716 summarySection
18- if viewModel. sections. isEmpty, !viewModel. state. isLoading {
17+ if coordinator . viewModel. sections. isEmpty, !coordinator . viewModel. state. isLoading {
1918 emptySection
2019 } else {
21- ForEach ( viewModel. sections) { section in
20+ ForEach ( coordinator . viewModel. sections) { section in
2221 todoSection ( section. title, items: section. items)
2322 }
2423 }
@@ -27,21 +26,21 @@ struct TodayView: View {
2726 . navigationTitle ( String ( localized: " nav_today " ) )
2827 . toolbar { toolbarContent }
2928 . background ( NavigationBarConfigurator ( ) )
30- . refreshable { viewModel. send ( . refresh) }
31- . onAppear { viewModel. send ( . onAppear) }
29+ . refreshable { coordinator . viewModel. send ( . refresh) }
30+ . onAppear { coordinator . viewModel. send ( . onAppear) }
3231 . alert (
33- viewModel. state. alertTitle,
32+ coordinator . viewModel. state. alertTitle,
3433 isPresented: Binding (
35- get: { viewModel. state. showAlert } ,
36- set: { viewModel. send ( . setAlert( $0) ) }
34+ get: { coordinator . viewModel. state. showAlert } ,
35+ set: { coordinator . viewModel. send ( . setAlert( $0) ) }
3736 )
3837 ) {
3938 Button ( String ( localized: " common_close " ) , role: . cancel) { }
4039 } message: {
41- Text ( viewModel. state. alertMessage)
40+ Text ( coordinator . viewModel. state. alertMessage)
4241 }
4342 . overlay {
44- if viewModel. state. isLoading {
43+ if coordinator . viewModel. state. isLoading {
4544 LoadingView ( )
4645 }
4746 }
@@ -54,14 +53,14 @@ struct TodayView: View {
5453 ForEach ( TodayViewModel . SectionScope. allCases, id: \. self) { scope in
5554 Button {
5655 withAnimation ( . easeInOut) {
57- viewModel. send ( . setSectionScope( scope) )
56+ coordinator . viewModel. send ( . setSectionScope( scope) )
5857 }
5958 } label: {
6059 SummaryCard (
6160 title: scope. title,
62- value: viewModel. summaryValue ( for: scope) ,
61+ value: coordinator . viewModel. summaryValue ( for: scope) ,
6362 accentColor: scope. accentColor,
64- isSelected: viewModel. state. selectedSectionScope == scope
63+ isSelected: coordinator . viewModel. state. selectedSectionScope == scope
6564 )
6665 }
6766 . buttonStyle ( . plain)
@@ -81,8 +80,8 @@ struct TodayView: View {
8180 Picker (
8281 String ( localized: " today_due_visibility_label " ) ,
8382 selection: Binding (
84- get: { viewModel. state. displayOptions. dueDateVisibility } ,
85- set: { viewModel. send ( . setDueDateVisibility( $0) ) }
83+ get: { coordinator . viewModel. state. displayOptions. dueDateVisibility } ,
84+ set: { coordinator . viewModel. send ( . setDueDateVisibility( $0) ) }
8685 )
8786 ) {
8887 ForEach ( TodayDisplayOptions . DueDateVisibility. allCases, id: \. self) { option in
@@ -93,20 +92,20 @@ struct TodayView: View {
9392 Toggle (
9493 String ( localized: " today_pinned_only " ) ,
9594 isOn: Binding (
96- get: { viewModel. state. displayOptions. focusVisibility == . focusedOnly } ,
95+ get: { coordinator . viewModel. state. displayOptions. focusVisibility == . focusedOnly } ,
9796 set: {
98- viewModel. send ( . setFocusVisibility( $0 ? . focusedOnly : . all) )
97+ coordinator . viewModel. send ( . setFocusVisibility( $0 ? . focusedOnly : . all) )
9998 }
10099 )
101100 )
102101 . tint ( . orange)
103102
104- if viewModel. state. displayOptions. focusVisibility == . focusedOnly {
103+ if coordinator . viewModel. state. displayOptions. focusVisibility == . focusedOnly {
105104 Text ( String ( localized: " today_pinned_only_description " ) )
106105 . font ( . caption)
107106 }
108107 } label: {
109- let options = viewModel. state. displayOptions
108+ let options = coordinator . viewModel. state. displayOptions
110109 Image ( systemName: " line.3.horizontal.decrease.circle \( options == . default ? " " : " .fill " ) " )
111110 }
112111 }
@@ -135,15 +134,15 @@ struct TodayView: View {
135134 todoRow ( item)
136135 . swipeActions ( edge: . leading, allowsFullSwipe: false ) {
137136 Button {
138- viewModel. send ( . togglePinned( item) )
137+ coordinator . viewModel. send ( . togglePinned( item) )
139138 } label: {
140139 Image ( systemName: item. isPinned ? " star.slash " : " star.fill " )
141140 }
142141 . tint ( . orange)
143142 }
144143 . swipeActions ( edge: . trailing, allowsFullSwipe: false ) {
145144 Button {
146- viewModel. send ( . completeTodo( item) )
145+ coordinator . viewModel. send ( . completeTodo( item) )
147146 } label: {
148147 Label ( String ( localized: " today_complete_action " ) , systemImage: " checkmark " )
149148 }
@@ -162,24 +161,23 @@ struct TodayView: View {
162161 if isCompactLayout {
163162 NavigationLink ( value: TodayRoute . todo ( TodoIdItem ( id: item. id) ) ) {
164163 TodayTodoRow ( item: item)
165- . listRowInsets ( EdgeInsets ( top: 0 , leading: 16 , bottom: 0 , trailing: 16 ) )
166164 }
167165 } else {
168166 Button {
169- router. replace ( with: . todo( TodoIdItem ( id: item. id) ) )
167+ coordinator . router. replace ( with: . todo( TodoIdItem ( id: item. id) ) )
170168 } label: {
171169 TodayTodoRow ( item: item)
172170 . frame ( maxWidth: . infinity, alignment: . leading)
173- . listRowInsets ( EdgeInsets ( top : 0 , leading : 16 , bottom : 0 , trailing : 16 ) )
171+ . contentShape ( . rect )
174172 }
175173 . buttonStyle ( . plain)
176174 }
177175 }
178176
179177 private var emptyStateContent : EmptyStateContent {
180- switch viewModel. state. selectedSectionScope {
178+ switch coordinator . viewModel. state. selectedSectionScope {
181179 case . all:
182- if viewModel. state. todos. isEmpty {
180+ if coordinator . viewModel. state. todos. isEmpty {
183181 return EmptyStateContent (
184182 title: String ( localized: " today_empty_all_title " ) ,
185183 message: String ( localized: " today_empty_all_message " )
0 commit comments