Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 22 additions & 39 deletions DevLog/Presentation/ViewModel/PushNotificationListViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@ final class PushNotificationListViewModel: Store {
var showAlert: Bool = false
var showToast: Bool = false
var alertTitle: String = ""
var alertType: AlertType?
var alertMessage: String = ""
var toastMessage: String = ""
var toastType: ToastType?
var isLoading: Bool = false
var hasMore: Bool = false
var nextCursor: PushNotificationCursor?
Expand All @@ -32,8 +30,8 @@ final class PushNotificationListViewModel: Store {
case toggleRead(PushNotification)
case undoDelete
case confirmDelete
case setAlert(isPresented: Bool, type: AlertType? = nil)
case setToast(isPresented: Bool, type: ToastType? = nil)
case setAlert(isPresented: Bool)
case setToast(isPresented: Bool)
case setLoading(Bool)
case appendNotifications([PushNotification], nextCursor: PushNotificationCursor?)
case resetPagination
Expand All @@ -52,14 +50,6 @@ final class PushNotificationListViewModel: Store {
case toggleRead(String)
}

enum AlertType {
case error
}

enum ToastType {
case delete
}

@Published private(set) var state: State
private let fetchUseCase: FetchPushNotificationsUseCase
private let deleteUseCase: DeletePushNotificationUseCase
Expand Down Expand Up @@ -128,7 +118,7 @@ final class PushNotificationListViewModel: Store {
let hasMore = page.items.count == query.pageSize && page.nextCursor != nil
send(.setHasMore(hasMore))
} catch {
send(.setAlert(isPresented: true, type: .error))
send(.setAlert(isPresented: true))
}

}
Expand All @@ -139,7 +129,7 @@ final class PushNotificationListViewModel: Store {
send(.setLoading(true))
try await deleteUseCase.execute(notification.id)
} catch {
send(.setAlert(isPresented: true, type: .error))
send(.setAlert(isPresented: true))
}
}
case .toggleRead(let todoID):
Expand All @@ -149,7 +139,7 @@ final class PushNotificationListViewModel: Store {
send(.setLoading(true))
try await toggleReadUseCase.execute(todoID)
} catch {
send(.setAlert(isPresented: true, type: .error))
send(.setAlert(isPresented: true))
}
}
}
Expand All @@ -161,11 +151,18 @@ private extension PushNotificationListViewModel {
func reduceByUser(_ action: Action, state: inout State) -> [SideEffect] {
switch action {
case .deleteNotification(let item):
var effects: [SideEffect] = []
if let (pendingItem, _) = state.pendingTask {
effects = [.delete(pendingItem)]
}

if let index = state.notifications.firstIndex(where: { $0.id == item.id }) {
state.pendingTask = (item, index)
state.notifications.remove(at: index)
setToast(&state, isPresented: true, for: .delete)
setToast(&state, isPresented: true)
}

return effects
case .toggleRead(let item):
if let index = state.notifications.firstIndex(where: { $0.id == item.id }) {
state.notifications[index].isRead.toggle()
Expand All @@ -175,8 +172,8 @@ private extension PushNotificationListViewModel {
guard let (item, index) = state.pendingTask else { return [] }
state.notifications.insert(item, at: index)
state.pendingTask = nil
case .setAlert(let isPresented, let type):
setAlert(&state, isPresented: isPresented, for: type)
case .setAlert(let isPresented):
setAlert(&state, isPresented: isPresented)
case .toggleSortOption:
state.query.sortOrder = state.query.sortOrder == .latest ? .oldest : .latest
updateQueryUseCase.execute(state.query)
Expand Down Expand Up @@ -221,8 +218,8 @@ private extension PushNotificationListViewModel {
guard let (item, _) = state.pendingTask else { return [] }
state.pendingTask = nil
return [.delete(item)]
case .setToast(let isPresented, let type):
setToast(&state, isPresented: isPresented, for: type)
case .setToast(let isPresented):
setToast(&state, isPresented: isPresented)
case .setSelectedTodoID(let todoID):
state.selectedTodoID = todoID
default:
Expand Down Expand Up @@ -259,32 +256,18 @@ private extension PushNotificationListViewModel {
private extension PushNotificationListViewModel {
func setAlert(
_ state: inout State,
isPresented: Bool,
for type: AlertType?
isPresented: Bool
) {
switch type {
case .error:
state.alertTitle = "오류"
state.alertMessage = "문제가 발생했습니다. 잠시 후 다시 시도해주세요."
case .none:
state.alertTitle = ""
state.alertMessage = ""
}
state.alertType = type
state.alertTitle = "오류"
state.alertMessage = "문제가 발생했습니다. 잠시 후 다시 시도해주세요."
state.showAlert = isPresented
Comment on lines +261 to 263

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Alert가 사라질 때 관련 상태(alertTitle, alertMessage)를 초기화하는 로직이 누락되었습니다. Alert가 다시 표시될 때 이전 메시지가 잠시 보이는 문제를 방지하기 위해 isPresentedfalse일 때 메시지를 비워주는 것이 좋습니다.

Suggested change
state.alertTitle = "오류"
state.alertMessage = "문제가 발생했습니다. 잠시 후 다시 시도해주세요."
state.showAlert = isPresented
state.alertTitle = isPresented ? "오류" : ""
state.alertMessage = isPresented ? "문제가 발생했습니다. 잠시 후 다시 시도해주세요." : ""
state.showAlert = isPresented

}
Comment on lines 257 to 264

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

setAlert 함수가 isPresented 값에 관계없이 항상 alertTitlealertMessage를 설정하고 있습니다. 얼럿이 사라질 때(isPresentedfalse일 때)는 메시지를 설정할 필요가 없으며, 이전 구현처럼 메시지를 비워주는 것이 상태 관리에 더 안전합니다. isPresented 값에 따라 분기하여 처리하도록 수정하는 것을 제안합니다.

    func setAlert(
        _ state: inout State,
        isPresented: Bool
    ) {
        if isPresented {
            state.alertTitle = "오류"
            state.alertMessage = "문제가 발생했습니다. 잠시 후 다시 시도해주세요."
        } else {
            state.alertTitle = ""
            state.alertMessage = ""
        }
        state.showAlert = isPresented
    }


func setToast(
_ state: inout State,
isPresented: Bool,
for type: ToastType?
isPresented: Bool
) {
switch type {
case .delete:
state.toastMessage = "실행 취소"
case .none:
state.toastMessage = ""
}
state.toastMessage = "실행 취소"
state.showToast = isPresented
Comment on lines +270 to 271

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Toast가 사라질 때 toastMessage를 초기화하는 로직이 누락되었습니다. isPresentedfalse일 때 메시지를 비워주어 상태를 명확하게 관리하는 것이 좋습니다.

Suggested change
state.toastMessage = "실행 취소"
state.showToast = isPresented
state.toastMessage = isPresented ? "실행 취소" : ""
state.showToast = isPresented

}
Comment on lines 266 to 272

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

setToast 함수도 setAlert와 유사하게, isPresented 값에 관계없이 항상 toastMessage를 설정하고 있습니다. 토스트가 사라질 때(isPresentedfalse일 때)는 메시지를 비워주는 것이 상태 관리에 더 좋습니다. 삼항 연산자를 사용하여 코드를 간결하게 수정하는 것을 제안합니다.

    func setToast(
        _ state: inout State,
        isPresented: Bool
    ) {
        state.toastMessage = isPresented ? "실행 취소" : ""
        state.showToast = isPresented
    }

}
Expand Down
11 changes: 6 additions & 5 deletions DevLog/Presentation/ViewModel/TodoListViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,13 @@ private extension TodoListViewModel {
if let (pendingItem, _) = state.pendingTask {
effects = [.delete(pendingItem.id)]
}
guard let index = state.todos.firstIndex(where: { $0.id == todo.id }) else {
return []

if let index = state.todos.firstIndex(where: { $0.id == todo.id }) {
state.pendingTask = (todo, index)
state.todos.remove(at: index)
setToast(&state, isPresented: true)
}
state.pendingTask = (todo, index)
state.todos.remove(at: index)
setToast(&state, isPresented: true)

return effects
case .tapFilterOption(let option):
state.filterOption = option
Expand Down