Skip to content

Commit 602f80b

Browse files
authored
[#275] 토스트를 통해 undo 액션이 구현되어 있을 경우 서버사이드로 책임을 이관하도록 개선한다 (#276)
* refactor: 푸시알림 데이터를 undo 하는 역할을 서버 사이드로 이관 * feat: 삭제 실패 시 원복하는 기능 추가 * style: normalizeError 메서드 모듈화 * refactor: 웹페이지 데이터를 undo 하는 역할을 서버 사이드로 이관 * style: 더 적합한 변수명 / 액션명으로 수정 * refactor: undo 실패 여부와 상관없이 fetch가 호출되도록 개선 * refactor: 코드 개선 및 webPageSection에서는 렌더링 강제 * style: 불필요 코드 제거 * style: 변수명 수정 * refactor: 삭제 후 fetch하도록 개선 * style: id의 혼선 개선
1 parent 88f88a3 commit 602f80b

23 files changed

Lines changed: 717 additions & 124 deletions

DevLog/App/Assembler/DomainAssembler.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ private extension DomainAssembler {
9595
DeletePushNotificationUseCaseImpl(container.resolve(PushNotificationRepository.self))
9696
}
9797

98+
container.register(UndoDeletePushNotificationUseCase.self) {
99+
UndoDeletePushNotificationUseCaseImpl(container.resolve(PushNotificationRepository.self))
100+
}
101+
98102
container.register(FetchPushNotificationsUseCase.self) {
99103
FetchPushNotificationsUseCaseImpl(container.resolve(PushNotificationRepository.self))
100104
}
@@ -116,6 +120,10 @@ private extension DomainAssembler {
116120
container.register(DeleteWebPageUseCase.self) {
117121
DeleteWebPageUseCaseImpl(container.resolve(WebPageRepository.self))
118122
}
123+
124+
container.register(UndoDeleteWebPageUseCase.self) {
125+
UndoDeleteWebPageUseCaseImpl(container.resolve(WebPageRepository.self))
126+
}
119127
}
120128

121129
func registerUserPreferencesUseCases(_ container: DIContainer) {

DevLog/Data/Repository/PushNotificationRepositoryImpl.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ final class PushNotificationRepositoryImpl: PushNotificationRepository {
5656
try await service.deleteNotification(notificationID)
5757
}
5858

59+
func undoDeleteNotification(_ notificationID: String) async throws {
60+
try await service.undoDeleteNotification(notificationID)
61+
}
62+
5963
// 푸시 알림 읽음/안읽음 토글
6064
func toggleNotificationRead(_ todoId: String) async throws {
6165
try await service.toggleNotificationRead(todoId)

DevLog/Data/Repository/WebPageRepositoryImpl.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ final class WebPageRepositoryImpl: WebPageRepository {
5757
try await webPageService.deleteWebPage(urlString)
5858
await metadataService.removeCachedImage(for: urlString)
5959
}
60+
61+
func undoDelete(_ urlString: String) async throws {
62+
try await webPageService.undoDeleteWebPage(urlString)
63+
}
6064
}
6165

6266
private extension WebPageRepositoryImpl {

DevLog/Domain/Protocol/PushNotificationRepository.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ protocol PushNotificationRepository {
2121
limit: Int
2222
) throws -> AnyPublisher<PushNotificationPage, Error>
2323
func deleteNotification(_ notificationID: String) async throws
24+
func undoDeleteNotification(_ notificationID: String) async throws
2425
func toggleNotificationRead(_ todoId: String) async throws
2526
}

DevLog/Domain/Protocol/WebPageRepository.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ protocol WebPageRepository {
99
func fetch(_ query: String) async throws -> [WebPage]
1010
func upsert(_ urlString: String) async throws
1111
func delete(_ urlString: String) async throws
12+
func undoDelete(_ urlString: String) async throws
1213
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//
2+
// UndoDeletePushNotificationUseCase.swift
3+
// DevLog
4+
//
5+
// Created by opfic on 3/16/26.
6+
//
7+
8+
protocol UndoDeletePushNotificationUseCase {
9+
func execute(_ notificationID: String) async throws
10+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//
2+
// UndoDeletePushNotificationUseCaseImpl.swift
3+
// DevLog
4+
//
5+
// Created by opfic on 3/16/26.
6+
//
7+
8+
final class UndoDeletePushNotificationUseCaseImpl: UndoDeletePushNotificationUseCase {
9+
private let repository: PushNotificationRepository
10+
11+
init(_ repository: PushNotificationRepository) {
12+
self.repository = repository
13+
}
14+
15+
func execute(_ notificationID: String) async throws {
16+
try await repository.undoDeleteNotification(notificationID)
17+
}
18+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//
2+
// UndoDeleteWebPageUseCase.swift
3+
// DevLog
4+
//
5+
// Created by opfic on 3/16/26.
6+
//
7+
8+
protocol UndoDeleteWebPageUseCase {
9+
func execute(_ urlString: String) async throws
10+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//
2+
// UndoDeleteWebPageUseCaseImpl.swift
3+
// DevLog
4+
//
5+
// Created by opfic on 3/16/26.
6+
//
7+
8+
final class UndoDeleteWebPageUseCaseImpl: UndoDeleteWebPageUseCase {
9+
private let repository: WebPageRepository
10+
11+
init(_ repository: WebPageRepository) {
12+
self.repository = repository
13+
}
14+
15+
func execute(_ urlString: String) async throws {
16+
try await repository.undoDelete(urlString)
17+
}
18+
}

DevLog/Infra/Service/PushNotificationService.swift

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,16 @@
88
import FirebaseAuth
99
import Combine
1010
import FirebaseFirestore
11+
import FirebaseFunctions
1112

1213
final class PushNotificationService {
14+
private enum FunctionName: String {
15+
case requestPushNotificationDeletion
16+
case undoPushNotificationDeletion
17+
}
18+
1319
private let store = Firestore.firestore()
20+
private let functions = Functions.functions(region: "asia-northeast3")
1421
private let logger = Logger(category: "PushNotificationService")
1522

1623
/// 푸시 알림 On/Off 설정
@@ -174,13 +181,24 @@ final class PushNotificationService {
174181
/// 푸시 알림 기록 삭제
175182
func deleteNotification(_ notificationID: String) async throws {
176183
do {
177-
guard let uid = Auth.auth().currentUser?.uid else { throw AuthError.notAuthenticated }
184+
guard Auth.auth().currentUser?.uid != nil else { throw AuthError.notAuthenticated }
178185

179-
let docRef = store.collection("users/\(uid)/notifications").document(notificationID)
186+
let function = functions.httpsCallable(FunctionName.requestPushNotificationDeletion)
187+
_ = try await function.call(["notificationId": notificationID])
188+
} catch {
189+
logger.error("Failed to request notification deletion", error: error)
190+
throw error
191+
}
192+
}
193+
194+
func undoDeleteNotification(_ notificationID: String) async throws {
195+
do {
196+
guard Auth.auth().currentUser?.uid != nil else { throw AuthError.notAuthenticated }
180197

181-
try await docRef.delete()
198+
let function = functions.httpsCallable(FunctionName.undoPushNotificationDeletion)
199+
_ = try await function.call(["notificationId": notificationID])
182200
} catch {
183-
logger.error("Failed to delete notification", error: error)
201+
logger.error("Failed to undo notification deletion", error: error)
184202
throw error
185203
}
186204
}

0 commit comments

Comments
 (0)