From 5e722788470806ed6ecfbd5ba853bafea75e38a8 Mon Sep 17 00:00:00 2001 From: dlrjswns Date: Fri, 21 Aug 2026 15:39:48 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[FEAT]=20=EC=A0=84=EC=B2=B4=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EC=8B=9C=20CardShredView=EB=A1=9C=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Archive/Detail/ArchiveDetailView.swift | 57 +++++++------------ .../CardShred/CardShredView.swift | 15 ++++- .../CardShred/CardShredViewModel.swift | 28 +++++++-- 3 files changed, 59 insertions(+), 41 deletions(-) diff --git a/GAMSS/Sources/Presentation/Archive/Detail/ArchiveDetailView.swift b/GAMSS/Sources/Presentation/Archive/Detail/ArchiveDetailView.swift index bf2475e..0c5e03a 100644 --- a/GAMSS/Sources/Presentation/Archive/Detail/ArchiveDetailView.swift +++ b/GAMSS/Sources/Presentation/Archive/Detail/ArchiveDetailView.swift @@ -13,7 +13,7 @@ struct ArchiveDetailView: View { @StateObject private var viewModel: ArchiveDetailViewModel @State private var scene = DropStackScene() @State private var isMonthPickerPresented = false - @State private var isDeleteAllModalPresented = false + @State private var isShredPresented = false @State private var selectedNote: DropNote? private let title: String @@ -102,44 +102,29 @@ struct ArchiveDetailView: View { ), onClose: { selectedNote = nil + Task { await viewModel.load() } } ) .presentationBackground(.clear) } - if isDeleteAllModalPresented { - ModalContainerView( - isPresented: $isDeleteAllModalPresented - ) { - ModalContentView( - title: "대화 전체 비우기", - subtitle: "모든 대화 기록이 삭제돼요.\n삭제한 내용은 다시 복구할 수 없어요.", - actions: [ - .init( - title: "취소", - style: .secondary, - action: { - isDeleteAllModalPresented = false - } - ), - .init( - title: "비우기", - style: .destructive, - action: { - isDeleteAllModalPresented = false - - Task { - let success = await viewModel.deleteAll() - - if success { - viewModel.clearNotes() - scene.clear() - } - } - } - ) - ] - ) - } + .fullScreenCover(isPresented: $isShredPresented) { + CardShredView( + viewModel: CardShredViewModel( + deleteAllCardUseCase: DefaultDeleteAllCardUseCase( + cardRepository: DefaultCardRepository(networkManager: NetworkManager.shared) + ) + ), + stripImageName: "noteStrip", + onBack: { + isShredPresented = false + }, + onComplete: { + isShredPresented = false + viewModel.clearNotes() + scene.clear() + Task { await viewModel.load() } + } + ) } } } @@ -160,7 +145,7 @@ struct ArchiveDetailView: View { Spacer() Button { - isDeleteAllModalPresented = true + isShredPresented = true } label: { Text("비우기") .typography(.body5Medium) diff --git a/GAMSS/Sources/Presentation/CardShred/CardShredView.swift b/GAMSS/Sources/Presentation/CardShred/CardShredView.swift index 10fb82a..e92c28a 100644 --- a/GAMSS/Sources/Presentation/CardShred/CardShredView.swift +++ b/GAMSS/Sources/Presentation/CardShred/CardShredView.swift @@ -190,7 +190,7 @@ private struct ShredStrip: Identifiable { let height: CGFloat } -#Preview { +#Preview("단일 삭제") { CardShredView( viewModel: CardShredViewModel( cardId: 1, @@ -203,3 +203,16 @@ private struct ShredStrip: Identifiable { onComplete: {} ) } + +#Preview("전체 삭제") { + CardShredView( + viewModel: CardShredViewModel( + deleteAllCardUseCase: DefaultDeleteAllCardUseCase( + cardRepository: DefaultCardRepository(networkManager: NetworkManager.shared) + ) + ), + stripImageName: "noteStrip", + onBack: {}, + onComplete: {} + ) +} diff --git a/GAMSS/Sources/Presentation/CardShred/CardShredViewModel.swift b/GAMSS/Sources/Presentation/CardShred/CardShredViewModel.swift index 074b31a..bd8594c 100644 --- a/GAMSS/Sources/Presentation/CardShred/CardShredViewModel.swift +++ b/GAMSS/Sources/Presentation/CardShred/CardShredViewModel.swift @@ -8,19 +8,32 @@ import Combine import Foundation +enum CardShredMode { + case single(cardId: Int) + case all +} + @MainActor final class CardShredViewModel: ObservableObject { @Published private(set) var step = 0 @Published private(set) var isSubmitting = false @Published var alertMessage: String? - private let cardId: Int - private let deleteCardUseCase: DeleteCardUseCase + private let mode: CardShredMode + private let deleteCardUseCase: DeleteCardUseCase? + private let deleteAllCardUseCase: DeleteAllCardUseCase? private let requiredSteps = 4 init(cardId: Int, deleteCardUseCase: DeleteCardUseCase) { - self.cardId = cardId + self.mode = .single(cardId: cardId) self.deleteCardUseCase = deleteCardUseCase + self.deleteAllCardUseCase = nil + } + + init(deleteAllCardUseCase: DeleteAllCardUseCase) { + self.mode = .all + self.deleteCardUseCase = nil + self.deleteAllCardUseCase = deleteAllCardUseCase } var isPowerOn: Bool { @@ -48,7 +61,14 @@ final class CardShredViewModel: ObservableObject { defer { isSubmitting = false } do { - try await deleteCardUseCase.execute(cardId: cardId) + switch mode { + case .single(let cardId): + guard let deleteCardUseCase else { return false } + try await deleteCardUseCase.execute(cardId: cardId) + case .all: + guard let deleteAllCardUseCase else { return false } + try await deleteAllCardUseCase.execute() + } return true } catch { alertMessage = "기록을 파쇄하지 못했어요" From 6bdcc8dea9fb1de7d348c92b3720f9ffb87de966 Mon Sep 17 00:00:00 2001 From: dlrjswns Date: Fri, 21 Aug 2026 17:14:29 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[FEAT]=20=EB=B3=B4=EA=B4=80=ED=95=A8?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20=EC=84=A4=EC=A0=95=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EC=95=A1=EC=85=98=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GAMSS/Sources/Presentation/Archive/ArchiveView.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/GAMSS/Sources/Presentation/Archive/ArchiveView.swift b/GAMSS/Sources/Presentation/Archive/ArchiveView.swift index dedea17..e97ebe5 100644 --- a/GAMSS/Sources/Presentation/Archive/ArchiveView.swift +++ b/GAMSS/Sources/Presentation/Archive/ArchiveView.swift @@ -9,6 +9,7 @@ import SwiftUI struct ArchiveView: View { @StateObject private var viewModel: ArchiveViewModel + @State private var isSettingPresented = false init(viewModel: ArchiveViewModel) { _viewModel = StateObject(wrappedValue: viewModel) @@ -33,6 +34,8 @@ struct ArchiveView: View { } } .background(Color.colorWhite) + }.navigationDestination(isPresented: $isSettingPresented) { + SettingView().toolbar(.hidden, for: .tabBar) } } } @@ -48,7 +51,7 @@ private extension ArchiveView { Spacer() Button { - + isSettingPresented = true } label: { Image("gear") .resizable()