Skip to content

Commit d7a52d6

Browse files
VelikovPetarclaude
andauthored
Fix delivery receipts not being sent in privacy settings updates (#6178)
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 38f908a commit d7a52d6

4 files changed

Lines changed: 103 additions & 29 deletions

File tree

stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/DtoMapping.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@
1616

1717
package io.getstream.chat.android.client.api2.mapping
1818

19+
import io.getstream.chat.android.DeliveryReceipts
1920
import io.getstream.chat.android.PrivacySettings
2021
import io.getstream.chat.android.ReadReceipts
2122
import io.getstream.chat.android.TypingIndicators
2223
import io.getstream.chat.android.client.api2.model.dto.AttachmentDto
24+
import io.getstream.chat.android.client.api2.model.dto.DeliveryReceiptsDto
2325
import io.getstream.chat.android.client.api2.model.dto.DeviceDto
2426
import io.getstream.chat.android.client.api2.model.dto.PrivacySettingsDto
2527
import io.getstream.chat.android.client.api2.model.dto.ReadReceiptsDto
@@ -207,6 +209,7 @@ internal class DtoMapping(
207209
internal fun PrivacySettings.toDto(): PrivacySettingsDto = PrivacySettingsDto(
208210
typing_indicators = typingIndicators?.toDto(),
209211
read_receipts = readReceipts?.toDto(),
212+
delivery_receipts = deliveryReceipts?.toDto(),
210213
)
211214

212215
/**
@@ -223,6 +226,13 @@ internal class DtoMapping(
223226
enabled = enabled,
224227
)
225228

229+
/**
230+
* Maps the domain [DeliveryReceipts] model to a network [DeliveryReceiptsDto] model.
231+
*/
232+
internal fun DeliveryReceipts.toDto(): DeliveryReceiptsDto = DeliveryReceiptsDto(
233+
enabled = enabled,
234+
)
235+
226236
/**
227237
* Maps the domain [User] model to a network [UpstreamUserDto] model.
228238
*

stream-chat-android-client/src/main/java/io/getstream/chat/android/client/socket/SocketFactory.kt

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -107,21 +107,14 @@ internal class SocketFactory(
107107

108108
private fun PrivacySettings.reducePrivacySettings(): Map<String, Any> = mutableMapOf<String, Any>()
109109
.apply {
110-
typingIndicators?.also {
111-
put(
112-
"typing_indicators",
113-
mapOf<String, Any>(
114-
"enabled" to it.enabled,
115-
),
116-
)
110+
typingIndicators?.let {
111+
put("typing_indicators", mapOf<String, Any>("enabled" to it.enabled))
117112
}
118-
readReceipts?.also {
119-
put(
120-
"read_receipts",
121-
mapOf<String, Any>(
122-
"enabled" to it.enabled,
123-
),
124-
)
113+
deliveryReceipts?.let {
114+
put("delivery_receipts", mapOf<String, Any>("enabled" to it.enabled))
115+
}
116+
readReceipts?.let {
117+
put("read_receipts", mapOf<String, Any>("enabled" to it.enabled))
125118
}
126119
}
127120

stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/DtoMappingTest.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@
1616

1717
package io.getstream.chat.android.client.api2.mapping
1818

19+
import io.getstream.chat.android.DeliveryReceipts
1920
import io.getstream.chat.android.PrivacySettings
2021
import io.getstream.chat.android.ReadReceipts
2122
import io.getstream.chat.android.TypingIndicators
2223
import io.getstream.chat.android.client.api2.model.dto.AttachmentDto
24+
import io.getstream.chat.android.client.api2.model.dto.DeliveryReceiptsDto
2325
import io.getstream.chat.android.client.api2.model.dto.DeviceDto
2426
import io.getstream.chat.android.client.api2.model.dto.PrivacySettingsDto
2527
import io.getstream.chat.android.client.api2.model.dto.ReadReceiptsDto
@@ -238,12 +240,31 @@ internal class DtoMappingTest {
238240
val privacySettings = PrivacySettings(
239241
typingIndicators = TypingIndicators(enabled = true),
240242
readReceipts = ReadReceipts(enabled = false),
243+
deliveryReceipts = DeliveryReceipts(enabled = false),
241244
)
242245
val mapping = Fixture().get()
243246
val dto = with(mapping) { privacySettings.toDto() }
244247
val expected = PrivacySettingsDto(
245248
typing_indicators = TypingIndicatorsDto(enabled = true),
246249
read_receipts = ReadReceiptsDto(enabled = false),
250+
delivery_receipts = DeliveryReceiptsDto(enabled = false),
251+
)
252+
dto shouldBeEqualTo expected
253+
}
254+
255+
@Test
256+
fun `PrivacySettings with null deliveryReceipts is correctly mapped to Dto`() {
257+
val privacySettings = PrivacySettings(
258+
typingIndicators = TypingIndicators(enabled = true),
259+
readReceipts = ReadReceipts(enabled = false),
260+
deliveryReceipts = null,
261+
)
262+
val mapping = Fixture().get()
263+
val dto = with(mapping) { privacySettings.toDto() }
264+
val expected = PrivacySettingsDto(
265+
typing_indicators = TypingIndicatorsDto(enabled = true),
266+
read_receipts = ReadReceiptsDto(enabled = false),
267+
delivery_receipts = null,
247268
)
248269
dto shouldBeEqualTo expected
249270
}

stream-chat-android-client/src/test/java/io/getstream/chat/android/client/socket/SocketFactoryTest.kt

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616

1717
package io.getstream.chat.android.client.socket
1818

19+
import io.getstream.chat.android.DeliveryReceipts
20+
import io.getstream.chat.android.PrivacySettings
21+
import io.getstream.chat.android.ReadReceipts
22+
import io.getstream.chat.android.TypingIndicators
1923
import io.getstream.chat.android.client.parser.ChatParser
2024
import io.getstream.chat.android.client.parser2.ParserFactory
2125
import io.getstream.chat.android.client.token.FakeTokenManager
@@ -94,7 +98,7 @@ internal class SocketFactoryTest {
9498
}
9599

96100
@JvmStatic
97-
@Suppress("MaxLineLength")
101+
@Suppress("MaxLineLength", "LongMethod")
98102
fun arguments() = listOf(
99103
randomUser(image = randomString(), name = randomString(), language = randomString()).let {
100104
Arguments.of(
@@ -138,26 +142,72 @@ internal class SocketFactoryTest {
138142
"${endpoint}connect?json=${buildMinimumUserJson("anon")}&api_key=$apiKey&X-Stream-Client=${headersUtil.buildSdkTrackingHeaders()}&stream-auth-type=anonymous",
139143
)
140144
},
145+
randomUser(
146+
image = randomString(),
147+
name = randomString(),
148+
language = randomString(),
149+
privacySettings = PrivacySettings(
150+
typingIndicators = TypingIndicators(enabled = false),
151+
deliveryReceipts = DeliveryReceipts(enabled = false),
152+
readReceipts = ReadReceipts(enabled = true),
153+
),
154+
).let {
155+
Arguments.of(
156+
false,
157+
SocketFactory.ConnectionConf.UserConnectionConf(endpoint, apiKey, it),
158+
"${endpoint}connect?json=${buildFullUserJson(it, it.id)}&api_key=$apiKey&X-Stream-Client=${headersUtil.buildSdkTrackingHeaders()}&authorization=$token&stream-auth-type=jwt",
159+
)
160+
},
161+
randomUser(
162+
image = randomString(),
163+
name = randomString(),
164+
language = randomString(),
165+
privacySettings = PrivacySettings(
166+
typingIndicators = null,
167+
deliveryReceipts = DeliveryReceipts(enabled = false),
168+
readReceipts = null,
169+
),
170+
).let {
171+
Arguments.of(
172+
false,
173+
SocketFactory.ConnectionConf.UserConnectionConf(endpoint, apiKey, it),
174+
"${endpoint}connect?json=${buildFullUserJson(it, it.id)}&api_key=$apiKey&X-Stream-Client=${headersUtil.buildSdkTrackingHeaders()}&authorization=$token&stream-auth-type=jwt",
175+
)
176+
},
141177
)
142178

143179
private fun buildMinimumUserJson(userId: String): String = encode(
144180
defaultMap(userId, mapOf("id" to userId)),
145181
)
146182

147-
private fun buildFullUserJson(user: User, userId: String): String = encode(
148-
defaultMap(
149-
userId,
150-
mapOf(
151-
"id" to userId,
152-
"role" to user.role,
153-
"banned" to user.isBanned,
154-
"invisible" to user.isInvisible,
155-
"language" to user.language,
156-
"image" to user.image,
157-
"name" to user.name,
158-
) + user.extraData,
159-
),
160-
)
183+
private fun buildFullUserJson(user: User, userId: String): String {
184+
val ps = user.privacySettings
185+
return encode(
186+
defaultMap(
187+
userId,
188+
linkedMapOf(
189+
"id" to userId,
190+
"role" to user.role,
191+
"banned" to user.isBanned,
192+
"invisible" to user.isInvisible,
193+
) + if (ps != null) {
194+
mapOf(
195+
"privacy_settings" to listOfNotNull(
196+
ps.typingIndicators?.let { "typing_indicators" to mapOf("enabled" to it.enabled) },
197+
ps.deliveryReceipts?.let { "delivery_receipts" to mapOf("enabled" to it.enabled) },
198+
ps.readReceipts?.let { "read_receipts" to mapOf("enabled" to it.enabled) },
199+
).toMap(),
200+
)
201+
} else {
202+
emptyMap()
203+
} + mapOf(
204+
"language" to user.language,
205+
"image" to user.image,
206+
"name" to user.name,
207+
) + user.extraData,
208+
),
209+
)
210+
}
161211

162212
private fun defaultMap(userId: String, userDetails: Map<String, Any>): Map<String, Any> =
163213
mapOf(

0 commit comments

Comments
 (0)