Skip to content

Commit 3c42501

Browse files
committed
refactor: 불필요 액션 제거 및 비슷한 액션 집합 생성 후 정리
1 parent 56e8e89 commit 3c42501

2 files changed

Lines changed: 114 additions & 102 deletions

File tree

DevLog/Presentation/ViewModel/HomeViewModel.swift

Lines changed: 106 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ final class HomeViewModel: Store {
1818
var showSearchView: Bool = false
1919
var webPageURLInput: String = "https://"
2020
var selectedTodoKind: TodoKind?
21-
var searchText: String = ""
22-
var isSearching: Bool = false
2321
var reorderTodo: Bool = false
2422
var isRecentTodosLoading: Bool = false
2523
var isWebPageLoading: Bool = false
@@ -34,28 +32,21 @@ final class HomeViewModel: Store {
3432
}
3533

3634
enum Action {
35+
case onAppear
36+
case setPresentation(Presentation, Bool)
37+
case setAlert(isPresented: Bool, type: AlertType? = nil)
38+
case setToast(isPresented: Bool, type: ToastType? = nil)
39+
case setLoading(LoadingTarget, Bool)
3740
case tapTodoKind(TodoKind)
3841
case orderTodoKindPreferences([TodoKindPreference])
39-
case setReorderTodo(Bool)
40-
case setShowTodoEditor(Bool)
41-
case setShowContentPicker(Bool)
42-
case setShowSearchView(Bool)
43-
case setAlert(isPresented: Bool, type: AlertType? = nil)
44-
case onAppear
45-
case updateWebPageURLInput(String)
46-
case updateSearching(Bool)
47-
case updateSearchText(String)
4842
case addTodo(Todo)
43+
case updateRecentTodos([RecentTodoItem])
44+
case updateWebPageURLInput(String)
4945
case addWebPage
5046
case deleteWebPage(WebPageItem)
5147
case undoDeleteWebPage
52-
case setToast(isPresented: Bool, type: ToastType? = nil)
53-
case fetchRecentTodos([RecentTodoItem])
54-
case fetchWebPages([WebPageItem])
48+
case updateWebPages([WebPageItem])
5549
case restoreWebPage(WebPageItem, Int)
56-
case setRecentTodosLoading(Bool)
57-
case setWebPageLoading(Bool)
58-
case setAppending(Bool)
5950
}
6051

6152
enum SideEffect {
@@ -83,6 +74,19 @@ final class HomeViewModel: Store {
8374
case urlInputAlert
8475
}
8576

77+
enum Presentation {
78+
case reorderTodo
79+
case todoEditor
80+
case contentPicker
81+
case searchView
82+
}
83+
84+
enum LoadingTarget {
85+
case recentTodos
86+
case webPage
87+
case overlay
88+
}
89+
8690
private(set) var state = State()
8791
private let upsertTodoUseCase: UpsertTodoUseCase
8892
private let addWebPageUseCase: AddWebPageUseCase
@@ -113,17 +117,12 @@ final class HomeViewModel: Store {
113117
var effects: [SideEffect] = []
114118

115119
switch action {
116-
case .tapTodoKind, .orderTodoKindPreferences, .setReorderTodo,
117-
.setShowTodoEditor, .setShowContentPicker, .setShowSearchView,
118-
.updateWebPageURLInput, .setAlert, .deleteWebPage,
119-
.undoDeleteWebPage, .setToast:
120-
effects = reduceByUser(action, state: &state)
121-
122-
case .onAppear, .updateSearching, .updateSearchText, .addTodo, .addWebPage:
120+
case .onAppear, .setPresentation, .setAlert, .setToast, .tapTodoKind,
121+
.orderTodoKindPreferences, .addTodo, .updateWebPageURLInput,
122+
.addWebPage, .deleteWebPage, .undoDeleteWebPage:
123123
effects = reduceByView(action, state: &state)
124124

125-
case .fetchRecentTodos, .fetchWebPages, .restoreWebPage, .setRecentTodosLoading,
126-
.setWebPageLoading, .setAppending:
125+
case .setLoading, .updateRecentTodos, .updateWebPages, .restoreWebPage:
127126
effects = reduceByRun(action, state: &state)
128127
}
129128

@@ -136,50 +135,51 @@ final class HomeViewModel: Store {
136135
case .addTodo(let todo):
137136
Task {
138137
do {
139-
send(.setAppending(true))
138+
defer { send(.setLoading(.overlay, false)) }
139+
send(.setLoading(.overlay, true))
140140
try await upsertTodoUseCase.execute(todo)
141141
let page = try await fetchRecentTodos()
142142
let items = page.items
143143
.filter { $0.createdAt != $0.updatedAt }
144144
.prefix(5)
145145
.map { RecentTodoItem(from: $0) }
146-
send(.fetchRecentTodos(items))
146+
send(.updateRecentTodos(items))
147147
} catch {
148148
send(.setAlert(isPresented: true, type: .error))
149149
}
150150
}
151151
case .fetchRecentTodos:
152152
Task {
153153
do {
154-
defer { send(.setRecentTodosLoading(false)) }
155-
send(.setRecentTodosLoading(true))
154+
defer { send(.setLoading(.recentTodos, false)) }
155+
send(.setLoading(.recentTodos, true))
156156
let page = try await fetchRecentTodos()
157157
let items = page.items
158158
.filter { $0.createdAt != $0.updatedAt }
159159
.prefix(5)
160160
.map { RecentTodoItem(from: $0) }
161-
send(.fetchRecentTodos(items))
161+
send(.updateRecentTodos(items))
162162
} catch {
163163
send(.setAlert(isPresented: true, type: .error))
164164
}
165165
}
166166
case .addWebPage(let urlString):
167167
Task {
168168
do {
169-
defer { send(.setAppending(false)) }
170-
send(.setAppending(true))
169+
defer { send(.setLoading(.overlay, false)) }
170+
send(.setLoading(.overlay, true))
171171
try await addWebPageUseCase.execute(urlString)
172172
let pages = try await fetchWebPagesUseCase.execute("")
173-
send(.fetchWebPages(pages.map { WebPageItem(from: $0) }))
173+
send(.updateWebPages(pages.map { WebPageItem(from: $0) }))
174174
} catch {
175175
send(.setAlert(isPresented: true, type: .error))
176176
}
177177
}
178178
case .deleteWebPage(let page, let index):
179179
Task {
180180
do {
181-
defer { send(.setWebPageLoading(false)) }
182-
send(.setWebPageLoading(true))
181+
defer { send(.setLoading(.webPage, false)) }
182+
send(.setLoading(.webPage, true))
183183
try await deleteWebPageUseCase.execute(page.url.absoluteString)
184184
} catch {
185185
send(.restoreWebPage(page, index))
@@ -188,8 +188,8 @@ final class HomeViewModel: Store {
188188
}
189189
case .undoDeleteWebPage(let urlString):
190190
Task {
191-
defer { send(.setWebPageLoading(false)) }
192-
send(.setWebPageLoading(true))
191+
defer { send(.setLoading(.webPage, false)) }
192+
send(.setLoading(.webPage, true))
193193

194194
var shouldPresentError = false
195195

@@ -201,7 +201,7 @@ final class HomeViewModel: Store {
201201

202202
do {
203203
let pages = try await fetchWebPagesUseCase.execute("")
204-
send(.fetchWebPages(pages.map { WebPageItem(from: $0) }))
204+
send(.updateWebPages(pages.map { WebPageItem(from: $0) }))
205205
} catch {
206206
shouldPresentError = true
207207
}
@@ -213,10 +213,10 @@ final class HomeViewModel: Store {
213213
case .fetchWebPages:
214214
Task {
215215
do {
216-
defer { send(.setWebPageLoading(false)) }
217-
send(.setWebPageLoading(true))
216+
defer { send(.setLoading(.webPage, false)) }
217+
send(.setLoading(.webPage, true))
218218
let pages = try await fetchWebPagesUseCase.execute("")
219-
send(.fetchWebPages(pages.map { WebPageItem(from: $0) }))
219+
send(.updateWebPages(pages.map { WebPageItem(from: $0) }))
220220
} catch {
221221
send(.setAlert(isPresented: true, type: .error))
222222
}
@@ -226,7 +226,7 @@ final class HomeViewModel: Store {
226226
try await Task.sleep(for: .seconds(0.1))
227227
switch type {
228228
case .todoEditor:
229-
send(.setShowTodoEditor(true))
229+
send(.setPresentation(.todoEditor, true))
230230
case .urlInputAlert:
231231
send(.setAlert(isPresented: true, type: .webPageInput))
232232
}
@@ -237,81 +237,66 @@ final class HomeViewModel: Store {
237237

238238
// MARK: - Reduce Methods
239239
private extension HomeViewModel {
240-
func reduceByUser(_ action: Action, state: inout State) -> [SideEffect] {
240+
// swiftlint:disable cyclomatic_complexity
241+
func reduceByView(_ action: Action, state: inout State) -> [SideEffect] {
241242
switch action {
242-
case .tapTodoKind(let kind):
243-
state.selectedTodoKind = kind
244-
state.showContentPicker = false
245-
return [.showModalAfterDelay(.todoEditor)]
246-
case .orderTodoKindPreferences(let preferences):
247-
state.todoKindPreferences = preferences
248-
case .setReorderTodo(let presented):
249-
state.reorderTodo = presented
250-
case .setShowTodoEditor(let presented):
251-
state.showTodoEditor = presented
252-
if !presented { state.selectedTodoKind = nil }
253-
case .setShowContentPicker(let presented):
254-
state.showContentPicker = presented
255-
case .setShowSearchView(let presented):
256-
state.showSearchView = presented
257-
case .updateWebPageURLInput(let text):
258-
state.webPageURLInput = text
243+
case .onAppear:
244+
return [.fetchRecentTodos, .fetchWebPages]
245+
case .setPresentation(let presentation, let isPresented):
246+
setPresentation(&state, presentation: presentation, isPresented: isPresented)
259247
case .setAlert(let presented, let type):
260248
if presented && type == .webPageInput && state.showContentPicker {
261249
state.showContentPicker = false
262250
return [.showModalAfterDelay(.urlInputAlert)]
263251
}
264252
setAlert(&state, isPresented: presented, type: type)
265-
case .deleteWebPage(let page):
266-
if let index = state.webPages.firstIndex(where: { $0.id == page.id }) {
267-
deletedWebPageURLString = page.url.absoluteString
268-
state.webPages.remove(at: index)
269-
setToast(&state, isPresented: true, for: .deleteWebPage)
270-
return [.deleteWebPage(page, index)]
271-
}
272-
case .undoDeleteWebPage:
273-
guard let deletedWebPageURLString else { return [] }
274-
self.deletedWebPageURLString = nil
275-
return [.undoDeleteWebPage(deletedWebPageURLString)]
276253
case .setToast(let isPresented, let type):
277254
setToast(&state, isPresented: isPresented, for: type)
278255
if !isPresented {
279256
deletedWebPageURLString = nil
280257
}
281-
default:
282-
break
283-
}
284-
return []
285-
}
286-
287-
func reduceByView(_ action: Action, state: inout State) -> [SideEffect] {
288-
switch action {
289-
case .onAppear:
290-
return [.fetchRecentTodos, .fetchWebPages]
291-
case .updateSearching(let isSearching):
292-
state.isSearching = isSearching
293-
case .updateSearchText(let text):
294-
state.searchText = text
258+
case .tapTodoKind(let kind):
259+
state.selectedTodoKind = kind
260+
state.showContentPicker = false
261+
return [.showModalAfterDelay(.todoEditor)]
262+
case .orderTodoKindPreferences(let preferences):
263+
state.todoKindPreferences = preferences
295264
case .addTodo(let todo):
296265
return [.addTodo(todo)]
266+
case .updateWebPageURLInput(let text):
267+
state.webPageURLInput = text
297268
case .addWebPage:
298269
guard let normalizedURL = normalizedWebPageURL(state.webPageURLInput) else {
299270
setAlert(&state, isPresented: true, type: .invalidURL)
300271
return []
301272
}
302273
setAlert(&state, isPresented: false, type: nil)
303274
return [.addWebPage(normalizedURL)]
275+
case .deleteWebPage(let page):
276+
if let index = state.webPages.firstIndex(where: { $0.id == page.id }) {
277+
deletedWebPageURLString = page.url.absoluteString
278+
state.webPages.remove(at: index)
279+
setToast(&state, isPresented: true, for: .deleteWebPage)
280+
return [.deleteWebPage(page, index)]
281+
}
282+
case .undoDeleteWebPage:
283+
guard let deletedWebPageURLString else { return [] }
284+
self.deletedWebPageURLString = nil
285+
return [.undoDeleteWebPage(deletedWebPageURLString)]
304286
default:
305287
break
306288
}
307289
return []
308290
}
291+
// swiftlint:enable cyclomatic_complexity
309292

310293
func reduceByRun(_ action: Action, state: inout State) -> [SideEffect] {
311294
switch action {
312-
case .fetchRecentTodos(let todos):
295+
case .setLoading(let loadingTarget, let isLoading):
296+
setLoading(&state, loadingTarget: loadingTarget, isLoading: isLoading)
297+
case .updateRecentTodos(let todos):
313298
state.recentTodos = todos
314-
case .fetchWebPages(let pages):
299+
case .updateWebPages(let pages):
315300
state.webPages = pages
316301
case .restoreWebPage(let page, let index):
317302
if state.webPages.contains(where: { $0.id == page.id }) { break }
@@ -323,12 +308,6 @@ private extension HomeViewModel {
323308
if deletedWebPageURLString == page.url.absoluteString {
324309
deletedWebPageURLString = nil
325310
}
326-
case .setRecentTodosLoading(let isLoading):
327-
state.isRecentTodosLoading = isLoading
328-
case .setWebPageLoading(let isLoading):
329-
state.isWebPageLoading = isLoading
330-
case .setAppending(let isLoading):
331-
state.isAppending = isLoading
332311
default:
333312
break
334313
}
@@ -338,6 +317,24 @@ private extension HomeViewModel {
338317

339318
// MARK: - Helper Methods
340319
private extension HomeViewModel {
320+
func setPresentation(
321+
_ state: inout State,
322+
presentation: Presentation,
323+
isPresented: Bool
324+
) {
325+
switch presentation {
326+
case .reorderTodo:
327+
state.reorderTodo = isPresented
328+
case .todoEditor:
329+
state.showTodoEditor = isPresented
330+
if !isPresented { state.selectedTodoKind = nil }
331+
case .contentPicker:
332+
state.showContentPicker = isPresented
333+
case .searchView:
334+
state.showSearchView = isPresented
335+
}
336+
}
337+
341338
func setAlert(
342339
_ state: inout State,
343340
isPresented: Bool,
@@ -377,6 +374,21 @@ private extension HomeViewModel {
377374
state.toastType = type
378375
}
379376

377+
func setLoading(
378+
_ state: inout State,
379+
loadingTarget: LoadingTarget,
380+
isLoading: Bool
381+
) {
382+
switch loadingTarget {
383+
case .recentTodos:
384+
state.isRecentTodosLoading = isLoading
385+
case .webPage:
386+
state.isWebPageLoading = isLoading
387+
case .overlay:
388+
state.isAppending = isLoading
389+
}
390+
}
391+
380392
func normalizedWebPageURL(_ input: String) -> String? {
381393
let trimmed = input.trimmingCharacters(in: .whitespacesAndNewlines)
382394
guard !trimmed.isEmpty else { return nil }

0 commit comments

Comments
 (0)