Skip to content

Commit

Permalink
Added v3.15.0
Browse files Browse the repository at this point in the history
  • Loading branch information
sendbird-sdk-deployment committed Mar 28, 2024
1 parent ba929e2 commit 7785f2a
Show file tree
Hide file tree
Showing 21 changed files with 200 additions and 38 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# Changelog
### v3.15.0 (Mar 28, 2024) with Chat SDK `v4.16.0`
* Added `sendLogViewed(List<BaseMessage>)` in `FeedNotificationChannelViewModel`.
* Deprecated `sendLogImpression(List<BaseMessage>)` in `FeedNotificationChannelViewModel`.
* Supported reactions in super group channel.
Added `enableReactionsSupergroup` in `ChannelConfig`.
### v3.14.1 (Mar 20, 2024) with Chat SDK `v4.15.6`
* Fixed issue where the position of the empty icon was displayed incorrectly.
### v3.14.0 (Mar 19, 2024) with Chat SDK `v4.15.6`
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ org.gradle.jvmargs=-Xmx1536m
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true

UIKIT_VERSION = 3.14.1
UIKIT_VERSION = 3.15.0
UIKIT_VERSION_CODE = 1
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ object StringSet {
const val PUSH_REDIRECT_CHANNEL = "PUSH_REDIRECT_CHANNEL"
const val PUSH_REDIRECT_MESSAGE_ID = "PUSH_REDIRECT_MESSAGE_ID"
const val PUSH_REDIRECT_CHANNEL_TYPE = "PUSH_REDIRECT_CHANNEL_TYPE"
const val PUSH_NOTIFICATION_DATA = "PUSH_NOTIFICATION_DATA"
const val SETTINGS_USE_HEADER = "SETTINGS_USE_HEADER"
const val SETTINGS_USE_DO_NOT_DISTURB = "SETTINGS_USE_DO_NOT_DISTURB"
const val SB_LIVE_TYPE = "SB_LIVE_TYPE"
Expand All @@ -32,4 +33,5 @@ object StringSet {
const val notification_chat = "notification_chat"
const val push_title = "push_title"
const val channel_type = "channel_type"
const val notification_channel_key = "notification_channel_key"
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.graphics.drawable.Drawable
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.sendbird.android.SendbirdChat
Expand Down Expand Up @@ -33,6 +34,7 @@ import com.sendbird.uikit.samples.customization.CustomizationHomeActivity
import com.sendbird.uikit.samples.notification.NotificationHomeActivity
import com.sendbird.uikit.samples.notification.NotificationLoginActivity
import com.sendbird.uikit.samples.notification.NotificationMainActivity
import java.io.Serializable

internal fun SampleType?.getLogoDrawable(context: Context): Drawable? {
return when (this) {
Expand Down Expand Up @@ -170,3 +172,12 @@ internal fun getFeedChannelUrl(): String {
feedChannels?.get(StringSet.feed)
} ?: ""
}

internal fun <T : Serializable?> Intent.getSerializable(key: String, clazz: Class<T>): T? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
this.getSerializableExtra(key, clazz)
} else {
@Suppress("UNCHECKED_CAST")
this.getSerializableExtra(key) as? T
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,13 @@ class MyFirebaseMessagingService : SendbirdPushHandler() {
try {
if (remoteMessage.data.containsKey(StringSet.sendbird)) {
val jsonStr = remoteMessage.data[StringSet.sendbird]
markAsDelivered(remoteMessage.data)
try {
markAsDelivered(remoteMessage.data)
} catch (e: Exception) {
Logger.e(e)
}
if (jsonStr == null) return
sendNotification(context, JSONObject(jsonStr))
sendNotification(context, JSONObject(jsonStr), remoteMessage.data)
}
} catch (e: JSONException) {
Logger.e(e)
Expand All @@ -72,12 +76,13 @@ class MyFirebaseMessagingService : SendbirdPushHandler() {
* @param sendBird JSONObject payload from FCM
*/
@Throws(JSONException::class)
fun sendNotification(context: Context, sendBird: JSONObject) {
fun sendNotification(context: Context, sendBird: JSONObject, data: Map<String, String>) {
val message = sendBird.getString(StringSet.message)
val channel = sendBird.getJSONObject(StringSet.channel)
val channelUrl = channel.getString(StringSet.channel_url)
val messageId = sendBird.getLong(StringSet.message_id)
val channelType = sendBird.optString(StringSet.channel_type, "")
val channelKey = sendBird.optString(StringSet.notification_channel_key, "")
var pushTitle = context.getString(R.string.app_name)
if (sendBird.has(StringSet.sender)) {
val sender = sendBird.getJSONObject(StringSet.sender)
Expand All @@ -95,7 +100,8 @@ class MyFirebaseMessagingService : SendbirdPushHandler() {
}
}

val intent = newRedirectToChannelIntent(context, channelUrl, messageId, channelType)
val hashedData = if (channelKey.isNotEmpty()) HashMap(data) else null
val intent = newRedirectToChannelIntent(context, channelUrl, messageId, channelType, hashedData)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)

@SuppressLint("UnspecifiedImmutableFlag")
Expand Down Expand Up @@ -128,14 +134,17 @@ class MyFirebaseMessagingService : SendbirdPushHandler() {
context: Context,
channelUrl: String,
messageId: Long,
channelType: String
channelType: String,
data: HashMap<String, String>?,
): Intent {
return PreferenceUtils.selectedSampleType.newRedirectToChannelIntent(
context,
channelUrl,
messageId,
channelType
)
).apply {
data?.let { putExtra(StringSet.PUSH_NOTIFICATION_DATA, it) }
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
package com.sendbird.uikit.samples.notification

import android.Manifest
import android.content.DialogInterface
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.view.View
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.content.PermissionChecker
import com.sendbird.uikit.activities.FeedNotificationChannelActivity
import com.sendbird.uikit.samples.R
import com.sendbird.uikit.samples.common.ThemeHomeActivity
Expand All @@ -11,9 +21,15 @@ import com.sendbird.uikit.samples.common.extensions.logout
import com.sendbird.uikit.samples.common.extensions.setTextColorResource
import com.sendbird.uikit.samples.common.preferences.PreferenceUtils
import com.sendbird.uikit.samples.databinding.ActivityNotificationHomeBinding
import com.sendbird.uikit.utils.ContextUtils
import java.util.Locale

class NotificationHomeActivity : ThemeHomeActivity() {
override val binding: ActivityNotificationHomeBinding by lazy { ActivityNotificationHomeBinding.inflate(layoutInflater) }
private val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { }
private val appSettingLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding.apply {
Expand All @@ -31,6 +47,21 @@ class NotificationHomeActivity : ThemeHomeActivity() {

}
btSignOut.setOnClickListener { logout() }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
val permission = Manifest.permission.POST_NOTIFICATIONS
if (ContextCompat.checkSelfPermission(
this@NotificationHomeActivity,
permission
) == PermissionChecker.PERMISSION_GRANTED
) {
return@apply
}
if (ActivityCompat.shouldShowRequestPermissionRationale(this@NotificationHomeActivity, permission)) {
showPermissionRationalePopup()
return@apply
}
requestPermissionLauncher.launch(permission)
}
}
}

Expand All @@ -42,4 +73,29 @@ class NotificationHomeActivity : ThemeHomeActivity() {
else R.drawable.selector_home_signout_button
)
}

private fun showPermissionRationalePopup() {
val builder = AlertDialog.Builder(this)
builder.setTitle(getString(com.sendbird.uikit.R.string.sb_text_dialog_permission_title))
builder.setMessage(
String.format(
Locale.US,
getString(R.string.sb_text_need_to_allow_permission_notification),
ContextUtils.getApplicationName(this)
)
)
builder.setPositiveButton(com.sendbird.uikit.R.string.sb_text_go_to_settings) { _: DialogInterface?, _: Int ->
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
intent.addCategory(Intent.CATEGORY_DEFAULT)
intent.data = Uri.parse("package:$packageName")
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
appSettingLauncher.launch(intent)
}
val dialog = builder.create()
dialog.show()
dialog.getButton(AlertDialog.BUTTON_POSITIVE)
.setTextColor(ContextCompat.getColor(this, com.sendbird.uikit.R.color.secondary_300))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import com.sendbird.android.SendbirdChat.removeUserEventHandler
import com.sendbird.android.exception.SendbirdException
import com.sendbird.android.handler.UnreadMessageCountHandler
import com.sendbird.android.handler.UserEventHandler
import com.sendbird.android.push.SendbirdPushHelper
import com.sendbird.android.user.UnreadMessageCount
import com.sendbird.android.user.User
import com.sendbird.uikit.SendbirdUIKit
Expand All @@ -30,6 +31,7 @@ import com.sendbird.uikit.samples.common.SampleSettingsFragment
import com.sendbird.uikit.samples.common.consts.InitState
import com.sendbird.uikit.samples.common.consts.StringSet
import com.sendbird.uikit.samples.common.extensions.getFeedChannelUrl
import com.sendbird.uikit.samples.common.extensions.getSerializable
import com.sendbird.uikit.samples.common.extensions.isUsingDarkTheme
import com.sendbird.uikit.samples.common.preferences.PreferenceUtils
import com.sendbird.uikit.samples.common.widgets.CustomTabView
Expand Down Expand Up @@ -152,15 +154,27 @@ class NotificationMainActivity : AppCompatActivity() {

private fun redirectChannelIfNeeded(intent: Intent?) {
if (intent == null) return
Logger.i("++ intent: %s", intent)
Logger.i("++ intent: %s, %s", intent, intent.extras)
if (intent.hasExtra(StringSet.PUSH_NOTIFICATION_DATA)) {
intent.getSerializable(StringSet.PUSH_NOTIFICATION_DATA, HashMap::class.java)?.let {
val resultMap = HashMap<String, String>()
for ((key, value) in it) {
if (key is String && value is String) {
resultMap[key] = value
}
}
SendbirdPushHelper.markPushNotificationAsClicked(resultMap)
}
intent.removeExtra(StringSet.PUSH_NOTIFICATION_DATA)
}
if (intent.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY == Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) {
intent.removeExtra(StringSet.PUSH_REDIRECT_CHANNEL)
intent.removeExtra(StringSet.PUSH_REDIRECT_MESSAGE_ID)
}
if (intent.hasExtra(StringSet.PUSH_REDIRECT_CHANNEL)) {
val channelUrl = intent.getStringExtra(StringSet.PUSH_REDIRECT_CHANNEL)
intent.removeExtra(StringSet.PUSH_REDIRECT_CHANNEL)
if (channelUrl == null) return
if (channelUrl.isNullOrEmpty()) return
val channelType = intent.getStringExtra(StringSet.PUSH_REDIRECT_CHANNEL_TYPE)
if (channelType.isNullOrEmpty()) return

Expand Down
2 changes: 1 addition & 1 deletion uikit/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])

// Sendbird
api 'com.sendbird.sdk:sendbird-chat:4.15.6'
api 'com.sendbird.sdk:sendbird-chat:4.16.0'

implementation 'com.github.bumptech.glide:glide:4.13.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.13.0'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -515,16 +515,15 @@ void showEmojiReactionDialog(@NonNull BaseMessage message, int position) {
return;
}

final GroupChannel channel = getViewModel().getChannel();
if (channel == null || channel.isSuper()) return;
final Context contextThemeWrapper = ContextUtils.extractModuleThemeContext(getContext(), getModule().getParams().getTheme(), R.attr.sb_component_list);
final EmojiReactionUserListView emojiReactionUserListView = new EmojiReactionUserListView(contextThemeWrapper);
emojiReactionUserListView.setOnProfileClickListener(this::onEmojiReactionUserListProfileClicked);
final GroupChannel channel = getViewModel().getChannel();
if (channel != null) {
emojiReactionUserListView.setEmojiReactionUserData(this,
position,
message.getReactions(),
getReactionUserInfo(channel, message.getReactions()));
}
emojiReactionUserListView.setEmojiReactionUserData(this,
position,
message.getReactions(),
getReactionUserInfo(channel, message.getReactions()));
hideKeyboard();
DialogUtils.showContentDialog(requireContext(), emojiReactionUserListView);
}
Expand Down Expand Up @@ -863,9 +862,9 @@ private boolean isUploadFileSizeLimitExceeded(@NonNull List<Integer> fileSizes)
private static int getMultipleFilesMessageFileCountLimit() {
return Math.min(
MULTIPLE_FILES_COUNT_LIMIT,
SendbirdChat.getAppInfo() == null ?
MULTIPLE_FILES_COUNT_LIMIT :
SendbirdChat.isInitialized() && SendbirdChat.getAppInfo() != null ?
SendbirdChat.getAppInfo().getMultipleFilesMessageFileCountLimit()
: MULTIPLE_FILES_COUNT_LIMIT
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ protected void onBindNotificationListComponent(@NonNull FeedNotificationListComp
Logger.d(">> FeedNotificationChannelFragment::onBindFeedNotificationListComponent()");
listComponent.setOnMessageTemplateActionHandler(actionHandler != null ? actionHandler : this::handleAction);
listComponent.setOnTooltipClickListener(v -> listComponent.scrollToFirst());
listComponent.setOnNotificationViewedDetectedListener(viewModel::sendLogImpression);
listComponent.setOnNotificationViewedDetectedListener(viewModel::sendLogViewed);
listComponent.setOnNotificationCategorySelectListener(category -> {
Logger.d("++ selected category = %s", category);
listComponent.clearData();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ internal object KeySet {
const val enable_typing_indicator = "enable_typing_indicator"
const val typing_indicator_types = "typing_indicator_types"
const val enable_reactions = "enable_reactions"
const val enable_reactions_supergroup = "enable_reactions_supergroup"
const val enable_voice_message = "enable_voice_message"
const val enable_multiple_files_message = "enable_multiple_files_message"
const val enable_suggested_replies = "enable_suggested_replies"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,19 @@ internal abstract class BaseNotificationView @JvmOverloads internal constructor(
val tags: List<String> = message.notificationData?.tags ?: listOf()
val result = SendbirdStatistics.appendStat(
KeySet.noti_stats,
mapOf(
mutableMapOf(
KeySet.action to KeySet.clicked,
KeySet.template_key to templateKey,
KeySet.channel_url to message.channelUrl,
KeySet.tags to tags,
KeySet.message_id to message.messageId,
KeySet.source to KeySet.notification,
KeySet.message_ts to message.createdAt,
)
).apply {
message.notificationEventDeadline?.let {
put(KeySet.notification_event_deadline, it)
}
}.toMap()
)
Logger.d("++ appendStat end, result=%s, tags=%s", result, tags)
} catch (e: Throwable) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import android.util.AttributeSet
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import com.sendbird.android.channel.BaseChannel
import com.sendbird.android.channel.GroupChannel
import com.sendbird.android.message.BaseMessage
import com.sendbird.uikit.R
import com.sendbird.uikit.databinding.SbViewChatNotificationComponentBinding
Expand Down Expand Up @@ -65,8 +65,9 @@ internal class ChatNotificationView @JvmOverloads internal constructor(
}
}

fun drawMessage(channel: BaseChannel, message: BaseMessage, config: NotificationConfig? = null) {
fun drawMessage(channel: GroupChannel, message: BaseMessage, config: NotificationConfig? = null) {
binding.tvLabel.text = MessageUtils.getNotificationLabel(message)
binding.tvLabel.visibility = if (channel.isTemplateLabelEnabled) View.VISIBLE else View.INVISIBLE
binding.tvSentAt.text = DateUtils.formatDateTime(context, message.createdAt)
binding.ivProfileView.loadCircle(channel.coverUrl)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ internal class FeedNotificationListAdapter(
var onMessageTemplateActionHandler: OnNotificationTemplateActionHandler? = null

init {
this.prevLastSeenAt = channel.myLastRead
this.currentLastSeenAt = channel.myLastRead
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import com.sendbird.uikit.internal.ui.widgets.InnerLinearLayoutManager
import com.sendbird.uikit.log.Logger
import com.sendbird.uikit.model.Action
import com.sendbird.uikit.utils.DrawableUtils
import java.lang.Exception
import java.util.concurrent.atomic.AtomicBoolean

/**
Expand Down Expand Up @@ -91,8 +92,14 @@ internal open class FeedNotificationListComponent @JvmOverloads constructor(

onNotificationViewedDetectedListener?.let {
val range = if (firstVisibleItem <= lastVisibleItem) firstVisibleItem..lastVisibleItem else lastVisibleItem..firstVisibleItem
val items = range.mapNotNull { i -> adapter?.getItem(i) }
it.onNotificationViewedDetected(items)
val copiedList = adapter?.getItems()?.toList()
if (copiedList != null) {
try {
val items = range.mapNotNull { i -> copiedList[i] }
it.onNotificationViewedDetected(items)
} catch (ignore: Exception) {
}
}
}
}

Expand Down
Loading

0 comments on commit 7785f2a

Please sign in to comment.