@@ -9,25 +9,30 @@ import Foundation
99import Combine
1010
1111final class PushNotificationRepositoryImpl : PushNotificationRepository {
12- private let service : PushNotificationService
12+ private let pushNotificationService : PushNotificationService
13+ private let todoCategoryService : TodoCategoryService
1314
14- init ( pushNotificationService: PushNotificationService ) {
15- self . service = pushNotificationService
15+ init (
16+ pushNotificationService: PushNotificationService ,
17+ todoCategoryService: TodoCategoryService
18+ ) {
19+ self . pushNotificationService = pushNotificationService
20+ self . todoCategoryService = todoCategoryService
1621 }
1722
1823 /// 푸시 알림 On/Off 설정
1924 func fetchPushNotificationEnabled( ) async throws -> Bool {
20- return try await service . fetchPushNotificationEnabled ( )
25+ return try await pushNotificationService . fetchPushNotificationEnabled ( )
2126 }
2227
2328 /// 푸시 알림 시간 설정
2429 func fetchPushNotificationTime( ) async throws -> DateComponents {
25- return try await service . fetchPushNotificationTime ( )
30+ return try await pushNotificationService . fetchPushNotificationTime ( )
2631 }
2732
2833 /// 푸시 알림 설정 업데이트
2934 func updatePushNotificationSettings( _ settings: PushNotificationSettings ) async throws {
30- try await service . updatePushNotificationSettings (
35+ try await pushNotificationService . updatePushNotificationSettings (
3136 isEnabled: settings. isEnabled, components: settings. scheduledTime
3237 )
3338 }
@@ -38,35 +43,133 @@ final class PushNotificationRepositoryImpl: PushNotificationRepository {
3843 cursor: PushNotificationCursor ?
3944 ) async throws -> PushNotificationPage {
4045 let cursorDTO = cursor. map { PushNotificationCursorDTO . fromDomain ( $0) }
41- let response = try await service. requestNotifications ( query, cursor: cursorDTO)
42- return try response. toDomain ( )
46+ async let responseTask = pushNotificationService. requestNotifications ( query, cursor: cursorDTO)
47+ async let preferencesTask = todoCategoryService. fetchPreferences ( )
48+
49+ let ( response, preferences) = try await ( responseTask, preferencesTask)
50+ let userTodoCategories : [ UserTodoCategory ] = preferences. compactMap { preference in
51+ guard case . user( let userTodoCategory) = preference. category else {
52+ return nil
53+ }
54+
55+ return userTodoCategory
56+ }
57+
58+ let responses = try response. items. map {
59+ try resolve ( $0, userTodoCategories: userTodoCategories)
60+ }
61+
62+ return try PushNotificationPageResponse (
63+ items: responses,
64+ nextCursor: response. nextCursor
65+ ) . toDomain ( )
4366 }
4467
4568 func observeNotifications(
4669 _ query: PushNotificationQuery ,
4770 limit: Int
4871 ) throws -> AnyPublisher < PushNotificationPage , Error > {
49- try service. observeNotifications ( query, limit: limit)
50- . tryMap { try $0. toDomain ( ) }
72+ let subject = PassthroughSubject < PushNotificationPage , Error > ( )
73+ var cancellable : AnyCancellable ?
74+
75+ cancellable = try pushNotificationService. observeNotifications ( query, limit: limit)
76+ . sink (
77+ receiveCompletion: { completion in
78+ switch completion {
79+ case . finished:
80+ subject. send ( completion: . finished)
81+ case . failure( let error) :
82+ subject. send ( completion: . failure( error) )
83+ }
84+ } ,
85+ receiveValue: { [ weak self] response in
86+ guard let self else { return }
87+
88+ Task {
89+ do {
90+ let preferences = try await self . todoCategoryService. fetchPreferences ( )
91+ let userTodoCategories : [ UserTodoCategory ] = preferences. compactMap { preference in
92+ guard case . user( let userTodoCategory) = preference. category else {
93+ return nil
94+ }
95+
96+ return userTodoCategory
97+ }
98+
99+ let responses = try response. items. map {
100+ try self . resolve ( $0, userTodoCategories: userTodoCategories)
101+ }
102+
103+ let page = try PushNotificationPageResponse (
104+ items: responses,
105+ nextCursor: response. nextCursor
106+ ) . toDomain ( )
107+
108+ subject. send ( page)
109+ } catch {
110+ subject. send ( completion: . failure( error) )
111+ }
112+ }
113+ }
114+ )
115+
116+ return subject
117+ . handleEvents ( receiveCancel: { cancellable? . cancel ( ) } )
51118 . eraseToAnyPublisher ( )
52119 }
53120
54121 func observeUnreadPushCount( ) throws -> AnyPublisher < Int , Error > {
55- try service . observeUnreadPushCount ( )
122+ try pushNotificationService . observeUnreadPushCount ( )
56123 . eraseToAnyPublisher ( )
57124 }
58125
59126 // 푸시 알림 기록 삭제
60127 func deleteNotification( _ notificationID: String ) async throws {
61- try await service . deleteNotification ( notificationID)
128+ try await pushNotificationService . deleteNotification ( notificationID)
62129 }
63130
64131 func undoDeleteNotification( _ notificationID: String ) async throws {
65- try await service . undoDeleteNotification ( notificationID)
132+ try await pushNotificationService . undoDeleteNotification ( notificationID)
66133 }
67134
68135 // 푸시 알림 읽음/안읽음 토글
69136 func toggleNotificationRead( _ todoId: String ) async throws {
70- try await service. toggleNotificationRead ( todoId)
137+ try await pushNotificationService. toggleNotificationRead ( todoId)
138+ }
139+ }
140+
141+ private extension PushNotificationRepositoryImpl {
142+ func resolve(
143+ _ response: PushNotificationResponse ,
144+ userTodoCategories: [ UserTodoCategory ]
145+ ) throws -> PushNotificationResponse {
146+ let categoryName : String
147+ switch response. todoCategory {
148+ case . raw( let rawValue) :
149+ categoryName = rawValue
150+ case . decoded:
151+ return response
152+ }
153+
154+ let todoCategory : TodoCategory
155+ if let systemTodoCategory = SystemTodoCategory ( rawValue: categoryName) {
156+ todoCategory = . system( systemTodoCategory)
157+ } else if let userTodoCategory = userTodoCategories. first ( where: {
158+ $0. name == categoryName
159+ } ) {
160+ todoCategory = . user( userTodoCategory)
161+ } else {
162+ throw DataError . invalidData ( " PushNotificationResponse.todoCategory is invalid: \( categoryName) " )
163+ }
164+
165+ return PushNotificationResponse (
166+ id: response. id,
167+ title: response. title,
168+ body: response. body,
169+ receivedAt: response. receivedAt,
170+ isRead: response. isRead,
171+ todoId: response. todoId,
172+ todoCategory: . decoded( todoCategory)
173+ )
71174 }
72175}
0 commit comments