@@ -15,10 +15,16 @@ enum MessageRepositoryError: LocalizedError {
15
15
class MessageRepository {
16
16
let database : DatabaseContainer
17
17
let apiClient : APIClient
18
+ var interceptor : SendMessageInterceptor ?
18
19
19
- init ( database: DatabaseContainer , apiClient: APIClient ) {
20
+ init (
21
+ database: DatabaseContainer ,
22
+ apiClient: APIClient ,
23
+ interceptor: SendMessageInterceptor ?
24
+ ) {
20
25
self . database = database
21
26
self . apiClient = apiClient
27
+ self . interceptor = interceptor
22
28
}
23
29
24
30
func sendMessage(
@@ -49,84 +55,82 @@ class MessageRepository {
49
55
let requestBody = dto. asRequestBody ( ) as MessageRequestBody
50
56
let skipPush : Bool = dto. skipPush
51
57
let skipEnrichUrl : Bool = dto. skipEnrichUrl
58
+ var message : ChatMessage ?
52
59
53
60
// Change the message state to `.sending` and the proceed with the actual sending
54
- self ? . database. write ( {
55
- let messageDTO = $0. message ( id: messageId)
56
- messageDTO? . localMessageState = . sending
57
- } , completion: { error in
58
- if let error = error {
59
- log. error ( " Error changing localMessageState message with id \( messageId) to `sending`: \( error) " )
60
- self ? . markMessageAsFailedToSend ( id: messageId) {
61
- completion ( . failure( . failedToSendMessage( error) ) )
61
+ self ? . database. write (
62
+ {
63
+ let messageDTO = $0. message ( id: messageId)
64
+ messageDTO? . localMessageState = . sending
65
+ message = try messageDTO? . asModel ( )
66
+ } ,
67
+ completion: { error in
68
+ if let error = error {
69
+ log. error ( " Error changing localMessageState message with id \( messageId) to `sending`: \( error) " )
70
+ self ? . markMessageAsFailedToSend ( id: messageId) {
71
+ completion ( . failure( . failedToSendMessage( error) ) )
72
+ }
73
+ return
62
74
}
63
- return
64
- }
65
-
66
- let endpoint : Endpoint < MessagePayload . Boxed > = . sendMessage(
67
- cid: cid,
68
- messagePayload: requestBody,
69
- skipPush: skipPush,
70
- skipEnrichUrl: skipEnrichUrl
71
- )
72
- self ? . apiClient. request ( endpoint: endpoint) {
73
- switch $0 {
74
- case let . success( payload) :
75
- self ? . saveSuccessfullySentMessage ( cid: cid, message: payload. message) { result in
76
- switch result {
75
+
76
+ if let interceptor = self ? . interceptor, let message {
77
+ let options = SendMessageOptions (
78
+ skipPush: skipPush,
79
+ skipEnrichUrl: skipEnrichUrl
80
+ )
81
+ interceptor. sendMessage ( message, options: options) {
82
+ switch $0 {
77
83
case let . success( message) :
78
84
completion ( . success( message) )
79
85
case let . failure( error) :
80
- completion ( . failure( . failedToSendMessage( error) ) )
86
+ self ? . handleSendingMessageError (
87
+ error,
88
+ messageId: messageId,
89
+ completion: completion
90
+ )
81
91
}
82
92
}
83
-
84
- case let . failure( error) :
85
- self ? . handleSendingMessageError ( error, messageId: messageId, completion: completion)
93
+ return
94
+ }
95
+
96
+ let endpoint : Endpoint < MessagePayload . Boxed > = . sendMessage(
97
+ cid: cid,
98
+ messagePayload: requestBody,
99
+ skipPush: skipPush,
100
+ skipEnrichUrl: skipEnrichUrl
101
+ )
102
+ self ? . apiClient. request ( endpoint: endpoint) {
103
+ self ? . handleNewMessage (
104
+ messageId: messageId,
105
+ cid: cid,
106
+ result: $0. map ( \. message) ,
107
+ completion: completion
108
+ )
86
109
}
87
110
}
88
- } )
111
+ )
89
112
}
90
113
}
91
-
92
- /// Marks the message's local status to failed and adds it to the offline retry which sends the message when connection comes back.
93
- func scheduleOfflineRetry( for messageId: MessageId , completion: @escaping ( Result < ChatMessage , MessageRepositoryError > ) -> Void ) {
94
- var dataEndpoint : DataEndpoint !
95
- var messageModel : ChatMessage !
96
- database. write { session in
97
- guard let dto = session. message ( id: messageId) else {
98
- throw MessageRepositoryError . messageDoesNotExist
99
- }
100
- guard let channelDTO = dto. channel, let cid = try ? ChannelId ( cid: channelDTO. cid) else {
101
- throw MessageRepositoryError . messageDoesNotHaveValidChannel
102
- }
103
-
104
- // Send the message to offline handling
105
- let requestBody = dto. asRequestBody ( ) as MessageRequestBody
106
- let endpoint : Endpoint < MessagePayload . Boxed > = . sendMessage(
107
- cid: cid,
108
- messagePayload: requestBody,
109
- skipPush: dto. skipPush,
110
- skipEnrichUrl: dto. skipEnrichUrl
111
- )
112
- dataEndpoint = endpoint. withDataResponse
113
-
114
- // Mark it as failed
115
- dto. localMessageState = . sendingFailed
116
- messageModel = try dto. asModel ( )
117
- } completion: { [ weak self] writeError in
118
- if let writeError {
119
- switch writeError {
120
- case let repositoryError as MessageRepositoryError :
121
- completion ( . failure( repositoryError) )
122
- default :
123
- completion ( . failure( . failedToSendMessage( writeError) ) )
114
+
115
+ func handleNewMessage(
116
+ messageId: MessageId ,
117
+ cid: ChannelId ,
118
+ result: Result < MessagePayload , Error > ,
119
+ completion: @escaping ( Result < ChatMessage , MessageRepositoryError > ) -> Void
120
+ ) {
121
+ switch result {
122
+ case let . success( payload) :
123
+ saveSuccessfullySentMessage ( cid: cid, message: payload) { result in
124
+ switch result {
125
+ case let . success( message) :
126
+ completion ( . success( message) )
127
+ case let . failure( error) :
128
+ completion ( . failure( . failedToSendMessage( error) ) )
124
129
}
125
- return
126
130
}
127
- // Offline repository will send it when connection comes back on, until then we show the message as failed
128
- self ? . apiClient . queueOfflineRequest ? ( dataEndpoint . withDataResponse )
129
- completion ( . success ( messageModel ) )
131
+
132
+ case let . failure ( error ) :
133
+ handleSendingMessageError ( error , messageId : messageId , completion : completion )
130
134
}
131
135
}
132
136
@@ -345,6 +349,47 @@ class MessageRepository {
345
349
completion ? ( )
346
350
}
347
351
}
352
+
353
+ /// Marks the message's local status to failed and adds it to the offline retry which sends the message when connection comes back.
354
+ func scheduleOfflineRetry( for messageId: MessageId , completion: @escaping ( Result < ChatMessage , MessageRepositoryError > ) -> Void ) {
355
+ var dataEndpoint : DataEndpoint !
356
+ var messageModel : ChatMessage !
357
+ database. write { session in
358
+ guard let dto = session. message ( id: messageId) else {
359
+ throw MessageRepositoryError . messageDoesNotExist
360
+ }
361
+ guard let channelDTO = dto. channel, let cid = try ? ChannelId ( cid: channelDTO. cid) else {
362
+ throw MessageRepositoryError . messageDoesNotHaveValidChannel
363
+ }
364
+
365
+ // Send the message to offline handling
366
+ let requestBody = dto. asRequestBody ( ) as MessageRequestBody
367
+ let endpoint : Endpoint < MessagePayload . Boxed > = . sendMessage(
368
+ cid: cid,
369
+ messagePayload: requestBody,
370
+ skipPush: dto. skipPush,
371
+ skipEnrichUrl: dto. skipEnrichUrl
372
+ )
373
+ dataEndpoint = endpoint. withDataResponse
374
+
375
+ // Mark it as failed
376
+ dto. localMessageState = . sendingFailed
377
+ messageModel = try dto. asModel ( )
378
+ } completion: { [ weak self] writeError in
379
+ if let writeError {
380
+ switch writeError {
381
+ case let repositoryError as MessageRepositoryError :
382
+ completion ( . failure( repositoryError) )
383
+ default :
384
+ completion ( . failure( . failedToSendMessage( writeError) ) )
385
+ }
386
+ return
387
+ }
388
+ // Offline repository will send it when connection comes back on, until then we show the message as failed
389
+ self ? . apiClient. queueOfflineRequest ? ( dataEndpoint. withDataResponse)
390
+ completion ( . success( messageModel) )
391
+ }
392
+ }
348
393
}
349
394
350
395
extension MessageRepository {
0 commit comments