66//
77
88import SwiftUI
9+ import ComposableArchitecture
910import DevLogCore
1011import DevLogDomain
1112
1213struct TodoDetailView : View {
1314 @Environment ( \. diContainer) private var container : DIContainer
1415 @Environment ( \. openWindow) private var openWindow
1516 @Environment ( \. isiOSAppOnMac) private var isiOSAppOnMac
16- @State var viewModel : TodoDetailViewModel
17+ @State private var store : StoreOf < TodoDetailFeature >
18+
19+ init ( store: StoreOf < TodoDetailFeature > ) {
20+ self . _store = State ( initialValue: store)
21+ }
22+
23+ init (
24+ fetchTodoUseCase: FetchTodoByIdUseCase ,
25+ fetchReferenceItemsUseCase: FetchReferenceItemsUseCase ,
26+ todoId: String ,
27+ showEditButton: Bool = true
28+ ) {
29+ self . init ( store: Store (
30+ initialState: TodoDetailFeature . State (
31+ todoId: todoId,
32+ showEditButton: showEditButton
33+ )
34+ ) {
35+ TodoDetailFeature ( )
36+ } withDependencies: {
37+ $0. fetchTodoByIdUseCase = fetchTodoUseCase
38+ $0. fetchReferenceItemsUseCase = fetchReferenceItemsUseCase
39+ } )
40+ }
1741
1842 var body : some View {
1943 ZStack {
2044 Color ( . systemGroupedBackground) . ignoresSafeArea ( )
21- if let todo = viewModel . state . todo {
45+ if let todo = store . todo {
2246 TodoDetailContentView (
2347 title: todo. title,
2448 content: todo. content,
25- referenceItems: viewModel . state . referenceItems,
49+ referenceItems: store . referenceItems,
2650 number: todo. number,
27- onOpenTodoID: { viewModel . send ( . setSelectedTodoId ( TodoIdItem ( id: $0) ) ) }
51+ onOpenTodoID: { store . send ( . setSheet ( . todo ( TodoIdItem ( id: $0) ) ) ) }
2852 )
29- } else if viewModel . state . isLoading {
53+ } else if store . isLoading {
3054 LoadingView ( )
3155 }
3256 }
33- . onAppear { viewModel . send ( . onAppear) }
57+ . onAppear { store . send ( . onAppear) }
3458 . navigationBarTitleDisplayMode ( . inline)
35- . sheet ( isPresented: Binding (
36- get: { viewModel. state. showInfo } ,
37- set: { viewModel. send ( . setShowInfo( $0) ) }
38- ) ) {
39- sheetContent
40- }
41- . sheet ( item: Binding (
42- get: { viewModel. state. selectedTodoId } ,
43- set: { viewModel. send ( . setSelectedTodoId( $0) ) }
44- ) ) { item in
45- NavigationStack {
46- TodoDetailView ( viewModel: TodoDetailViewModel (
47- fetchTodoUseCase: container. resolve ( FetchTodoByIdUseCase . self) ,
48- fetchReferenceItemsUseCase: container. resolve ( FetchReferenceItemsUseCase . self) ,
49- todoId: item. id,
50- showEditButton: false
51- ) )
52- . toolbar {
53- ToolbarLeadingButton {
54- viewModel. send ( . setSelectedTodoId( nil ) )
55- }
56- }
57- }
58- . background ( Color ( . systemGroupedBackground) )
59- . presentationDragIndicator ( . visible)
59+ . alert ( $store. scope ( state: \. alert, action: \. alert) )
60+ . sheet ( item: $store. scope ( state: \. sheet, action: \. sheet) ) { sheetStore in
61+ sheetContent ( sheetStore)
6062 }
61- . fullScreenCover ( isPresented: Binding (
62- get: { viewModel. state. showEditor } ,
63- set: { viewModel. send ( . setShowEditor( $0) ) }
64- ) ) {
65- if let todo = viewModel. state. todo {
66- TodoEditorView (
67- viewModel: TodoEditorViewModel (
68- todo: todo,
69- fetchPreferencesUseCase: container. resolve ( FetchTodoCategoryPreferencesUseCase . self) ,
70- fetchReferenceItemsUseCase: container. resolve ( FetchReferenceItemsUseCase . self) ,
71- upsertTodoUseCase: container. resolve ( UpsertTodoUseCase . self) ,
72- onUpdateSuccess: { todo in
73- viewModel. send ( . setShowEditor( false ) )
74- viewModel. send ( . setTodo( todo) )
75- }
76- )
77- )
78- }
63+ . fullScreenCover (
64+ item: $store. scope ( state: \. fullScreenCover, action: \. fullScreenCover)
65+ ) { coverStore in
66+ fullScreenCoverContent ( coverStore)
7967 }
8068 . toolbar { toolbarContent }
8169 }
@@ -84,12 +72,12 @@ struct TodoDetailView: View {
8472 private var toolbarContent : some ToolbarContent {
8573 ToolbarItem ( placement: . topBarTrailing) {
8674 Button {
87- viewModel . send ( . setShowInfo ( true ) )
75+ store . send ( . setSheet ( . info ) )
8876 } label: {
8977 Image ( systemName: " info.circle " )
9078 }
9179 }
92- if viewModel . showEditButton {
80+ if store . showEditButton {
9381 if #available( iOS 26 . 0 , * ) {
9482 ToolbarSpacer ( . fixed, placement: . topBarTrailing)
9583 }
@@ -105,22 +93,66 @@ struct TodoDetailView: View {
10593
10694 private func openTodoEditor( ) {
10795 if isiOSAppOnMac {
108- guard let todo = viewModel . state . todo else { return }
96+ guard let todo = store . todo else { return }
10997 openWindow (
11098 id: TodoEditorWindowValue . sceneId,
11199 value: TodoEditorWindowValue ( todo: todo)
112100 )
113101 } else {
114- viewModel. send ( . setShowEditor( true ) )
102+ store. send ( . setFullScreenCover( . editor) )
103+ }
104+ }
105+
106+ @ViewBuilder
107+ private func fullScreenCoverContent(
108+ _ coverStore: Store < TodoDetailFeature . FullScreenCoverState , Never >
109+ ) -> some View {
110+ switch coverStore. destination {
111+ case . editor:
112+ if let todo = store. todo {
113+ TodoEditorView (
114+ viewModel: TodoEditorViewModel (
115+ todo: todo,
116+ fetchPreferencesUseCase: container. resolve ( FetchTodoCategoryPreferencesUseCase . self) ,
117+ fetchReferenceItemsUseCase: container. resolve ( FetchReferenceItemsUseCase . self) ,
118+ upsertTodoUseCase: container. resolve ( UpsertTodoUseCase . self) ,
119+ onUpdateSuccess: { todo in
120+ store. send ( . setFullScreenCover( nil ) )
121+ store. send ( . setTodo( todo) )
122+ }
123+ )
124+ )
125+ }
115126 }
116127 }
117128
118129 @ViewBuilder
119- private var sheetContent : some View {
120- if let todo = viewModel. state. todo {
121- TodoDetailInfoSheetView ( todo: todo) {
122- viewModel. send ( . setShowInfo( false ) )
130+ private func sheetContent(
131+ _ sheetStore: Store < TodoDetailFeature . SheetState , TodoDetailFeature . Action . Sheet >
132+ ) -> some View {
133+ switch sheetStore. destination {
134+ case . info:
135+ if let todo = store. todo {
136+ TodoDetailInfoSheetView ( todo: todo) {
137+ sheetStore. send ( . tapCloseButton)
138+ }
123139 }
140+ case . todo( let item) :
141+ NavigationStack {
142+ TodoDetailView (
143+ fetchTodoUseCase: container. resolve ( FetchTodoByIdUseCase . self) ,
144+ fetchReferenceItemsUseCase: container. resolve ( FetchReferenceItemsUseCase . self) ,
145+ todoId: item. id,
146+ showEditButton: false
147+ )
148+ . toolbar {
149+ ToolbarLeadingButton {
150+ sheetStore. send ( . tapCloseButton)
151+ }
152+ }
153+ }
154+ . background ( Color ( . systemGroupedBackground) )
155+ . presentationDragIndicator ( . visible)
124156 }
125157 }
126158}
0 commit comments