Skip to content

Commit a1efe58

Browse files
committed
refactor: SheetState 적용
1 parent 93ed007 commit a1efe58

4 files changed

Lines changed: 75 additions & 31 deletions

File tree

Application/DevLogPresentation/Sources/Root/RootFeature.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ struct RootFeature {
2222
@ObservableState
2323
struct State: Equatable {
2424
@Presents var alert: AlertState<Never>?
25+
@Presents var sheet: SheetState?
2526
var isNetworkConnected = true
2627
var signIn: Bool?
2728
var theme: SystemTheme = .automatic
@@ -30,13 +31,25 @@ struct RootFeature {
3031
var isObservingTheme = false
3132
}
3233

34+
@ObservableState
35+
struct SheetState: Equatable, Identifiable {
36+
let todoId: String
37+
var id: String { todoId }
38+
}
39+
3340
enum Action: Equatable {
3441
case alert(PresentationAction<Never>)
42+
case sheet(PresentationAction<Sheet>)
3543
case view(ViewAction)
3644
case store(StoreAction)
3745

3846
enum ViewAction: Equatable {
3947
case onAppear
48+
case presentTodoDetail(String)
49+
}
50+
51+
enum Sheet: Equatable {
52+
case tapCloseButton
4053
}
4154

4255
enum StoreAction: Equatable {
@@ -57,6 +70,10 @@ struct RootFeature {
5770
switch action {
5871
case .alert:
5972
break
73+
case .sheet(.dismiss), .sheet(.presented(.tapCloseButton)):
74+
state.sheet = nil
75+
case .sheet:
76+
break
6077
case .view(.onAppear):
6178
var effect = clearApplicationBadgeCountEffect()
6279

@@ -76,6 +93,8 @@ struct RootFeature {
7693
}
7794

7895
return effect
96+
case .view(.presentTodoDetail(let todoId)):
97+
state.sheet = .init(todoId: todoId)
7998
case .store(.networkStatusChanged(let isConnected)):
8099
let wasConnected = state.isNetworkConnected
81100
state.isNetworkConnected = isConnected
@@ -94,6 +113,18 @@ struct RootFeature {
94113
return .none
95114
}
96115
.ifLet(\.$alert, action: \.alert)
116+
.ifLet(\.$sheet, action: \.sheet) {
117+
RootSheetFeature()
118+
}
119+
}
120+
}
121+
122+
private struct RootSheetFeature: Reducer {
123+
typealias State = RootFeature.SheetState
124+
typealias Action = RootFeature.Action.Sheet
125+
126+
var body: some ReducerOf<Self> {
127+
EmptyReducer()
97128
}
98129
}
99130

Application/DevLogPresentation/Sources/Root/RootView.swift

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import DevLogDomain
1414
public struct RootView: View {
1515
@Environment(\.diContainer) var container: DIContainer
1616
@State private var store: StoreOf<RootFeature>
17-
@State private var selectedRoute: Route?
1817
@State private var selectedMainTab = MainTab.home
1918
private let widgetURLTab: (URL) -> MainTab?
2019
private let windowEvent: TodoEditorWindowEvent
@@ -80,42 +79,28 @@ public struct RootView: View {
8079
}
8180
}
8281
.alert($store.scope(state: \.alert, action: \.alert))
83-
.sheet(item: $selectedRoute) { route in
84-
switch route {
85-
case .todoDetail(let todoId):
86-
NavigationStack {
87-
TodoDetailView(store: Store(
88-
initialState: TodoDetailFeature.State(todoId: todoId, showEditButton: false)
89-
) {
90-
TodoDetailFeature()
91-
} withDependencies: {
92-
$0.fetchTodoByIdUseCase = container.resolve(FetchTodoByIdUseCase.self)
93-
$0.fetchReferenceItemsUseCase = container.resolve(FetchReferenceItemsUseCase.self)
94-
})
95-
.toolbar {
96-
ToolbarLeadingButton {
97-
selectedRoute = nil
98-
}
82+
.sheet(item: $store.scope(state: \.sheet, action: \.sheet)) { sheetStore in
83+
NavigationStack {
84+
TodoDetailView(store: Store(
85+
initialState: TodoDetailFeature.State(todoId: sheetStore.todoId, showEditButton: false)
86+
) {
87+
TodoDetailFeature()
88+
} withDependencies: {
89+
$0.fetchTodoByIdUseCase = container.resolve(FetchTodoByIdUseCase.self)
90+
$0.fetchReferenceItemsUseCase = container.resolve(FetchReferenceItemsUseCase.self)
91+
})
92+
.toolbar {
93+
ToolbarLeadingButton {
94+
sheetStore.send(.tapCloseButton)
9995
}
10096
}
101-
.background(Color(.systemGroupedBackground))
102-
.presentationDragIndicator(.visible)
10397
}
98+
.background(Color(.systemGroupedBackground))
99+
.presentationDragIndicator(.visible)
104100
}
105101
.onReceive(pushNotificationTodoIdPublisher) { todoId in
106-
selectedRoute = .todoDetail(todoId)
102+
store.send(.view(.presentTodoDetail(todoId)))
107103
clearPushNotificationRoute()
108104
}
109105
}
110106
}
111-
112-
private enum Route: Equatable, Identifiable {
113-
case todoDetail(String)
114-
115-
var id: String {
116-
switch self {
117-
case .todoDetail(let todoId):
118-
return "todo:\(todoId)"
119-
}
120-
}
121-
}

Application/DevLogPresentation/Tests/Root/RootFeatureTestSupport.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,15 @@ import Testing
1515
@MainActor
1616
protocol RootStateDriving {
1717
var snapshot: RootStateSnapshot { get }
18+
var sheetTodoId: String? { get }
1819

1920
func onAppear() async
2021
func setAlert(_ isPresented: Bool) async
2122
func networkStatusChanged(_ isConnected: Bool) async
2223
func setTheme(_ theme: SystemTheme) async
2324
func didLogined(_ signIn: Bool) async
25+
func presentTodoDetail(_ todoId: String) async
26+
func dismissSheet() async
2427
}
2528

2629
struct RootStateSnapshot: Equatable {
@@ -44,6 +47,7 @@ struct RootStoreTestAdapter: RootStateDriving {
4447
theme: store.state.theme
4548
)
4649
}
50+
var sheetTodoId: String? { store.state.sheet?.todoId }
4751

4852
init(
4953
sessionUseCase: ObserveAuthSessionUseCase = ObserveAuthSessionUseCaseSpy(currentValue: true),
@@ -95,6 +99,14 @@ struct RootStoreTestAdapter: RootStateDriving {
9599
await store.send(.store(.didLogined(signIn)))
96100
}
97101

102+
func presentTodoDetail(_ todoId: String) async {
103+
await store.send(.view(.presentTodoDetail(todoId)))
104+
}
105+
106+
func dismissSheet() async {
107+
await store.send(.sheet(.dismiss))
108+
}
109+
98110
private func drainReceivedActions() async {
99111
for _ in 0..<8 {
100112
await store.skipReceivedActions(strict: false)
@@ -191,6 +203,15 @@ func verifyObservedInitialValues(adapter: some RootStateDriving) async {
191203
)
192204
}
193205

206+
@MainActor
207+
func verifyTodoDetailSheetPresentation(adapter: some RootStateDriving) async {
208+
await adapter.presentTodoDetail("todo-1")
209+
#expect(adapter.sheetTodoId == "todo-1")
210+
211+
await adapter.dismissSheet()
212+
#expect(adapter.sheetTodoId == nil)
213+
}
214+
194215
final class ObserveAuthSessionUseCaseSpy: ObserveAuthSessionUseCase {
195216
let subject: CurrentValueSubject<Bool, Never>
196217
private(set) var observeCallCount = 0

Application/DevLogPresentation/Tests/Root/RootFeatureTests.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,11 @@ struct RootFeatureTests {
9090

9191
#expect(badgeSpy.counts == [0, 0])
9292
}
93+
94+
@Test("RootFeature는 TodoDetail sheet 표시와 해제를 store state로 관리한다")
95+
func RootFeature는_TodoDetail_sheet_표시와_해제를_store_state로_관리한다() async {
96+
let adapter = RootStoreTestAdapter()
97+
98+
await verifyTodoDetailSheetPresentation(adapter: adapter)
99+
}
93100
}

0 commit comments

Comments
 (0)