diff --git a/CHANGELOG.md b/CHANGELOG.md index f99c8675..d04e358f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ # Changelog +### v3.21.1 (Nov 12, 2024) with Chat SDK `v4.20.0` +* Fixed thumbs up reaction not working in chat messages. ### v3.21.0 (Sep 12, 2024) with Chat SDK `v4.19.0` * Changed the Form type message UI rendering due to the modification of the Form model from BaseMessage to MessageForm. * Sendbird Business Messaging changes diff --git a/gradle.properties b/gradle.properties index 11e18dd7..1c1466bd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,5 +22,5 @@ android.nonTransitiveRClass=false android.nonFinalResIds=false android.enableR8.fullMode=false -UIKIT_VERSION = 3.21.0 +UIKIT_VERSION = 3.21.1 UIKIT_VERSION_CODE = 1 diff --git a/uikit-samples/src/main/java/com/sendbird/uikit/samples/common/consts/Region.kt b/uikit-samples/src/main/java/com/sendbird/uikit/samples/common/consts/Region.kt index 94828fed..db24c373 100644 --- a/uikit-samples/src/main/java/com/sendbird/uikit/samples/common/consts/Region.kt +++ b/uikit-samples/src/main/java/com/sendbird/uikit/samples/common/consts/Region.kt @@ -6,6 +6,7 @@ enum class Region { NO1, NO2, NO3, - NO4 + NO4, + NO5 ; } diff --git a/uikit-samples/src/main/java/com/sendbird/uikit/samples/common/extensions/UIKitExtensions.kt b/uikit-samples/src/main/java/com/sendbird/uikit/samples/common/extensions/UIKitExtensions.kt index 00d94062..66326405 100644 --- a/uikit-samples/src/main/java/com/sendbird/uikit/samples/common/extensions/UIKitExtensions.kt +++ b/uikit-samples/src/main/java/com/sendbird/uikit/samples/common/extensions/UIKitExtensions.kt @@ -193,6 +193,7 @@ internal fun Region.apiHost(): String? { Region.NO2 -> "https://api-no2.sendbirdtest.com" Region.NO3 -> "https://api-no3.sendbirdtest.com" Region.NO4 -> "https://api-no4.sendbirdtest.com" + Region.NO5 -> "https://api-no5.sendbirdtest.com" else -> null } } @@ -203,6 +204,7 @@ internal fun Region.wsHost(): String? { Region.NO2 -> "wss://ws-no2.sendbirdtest.com" Region.NO3 -> "wss://ws-no3.sendbirdtest.com" Region.NO4 -> "wss://ws-no4.sendbirdtest.com" + Region.NO5 -> "wss://ws-no5.sendbirdtest.com" else -> null } } diff --git a/uikit-samples/src/main/res/values/strings.xml b/uikit-samples/src/main/res/values/strings.xml index 5b24cfc5..7fed0a9b 100644 --- a/uikit-samples/src/main/res/values/strings.xml +++ b/uikit-samples/src/main/res/values/strings.xml @@ -166,5 +166,6 @@ NO2 NO3 NO4 + NO5 diff --git a/uikit/build.gradle b/uikit/build.gradle index d648af07..0ce49e1e 100644 --- a/uikit/build.gradle +++ b/uikit/build.gradle @@ -70,7 +70,7 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) // Sendbird - api 'com.sendbird.sdk:sendbird-chat:4.19.0' + api 'com.sendbird.sdk:sendbird-chat:4.20.0' implementation 'com.github.bumptech.glide:glide:4.16.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0' @@ -96,7 +96,7 @@ dokkaHtml { String dokkaBaseConfiguration = """ { - "footerMessage": "Report a bug or request a feature.\\tFor further developer documentation, see UIkit SDK Documentation. That documentation contains more detailed descriptions, conceptual overviews, definitions of terms, and code examples.
Copyright © 2022, Sendbird or its affiliates. All rights reserved." + "footerMessage": "Report a bug or request a feature.\\tFor further developer documentation, see UIkit SDK Documentation. That documentation contains more detailed descriptions, conceptual overviews, definitions of terms, and code examples.
Copyright © 2022, Sendbird or its affiliates. All rights reserved." } """ pluginsMapConfiguration.set( diff --git a/uikit/src/main/java/com/sendbird/uikit/internal/extensions/EmojiExtensions.kt b/uikit/src/main/java/com/sendbird/uikit/internal/extensions/EmojiExtensions.kt index f666a57d..06e74f60 100644 --- a/uikit/src/main/java/com/sendbird/uikit/internal/extensions/EmojiExtensions.kt +++ b/uikit/src/main/java/com/sendbird/uikit/internal/extensions/EmojiExtensions.kt @@ -4,7 +4,6 @@ import com.sendbird.android.message.Emoji import com.sendbird.android.message.Reaction internal fun Collection.containsEmoji(emojiKey: String): Boolean { - if (emojiKey == "sendbird_emoji_thumbsup") return false return this.any { it.key == emojiKey } } diff --git a/uikit/src/main/java/com/sendbird/uikit/internal/model/notifications/NotificationTemplate.kt b/uikit/src/main/java/com/sendbird/uikit/internal/model/notifications/NotificationTemplate.kt index b610a136..327ed546 100644 --- a/uikit/src/main/java/com/sendbird/uikit/internal/model/notifications/NotificationTemplate.kt +++ b/uikit/src/main/java/com/sendbird/uikit/internal/model/notifications/NotificationTemplate.kt @@ -6,6 +6,8 @@ import com.sendbird.uikit.internal.singleton.JsonParser import com.sendbird.uikit.log.Logger import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +import kotlinx.serialization.json.jsonArray +import kotlinx.serialization.json.jsonObject @Serializable internal data class NotificationTemplateList constructor( @@ -14,7 +16,17 @@ internal data class NotificationTemplateList constructor( companion object { @JvmStatic fun fromJson(value: String): NotificationTemplateList { - return JsonParser.fromJson(value) + val mutableTemplates = mutableListOf() + JsonParser.toJsonElement(value).jsonObject[KeySet.templates]?.jsonArray?.let { templateList -> + for (element in templateList) { + try { + mutableTemplates.add(JsonParser.fromJsonElement(element)) + } catch (e: Exception) { + e.printStackTrace() + } + } + } + return NotificationTemplateList(mutableTemplates.toList()) } } } diff --git a/uikit/src/main/java/com/sendbird/uikit/internal/model/template_messages/KeySet.kt b/uikit/src/main/java/com/sendbird/uikit/internal/model/template_messages/KeySet.kt index cb93fb08..4865f1e0 100644 --- a/uikit/src/main/java/com/sendbird/uikit/internal/model/template_messages/KeySet.kt +++ b/uikit/src/main/java/com/sendbird/uikit/internal/model/template_messages/KeySet.kt @@ -58,6 +58,7 @@ internal object KeySet { const val sub_data = "sub_data" const val sub_type = "sub_type" const val carouselView = "carouselView" + const val templates = "templates" // notifications const val key = "key" diff --git a/uikit/src/main/java/com/sendbird/uikit/internal/singleton/JsonParser.kt b/uikit/src/main/java/com/sendbird/uikit/internal/singleton/JsonParser.kt index 878631f5..1f53fbd1 100644 --- a/uikit/src/main/java/com/sendbird/uikit/internal/singleton/JsonParser.kt +++ b/uikit/src/main/java/com/sendbird/uikit/internal/singleton/JsonParser.kt @@ -4,7 +4,7 @@ import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonElement -import kotlinx.serialization.json.encodeToJsonElement +import kotlinx.serialization.json.decodeFromJsonElement internal object JsonParser { private val json by lazy { @@ -24,7 +24,12 @@ internal object JsonParser { } @JvmStatic - inline fun toJsonElement(value: T): JsonElement { - return json.encodeToJsonElement(value) + inline fun fromJsonElement(element: JsonElement): T { + return json.decodeFromJsonElement(element) + } + + @JvmStatic + internal fun toJsonElement(value: String): JsonElement { + return json.parseToJsonElement(value) } } diff --git a/uikit/src/main/java/com/sendbird/uikit/internal/singleton/NotificationChannelManager.kt b/uikit/src/main/java/com/sendbird/uikit/internal/singleton/NotificationChannelManager.kt index 6d602df8..d8896303 100644 --- a/uikit/src/main/java/com/sendbird/uikit/internal/singleton/NotificationChannelManager.kt +++ b/uikit/src/main/java/com/sendbird/uikit/internal/singleton/NotificationChannelManager.kt @@ -1,6 +1,7 @@ package com.sendbird.uikit.internal.singleton import android.content.Context +import androidx.annotation.VisibleForTesting import androidx.annotation.WorkerThread import com.sendbird.android.exception.SendbirdException import com.sendbird.uikit.internal.extensions.runOnUiThread @@ -13,6 +14,8 @@ import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.Executors import java.util.concurrent.atomic.AtomicBoolean +@VisibleForTesting +internal const val MAX_REQUEST_TEMPLATE_RETRY_COUNT = 10 internal object NotificationChannelManager { private data class TemplateRequestData( val key: String, @@ -24,9 +27,13 @@ internal object NotificationChannelManager { private val worker = Executors.newFixedThreadPool(10) private val isInitialized: AtomicBoolean = AtomicBoolean() private val templateRequestDatas: MutableMap> = ConcurrentHashMap() + @VisibleForTesting + internal val templateRequestCount: MutableMap = ConcurrentHashMap() - private lateinit var templateRepository: NotificationTemplateRepository - private lateinit var channelSettingsRepository: NotificationChannelRepository + @VisibleForTesting + internal lateinit var templateRepository: NotificationTemplateRepository + @VisibleForTesting + internal lateinit var channelSettingsRepository: NotificationChannelRepository /** * To avoid sending an unintended exception, if the NotificationChannelManager hasn't been initialized it tries to initialize automatically. @@ -71,6 +78,14 @@ internal object NotificationChannelManager { return } + // Apply a retry count to prevent infinite requests in case of failure. + val retryCount = templateRequestCount[key] ?: 0 + if (retryCount >= MAX_REQUEST_TEMPLATE_RETRY_COUNT) { + notifyError(key, SendbirdException("Too many template requests have been made.[key=$key]")) + return + } + templateRequestCount[key] = retryCount + 1 + synchronized(templateRequestDatas) { val request = TemplateRequestData(key, variables, themeMode, callback) templateRequestDatas[key]?.let { @@ -89,6 +104,7 @@ internal object NotificationChannelManager { val rawTemplate = templateRepository.requestTemplateBlocking(key) makeAndNotifyTemplate(key, rawTemplate) } catch (e: Throwable) { + templateRequestCount[key] = 1 notifyError(key, SendbirdException(e)) } } diff --git a/uikit/src/main/java/com/sendbird/uikit/internal/singleton/NotificationTemplateRepository.kt b/uikit/src/main/java/com/sendbird/uikit/internal/singleton/NotificationTemplateRepository.kt index e7e9254c..5901edf7 100644 --- a/uikit/src/main/java/com/sendbird/uikit/internal/singleton/NotificationTemplateRepository.kt +++ b/uikit/src/main/java/com/sendbird/uikit/internal/singleton/NotificationTemplateRepository.kt @@ -90,10 +90,10 @@ internal class NotificationTemplateRepository(context: Context) { ) { notificationTemplateList, _, token, e -> error = e try { - if (!token.isNullOrEmpty()) lastCacheToken = token val templateList = notificationTemplateList?.let { NotificationTemplateList.fromJson(it.jsonPayload) } + if (!token.isNullOrEmpty()) lastCacheToken = token result.set(templateList) } catch (e: Throwable) { error = SendbirdException("notification template list data is not valid", e) diff --git a/uikit/src/main/res/drawable-ldrtl-hdpi/icon_reply_filled.png b/uikit/src/main/res/drawable-ldrtl-hdpi/icon_reply_filled.png new file mode 100644 index 00000000..6306ba11 Binary files /dev/null and b/uikit/src/main/res/drawable-ldrtl-hdpi/icon_reply_filled.png differ diff --git a/uikit/src/main/res/drawable-ldrtl-mdpi/icon_reply_filled.png b/uikit/src/main/res/drawable-ldrtl-mdpi/icon_reply_filled.png new file mode 100644 index 00000000..46b2fa8f Binary files /dev/null and b/uikit/src/main/res/drawable-ldrtl-mdpi/icon_reply_filled.png differ diff --git a/uikit/src/main/res/drawable-ldrtl-xhdpi/icon_reply_filled.png b/uikit/src/main/res/drawable-ldrtl-xhdpi/icon_reply_filled.png new file mode 100644 index 00000000..a2a42fdc Binary files /dev/null and b/uikit/src/main/res/drawable-ldrtl-xhdpi/icon_reply_filled.png differ diff --git a/uikit/src/main/res/drawable-ldrtl-xxhdpi/icon_reply_filled.png b/uikit/src/main/res/drawable-ldrtl-xxhdpi/icon_reply_filled.png new file mode 100644 index 00000000..56eb0dd3 Binary files /dev/null and b/uikit/src/main/res/drawable-ldrtl-xxhdpi/icon_reply_filled.png differ diff --git a/uikit/src/main/res/drawable-ldrtl-xxxhdpi/icon_reply_filled.png b/uikit/src/main/res/drawable-ldrtl-xxxhdpi/icon_reply_filled.png new file mode 100644 index 00000000..6f59ad97 Binary files /dev/null and b/uikit/src/main/res/drawable-ldrtl-xxxhdpi/icon_reply_filled.png differ diff --git a/uikit/src/main/res/layout/sb_view_suggested_mention_list_item.xml b/uikit/src/main/res/layout/sb_view_suggested_mention_list_item.xml index 141dded4..d98ae15d 100644 --- a/uikit/src/main/res/layout/sb_view_suggested_mention_list_item.xml +++ b/uikit/src/main/res/layout/sb_view_suggested_mention_list_item.xml @@ -7,6 +7,7 @@ android:paddingTop="@dimen/sb_size_8" android:paddingEnd="@dimen/sb_size_16" android:paddingBottom="@dimen/sb_size_8" + xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> @@ -27,6 +28,7 @@ android:layout_marginStart="@dimen/sb_size_10" android:maxLines="1" android:ellipsize="end" + app:layout_constraintHorizontal_bias="0" app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintStart_toEndOf="@+id/ivProfile" app:layout_constraintEnd_toStartOf="@+id/tvDescription" @@ -35,7 +37,7 @@