Skip to content

Commit 2a64384

Browse files
committed
refactor: Todo 편집 윈도우 이벤트 전달 구조 개선
1 parent eb19e38 commit 2a64384

10 files changed

Lines changed: 64 additions & 39 deletions

File tree

Application/DevLogApp/Sources/App/DevLogApp.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,23 @@ struct DevLogApp: App {
3030
systemThemeUseCase: container.resolve(ObserveSystemThemeUseCase.self),
3131
trackAnalyticsEventUseCase: container.resolve(TrackAnalyticsEventUseCase.self),
3232
widgetURLTab: { MainTab(widgetURL: $0) },
33+
windowEvent: windowEvent,
3334
pushNotificationTodoIdPublisher: PushNotificationRoute.shared.observe(),
3435
clearPushNotificationRoute: { PushNotificationRoute.shared.clear() }
3536
)
3637
.autocorrectionDisabled()
37-
.environment(windowEvent)
3838
.onChange(of: scenePhase) { _, phase in
3939
guard phase == .background else { return }
4040
container.resolve(WidgetSyncEventBus.self).publish(.syncRequested)
4141
}
4242
}
4343
WindowGroup(id: TodoEditorWindowValue.sceneId, for: TodoEditorWindowValue.self) { value in
4444
if let value = value.wrappedValue {
45-
TodoEditorWindowView(value: value)
45+
TodoEditorWindowView(
46+
value: value,
47+
windowEvent: windowEvent
48+
)
4649
.autocorrectionDisabled()
47-
.environment(windowEvent)
4850
} else {
4951
ContentUnavailableView(
5052
String(localized: "todo_edit"),

Application/DevLogPresentation/Sources/Home/Home/HomeView.swift

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import SwiftUI
99
import DevLogDomain
1010

1111
struct HomeView: View {
12-
@Environment(TodoEditorWindowEvent.self) private var windowEvent
1312
@Environment(\.openWindow) private var openWindow
1413
@Environment(\.isiOSAppOnMac) private var isiOSAppOnMac
1514
@ScaledMetric(relativeTo: .largeTitle) private var labelWidth = CGFloat(34)
@@ -89,9 +88,6 @@ struct HomeView: View {
8988
LoadingView()
9089
}
9190
}
92-
.onChange(of: windowEvent.submitted) { _, submitted in
93-
handleTodoEditorSubmit(submitted)
94-
}
9591
}
9692

9793
@ViewBuilder
@@ -403,11 +399,6 @@ struct HomeView: View {
403399
}
404400
}
405401

406-
private func handleTodoEditorSubmit(_ submit: TodoEditorWindowSubmit?) {
407-
guard let submit, submit.value.matchesCreate(source: .home) else { return }
408-
coordinator.viewModel.send(.fetchData)
409-
}
410-
411402
}
412403

413404
enum HomeRoute: Hashable {

Application/DevLogPresentation/Sources/Home/Home/HomeViewCoordinator.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// Created by opfic on 5/10/26.
66
//
77

8+
import Combine
89
import Foundation
910
import DevLogCore
1011
import DevLogDomain
@@ -15,6 +16,8 @@ final class HomeViewCoordinator {
1516
let viewModel: HomeViewModel
1617
let router = NavigationRouter<HomeRoute>()
1718
private let diContainer: DIContainer
19+
@ObservationIgnored
20+
private var cancellable: AnyCancellable?
1821

1922
init(container: DIContainer) {
2023
self.diContainer = container
@@ -35,6 +38,16 @@ final class HomeViewCoordinator {
3538
viewModel.send(.fetchData)
3639
}
3740

41+
func bindWindowEvent(_ windowEvent: TodoEditorWindowEvent) {
42+
guard cancellable == nil else { return }
43+
44+
cancellable = windowEvent.submits
45+
.sink { [weak self] submit in
46+
guard submit.value.matchesCreate(source: .home) else { return }
47+
self?.viewModel.send(.fetchData)
48+
}
49+
}
50+
3851
func makeTodoManageViewModel() -> TodoManageViewModel {
3952
TodoManageViewModel(viewModel.state.preferences)
4053
}

Application/DevLogPresentation/Sources/Home/TodoDetailView.swift

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import DevLogDomain
1111

1212
struct TodoDetailView: View {
1313
@Environment(\.diContainer) private var container: DIContainer
14-
@Environment(TodoEditorWindowEvent.self) private var windowEvent
1514
@Environment(\.openWindow) private var openWindow
1615
@Environment(\.isiOSAppOnMac) private var isiOSAppOnMac
1716
@State var viewModel: TodoDetailViewModel
@@ -32,9 +31,6 @@ struct TodoDetailView: View {
3231
}
3332
}
3433
.onAppear { viewModel.send(.onAppear) }
35-
.onChange(of: windowEvent.submitted) { _, submitted in
36-
handleTodoEditorSubmit(submitted)
37-
}
3834
.navigationBarTitleDisplayMode(.inline)
3935
.sheet(isPresented: Binding(
4036
get: { viewModel.state.showInfo },
@@ -119,12 +115,6 @@ struct TodoDetailView: View {
119115
}
120116
}
121117

122-
private func handleTodoEditorSubmit(_ submit: TodoEditorWindowSubmit?) {
123-
guard let submit,
124-
submit.value.matchesEdit(todoId: viewModel.todoId) else { return }
125-
viewModel.send(.setTodo(submit.todo))
126-
}
127-
128118
@ViewBuilder
129119
private var sheetContent: some View {
130120
if let todo = viewModel.state.todo {

Application/DevLogPresentation/Sources/Home/TodoEditorWindowEvent.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,22 @@
55
// Created by opfic on 5/31/26.
66
//
77

8-
import Foundation
8+
import Combine
99
import DevLogDomain
1010

11-
@MainActor
12-
@Observable
1311
public final class TodoEditorWindowEvent {
14-
var submitted: TodoEditorWindowSubmit?
12+
private let subject = PassthroughSubject<TodoEditorWindowSubmit, Never>()
13+
14+
var submits: AnyPublisher<TodoEditorWindowSubmit, Never> {
15+
subject.eraseToAnyPublisher()
16+
}
1517

1618
public init() { }
1719

1820
func submit(
1921
value: TodoEditorWindowValue,
2022
todo: Todo
2123
) {
22-
submitted = TodoEditorWindowSubmit(value: value, todo: todo)
24+
subject.send(TodoEditorWindowSubmit(value: value, todo: todo))
2325
}
2426
}

Application/DevLogPresentation/Sources/Home/TodoEditorWindowView.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@ import DevLogDomain
1111

1212
public struct TodoEditorWindowView: View {
1313
@Environment(\.diContainer) private var container: DIContainer
14-
@Environment(TodoEditorWindowEvent.self) private var windowEvent
1514
@State private var windowScene: UIWindowScene?
1615
private let value: TodoEditorWindowValue
16+
private let windowEvent: TodoEditorWindowEvent
1717

18-
public init(value: TodoEditorWindowValue) {
18+
public init(
19+
value: TodoEditorWindowValue,
20+
windowEvent: TodoEditorWindowEvent
21+
) {
1922
self.value = value
23+
self.windowEvent = windowEvent
2024
}
2125

2226
public var body: some View {

Application/DevLogPresentation/Sources/Home/TodoListView.swift

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import DevLogDomain
1111

1212
struct TodoListView: View {
1313
@Environment(NavigationRouter<HomeRoute>.self) private var router
14-
@Environment(TodoEditorWindowEvent.self) private var windowEvent
1514
@Environment(\.diContainer) var container: DIContainer
1615
@Environment(\.colorScheme) private var colorScheme
1716
@Environment(\.openWindow) private var openWindow
@@ -118,9 +117,6 @@ struct TodoListView: View {
118117
}
119118
.background(NavigationBarConfigurator())
120119
.task { viewModel.send(.onAppear) }
121-
.onChange(of: windowEvent.submitted) { _, submitted in
122-
handleTodoEditorSubmit(submitted)
123-
}
124120
}
125121

126122
@ViewBuilder
@@ -252,12 +248,6 @@ struct TodoListView: View {
252248
}
253249
}
254250

255-
private func handleTodoEditorSubmit(_ submit: TodoEditorWindowSubmit?) {
256-
guard let submit,
257-
submit.value.matchesCreate(category: viewModel.category, source: .list) else { return }
258-
viewModel.send(.refresh)
259-
}
260-
261251
@ViewBuilder
262252
private var searchResultsContent: some View {
263253
let searchResults = viewModel.state.searchResults.filter { !$0.isHidden }

Application/DevLogPresentation/Sources/Home/TodoWindowCoordinator.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// Created by opfic on 5/31/26.
66
//
77

8+
import Combine
89
import Foundation
910
import DevLogCore
1011
import DevLogDomain
@@ -17,11 +18,22 @@ final class TodoWindowCoordinator {
1718
private var listViewModel: TodoListViewModel?
1819
@ObservationIgnored
1920
private var detailViewModel: TodoDetailViewModel?
21+
@ObservationIgnored
22+
private var cancellable: AnyCancellable?
2023

2124
init(container: DIContainer) {
2225
self.diContainer = container
2326
}
2427

28+
func bindWindowEvent(_ windowEvent: TodoEditorWindowEvent) {
29+
guard cancellable == nil else { return }
30+
31+
cancellable = windowEvent.submits
32+
.sink { [weak self] submit in
33+
self?.handleTodoEditorSubmit(submit)
34+
}
35+
}
36+
2537
func makeListViewModel(category: TodoCategory) -> TodoListViewModel {
2638
if let listViewModel,
2739
listViewModel.category == category {
@@ -60,4 +72,16 @@ final class TodoWindowCoordinator {
6072
self.detailViewModel = detailViewModel
6173
return detailViewModel
6274
}
75+
76+
private func handleTodoEditorSubmit(_ submit: TodoEditorWindowSubmit) {
77+
if let listViewModel,
78+
submit.value.matchesCreate(category: listViewModel.category, source: .list) {
79+
listViewModel.send(.refresh)
80+
}
81+
82+
if let detailViewModel,
83+
submit.value.matchesEdit(todoId: detailViewModel.todoId) {
84+
detailViewModel.send(.setTodo(submit.todo))
85+
}
86+
}
6387
}

Application/DevLogPresentation/Sources/Main/MainView.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ struct MainView: View {
1818
@State private var pushNotificationListViewCoordinator: PushNotificationListViewCoordinator
1919
@State private var profileViewCoordinator: ProfileViewCoordinator
2020
@Binding var selectedTab: MainTab?
21+
private let windowEvent: TodoEditorWindowEvent
2122

2223
init(
2324
container: DIContainer,
25+
windowEvent: TodoEditorWindowEvent,
2426
selectedTab: Binding<MainTab?>
2527
) {
2628
self._coordinator = State(initialValue: MainViewCoordinator(container: container))
@@ -31,6 +33,7 @@ struct MainView: View {
3133
initialValue: PushNotificationListViewCoordinator(container: container)
3234
)
3335
self._profileViewCoordinator = State(initialValue: ProfileViewCoordinator(container: container))
36+
self.windowEvent = windowEvent
3437
self._selectedTab = selectedTab
3538
}
3639

@@ -46,6 +49,8 @@ struct MainView: View {
4649
}
4750
.onAppear {
4851
coordinator.viewModel.send(.onAppear)
52+
homeViewCoordinator.bindWindowEvent(windowEvent)
53+
todoWindowCoordinator.bindWindowEvent(windowEvent)
4954
}
5055
.onChange(of: selectedTab, initial: true) { _, newValue in
5156
guard let newValue else { return }

Application/DevLogPresentation/Sources/Root/RootView.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public struct RootView: View {
1616
@State private var selectedRoute: Route?
1717
@State private var selectedMainTab: MainTab?
1818
private let widgetURLTab: (URL) -> MainTab?
19+
private let windowEvent: TodoEditorWindowEvent
1920
private let pushNotificationTodoIdPublisher: AnyPublisher<String, Never>
2021
private let clearPushNotificationRoute: () -> Void
2122

@@ -25,6 +26,7 @@ public struct RootView: View {
2526
systemThemeUseCase: ObserveSystemThemeUseCase,
2627
trackAnalyticsEventUseCase: TrackAnalyticsEventUseCase,
2728
widgetURLTab: @escaping (URL) -> MainTab?,
29+
windowEvent: TodoEditorWindowEvent,
2830
pushNotificationTodoIdPublisher: AnyPublisher<String, Never>,
2931
clearPushNotificationRoute: @escaping () -> Void
3032
) {
@@ -35,6 +37,7 @@ public struct RootView: View {
3537
trackAnalyticsEventUseCase: trackAnalyticsEventUseCase
3638
))
3739
self.widgetURLTab = widgetURLTab
40+
self.windowEvent = windowEvent
3841
self.pushNotificationTodoIdPublisher = pushNotificationTodoIdPublisher
3942
self.clearPushNotificationRoute = clearPushNotificationRoute
4043
}
@@ -46,6 +49,7 @@ public struct RootView: View {
4649
if signIn {
4750
MainView(
4851
container: container,
52+
windowEvent: windowEvent,
4953
selectedTab: $selectedMainTab
5054
)
5155
} else {

0 commit comments

Comments
 (0)