diff --git a/CHANGELOG.md b/CHANGELOG.md index 1eac3f56..a4ad1969 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog -### v3.16.1 (May 3, 2024) with Chat SDK `v4.16.2` +### v3.17.0 (May 23, 2024) with Chat SDK `v4.16.3` +* Deprecated `notifyStatusUpdated(GroupChannel, StatusFrameView)` in `MessageThreadInputComponent` +* Added a new interface to set the enable state of the message input field + * Added `boolean tryToChangeEnableInputView(boolean, String)` in `ChannelFragment`, `MessageThreadFragment`, `OpenChannelFragment` + * Added `boolean tryToChangeEnableInputView(boolean, GroupChannel, String)` in `MessageInputComponent` + * Added `boolean tryToChangeEnableInputView(boolean, OpenChannel, String)` in `OpenChannelMessageInputComponent` + +* A new interface has been added to allow you to customise the items in the RecyclerView + * Added `String getActionContextMenuTitle(GroupChannel)`, `List makeChannelContextMenu(GroupChannel)`, and `boolean onChannelContextMenuItemClicked(GroupChannel, View, DialogListItem)` in `ChannelListFragment` + +* Added a new interface to receive events when a message is clicked or long-clicked on the screen used in Sendbird Business Messaging + * Added `setOnItemClickListener(OnItemClickListener)` and `setOnItemLongClickListener(OnItemLongClickListener)` in `ChatNotificationChannelFragment.Builder` and `FeedNotificationChannelFragment.Builder` + +* Added a new feature to support markdown syntax in UserMessage + * Added `enableMarkdownForUserMessage: Boolean` in `ChannelConfig`. If you enable this feature, you can use markdown syntax in the UserMessage. + * Currently, the following markdown syntax is supported: + * Bold: `**bold**`, `__bold__` + * Link: `[link](https://sendbird.com)` + +* Options for Suggested Replies, Direction and Target, have been added. + * These two options only work when `ChannelConfig.enableSuggestedReplies` is enabled, and each flag operates independently. + * Added `SuggestedRepliesDirection.VERTICAL` and `SuggestedRepliesDirection.HORIZONTAL` which indicate the direction of the suggested replies in `SuggestedRepliesView`. + * Added `SuggestedRepliesFor.ALL_MESSAGES` and `SuggestedRepliesFor.LAST_MESSAGE_ONLY`, which specify the target messages for suggested replies. + * Added `suggestedRepliesFor` in `ChannelConfig` to set the target messages for suggested replies. + * Added `suggestedRepliesDirection` in `ChannelConfig` to set the direction of the suggested replies.### v3.16.1 (May 3, 2024) with Chat SDK `v4.16.2` * Fixed timeline messages not showing up in the channel. ### v3.16.0 (Apr 25, 2024) with Chat SDK `v4.16.2` Support a way to customise the menu items in the `ChannelSettingsMenuComponent` and `OpenChannelSettingsMenuComponent`. @@ -177,7 +201,7 @@ ViewModelProviders.channel = ChannelViewModelProvider { owner, channelUrl, param * Improved stability ### v3.6.0 (Jun 23, 2023) with Chat SDK `v4.9.1` -* Support feature configuration +* Support feature configuration * Added `UIKitConfig` object * Added `setChannelConfig(ChannelConfig)` in `ChannelFragment.Builder`, `MessageThreadFragment.Builder` * Added `setChanneListConfig(ChannelListConfig)` in `ChannelListFragment.Builder` @@ -290,7 +314,7 @@ We’re excited to announce the launch of Sendbird Notifications v1.0! It’s a * Added `setUseBanner(boolean)` in `MessageListComponent.Params` * Added `setUseUserIdForNickname(boolean)` and `isUsingUserIdForNickname()` in `SendbirdUIKit` -### v3.2.2 (Oct 27, 2022) with Chat SDK `v4.1.1` +### v3.2.2 (Oct 27, 2022) with Chat SDK `v4.1.1` * Added `setOnScrollFirstButtonClickListener(OnConsumableClickListener)` in `ChannelFragment.Builder` and `OpenChannelFragment.Builder` * Added `scrollToFirst()`, `setOnScrollFirstButtonClickListener(OnConsumableClickListener)`, and `onScrollFirstButtonClicked(View)` in `MessageListComponent` and `OpemChannelMessageListComponent` * Deprecated `setOnScrollBottomButtonClickListener(View.OnClickListener)` in `ChannelFragment.Builder` and `OpenChannelFragment.Builder` diff --git a/gradle.properties b/gradle.properties index 955872f9..26c9b6f3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,5 +16,5 @@ org.gradle.jvmargs=-Xmx1536m # https://developer.android.com/topic/libraries/support-library/androidx-rn android.useAndroidX=true -UIKIT_VERSION = 3.16.1 +UIKIT_VERSION = 3.17.0 UIKIT_VERSION_CODE = 1 diff --git a/uikit-samples/src/main/AndroidManifest.xml b/uikit-samples/src/main/AndroidManifest.xml index f5ed60ca..b68a2d75 100644 --- a/uikit-samples/src/main/AndroidManifest.xml +++ b/uikit-samples/src/main/AndroidManifest.xml @@ -57,6 +57,10 @@ android:name=".aichatbot.AIChatBotHomeActivity" android:configChanges="orientation|screenSize|keyboardHidden" android:launchMode="singleTask" /> + + if (error != null) { ContextUtils.toastError(this, "Failed to start chat with ai bot. ${error.message}") diff --git a/uikit-samples/src/main/java/com/sendbird/uikit/samples/aichatbot/AiChatBotLoginActivity.kt b/uikit-samples/src/main/java/com/sendbird/uikit/samples/aichatbot/AiChatBotLoginActivity.kt new file mode 100644 index 00000000..ba771fbb --- /dev/null +++ b/uikit-samples/src/main/java/com/sendbird/uikit/samples/aichatbot/AiChatBotLoginActivity.kt @@ -0,0 +1,52 @@ +package com.sendbird.uikit.samples.aichatbot + +import android.os.Bundle +import android.view.View +import com.sendbird.android.exception.SendbirdException +import com.sendbird.android.push.SendbirdPushHelper +import com.sendbird.android.user.User +import com.sendbird.uikit.log.Logger +import com.sendbird.uikit.samples.common.LoginActivity +import com.sendbird.uikit.samples.common.extensions.authenticate +import com.sendbird.uikit.samples.common.extensions.startingIntent +import com.sendbird.uikit.samples.common.fcm.MyFirebaseMessagingService +import com.sendbird.uikit.samples.common.preferences.PreferenceUtils +import com.sendbird.uikit.samples.common.widgets.WaitingDialog +import com.sendbird.uikit.utils.ContextUtils + +class AiChatBotLoginActivity : LoginActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding.apply { + title.visibility = View.GONE + botIdLayout.visibility = View.VISIBLE + notificationTitle.visibility = View.VISIBLE + botId.setText(PreferenceUtils.botId.ifEmpty { "client_bot" }) + } + } + + override fun onSignUp(userId: String, nickname: String) { + Logger.i(">> AiChatBotLoginActivity::onSignUp(), userId=$userId, nickname=$nickname") + val botId = binding.botId.text.toString() + if (botId.isEmpty()) return + Logger.i("++ onSignUp botId=$botId") + + WaitingDialog.show(this) + PreferenceUtils.botId = botId + authenticate { _: User?, e: SendbirdException? -> + WaitingDialog.dismiss() + if (e != null) { + Logger.e(e) + ContextUtils.toastError(this@AiChatBotLoginActivity, "${e.message}") + return@authenticate + } + PreferenceUtils.userId = userId + PreferenceUtils.nickname = nickname + SendbirdPushHelper.registerPushHandler(MyFirebaseMessagingService()) + val intent = PreferenceUtils.selectedSampleType.startingIntent(this) + startActivity(intent) + finish() + } + } +} diff --git a/uikit-samples/src/main/java/com/sendbird/uikit/samples/common/SelectServiceActivity.kt b/uikit-samples/src/main/java/com/sendbird/uikit/samples/common/SelectServiceActivity.kt index 6ef0e0a9..7a569448 100644 --- a/uikit-samples/src/main/java/com/sendbird/uikit/samples/common/SelectServiceActivity.kt +++ b/uikit-samples/src/main/java/com/sendbird/uikit/samples/common/SelectServiceActivity.kt @@ -10,6 +10,7 @@ import androidx.core.content.ContextCompat import com.sendbird.android.SendbirdChat import com.sendbird.uikit.BuildConfig import com.sendbird.uikit.samples.R +import com.sendbird.uikit.samples.aichatbot.AiChatBotLoginActivity import com.sendbird.uikit.samples.common.consts.SampleType import com.sendbird.uikit.samples.common.preferences.PreferenceUtils import com.sendbird.uikit.samples.databinding.ActivitySelectServiceBinding @@ -36,7 +37,7 @@ class SelectServiceActivity : AppCompatActivity() { aiChatBotSampleButton.setOnClickListener { if (enableAiChatBotSample) { PreferenceUtils.selectedSampleType = SampleType.AiChatBot - startActivity(Intent(this@SelectServiceActivity, LoginActivity::class.java)) + startActivity(Intent(this@SelectServiceActivity, AiChatBotLoginActivity::class.java)) finish() } else { showSampleNotSupported("https://github.com/sendbird/sendbird-uikit-android/tree/main/uikit-samples/src/main/java/com/sendbird/uikit/samples/aichatbot/README.md") 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 021697d2..a3a68cae 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 @@ -14,7 +14,6 @@ import com.sendbird.android.handler.ConnectHandler import com.sendbird.android.handler.PushRequestCompleteHandler import com.sendbird.android.push.SendbirdPushHelper import com.sendbird.uikit.SendbirdUIKit -import com.sendbird.uikit.activities.FeedNotificationChannelActivity import com.sendbird.uikit.log.Logger import com.sendbird.uikit.providers.AdapterProviders import com.sendbird.uikit.providers.FragmentProviders @@ -22,6 +21,7 @@ import com.sendbird.uikit.providers.ModuleProviders import com.sendbird.uikit.providers.ViewModelProviders import com.sendbird.uikit.samples.R import com.sendbird.uikit.samples.aichatbot.AIChatBotHomeActivity +import com.sendbird.uikit.samples.aichatbot.AiChatBotLoginActivity import com.sendbird.uikit.samples.basic.BasicHomeActivity import com.sendbird.uikit.samples.basic.GroupChannelMainActivity import com.sendbird.uikit.samples.common.LoginActivity @@ -31,6 +31,7 @@ import com.sendbird.uikit.samples.common.consts.StringSet import com.sendbird.uikit.samples.common.preferences.PreferenceUtils import com.sendbird.uikit.samples.common.widgets.WaitingDialog import com.sendbird.uikit.samples.customization.CustomizationHomeActivity +import com.sendbird.uikit.samples.notification.FeedChannelListMainActivity import com.sendbird.uikit.samples.notification.NotificationHomeActivity import com.sendbird.uikit.samples.notification.NotificationLoginActivity import com.sendbird.uikit.samples.notification.NotificationMainActivity @@ -42,7 +43,7 @@ internal fun SampleType?.getLogoDrawable(context: Context): Drawable? { SampleType.Basic -> R.drawable.logo_sendbird SampleType.Notification -> R.drawable.logo_business_messaging SampleType.Customization -> R.drawable.logo_sendbird - SampleType.AiChatBot -> R.drawable.logo_sendbird + SampleType.AiChatBot -> R.drawable.logo_ai_chatbot }.let { ContextCompat.getDrawable(context, it) } } @@ -75,7 +76,7 @@ internal fun SampleType?.startingIntent(context: Context): Intent { if (userId.isNotEmpty()) { Intent(context, AIChatBotHomeActivity::class.java) } else { - Intent(context, LoginActivity::class.java) + Intent(context, AiChatBotLoginActivity::class.java) } } } @@ -100,8 +101,11 @@ internal fun SampleType?.newRedirectToChannelIntent( addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) } } else { - FeedNotificationChannelActivity.newIntent(context, channelUrl).apply { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP) + FeedChannelListMainActivity.newRedirectToChannelIntent( + context, + channelUrl, + ).apply { + addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) } } } diff --git a/uikit-samples/src/main/java/com/sendbird/uikit/samples/common/preferences/PreferenceUtils.kt b/uikit-samples/src/main/java/com/sendbird/uikit/samples/common/preferences/PreferenceUtils.kt index 81fc378f..bd917962 100644 --- a/uikit-samples/src/main/java/com/sendbird/uikit/samples/common/preferences/PreferenceUtils.kt +++ b/uikit-samples/src/main/java/com/sendbird/uikit/samples/common/preferences/PreferenceUtils.kt @@ -11,12 +11,12 @@ import com.sendbird.uikit.samples.common.consts.SampleType internal object PreferenceUtils { private const val PREFERENCE_KEY_APP_ID = "PREFERENCE_KEY_APP_ID" private const val PREFERENCE_KEY_USER_ID = "PREFERENCE_KEY_USER_ID" + private const val PREFERENCE_KEY_BOT_ID = "PREFERENCE_KEY_BOT_ID" private const val PREFERENCE_KEY_NICKNAME = "PREFERENCE_KEY_NICKNAME" private const val PREFERENCE_KEY_PROFILE_URL = "PREFERENCE_KEY_PROFILE_URL" private const val PREFERENCE_KEY_THEME_MODE = "PREFERENCE_KEY_THEME_MODE" private const val PREFERENCE_KEY_DO_NOT_DISTURB = "PREFERENCE_KEY_DO_NOT_DISTURB" private const val PREFERENCE_KEY_LATEST_USED_SAMPLE = "PREFERENCE_KEY_LATEST_USED_SAMPLE" - private const val PREFERENCE_KEY_NOTIFICATION_USE_AUTHENTICATE = "PREFERENCE_KEY_NOTIFICATION_USE_AUTHENTICATE" private const val PREFERENCE_KEY_NOTIFICATION_USE_FEED_CHANNEL_ONLY = "PREFERENCE_KEY_NOTIFICATION_USE_FEED_CHANNEL_ONLY" private lateinit var pref: Preference @@ -50,9 +50,9 @@ internal object PreferenceUtils { get() = pref.getBoolean(PREFERENCE_KEY_DO_NOT_DISTURB, false) set(doNotDisturb) = pref.putBoolean(PREFERENCE_KEY_DO_NOT_DISTURB, doNotDisturb) -// var isUsingAuthenticate: Boolean -// get() = pref.getBoolean(PREFERENCE_KEY_NOTIFICATION_USE_AUTHENTICATE, false) -// set(useAuth) = pref.putBoolean(PREFERENCE_KEY_NOTIFICATION_USE_AUTHENTICATE, useAuth) + var botId: String + get() = pref.getString(PREFERENCE_KEY_BOT_ID) ?: "" + set(nickname) = pref.putString(PREFERENCE_KEY_BOT_ID, nickname) var isUsingFeedChannelOnly: Boolean get() = pref.getBoolean(PREFERENCE_KEY_NOTIFICATION_USE_FEED_CHANNEL_ONLY, false) diff --git a/uikit-samples/src/main/java/com/sendbird/uikit/samples/customization/channelsettings/GroupChannelSettingSample.kt b/uikit-samples/src/main/java/com/sendbird/uikit/samples/customization/channelsettings/GroupChannelSettingSample.kt index 7d0adc1b..9ab3ca32 100644 --- a/uikit-samples/src/main/java/com/sendbird/uikit/samples/customization/channelsettings/GroupChannelSettingSample.kt +++ b/uikit-samples/src/main/java/com/sendbird/uikit/samples/customization/channelsettings/GroupChannelSettingSample.kt @@ -15,7 +15,7 @@ fun showAppendNewCustomGroupChannelSettingsMenuSample(activity: Activity) { // The following code is an example of how to customize the Group Channel settings menu. // If you want to handle the CUSTOM menu click event, you should handle it yourself after creating a custom menu view. ModuleProviders.channelSettings = ChannelSettingsModuleProvider { context, _ -> - val module = ChannelSettingsModule(context).apply { + ChannelSettingsModule(context).apply { val customMenuList = ChannelSettingsMenuComponent.defaultMenuSet.toMutableList().apply { add(ChannelSettingsMenuComponent.Menu.CUSTOM) } @@ -26,7 +26,7 @@ fun showAppendNewCustomGroupChannelSettingsMenuSample(activity: Activity) { context, "Go to Chat", null, - SingleMenuType.NEXT, + SingleMenuType.NONE, R.drawable.icon_chat, 0 ).apply { @@ -39,7 +39,6 @@ fun showAppendNewCustomGroupChannelSettingsMenuSample(activity: Activity) { } setChannelSettingsMenuComponent(component) } - module } GroupChannelRepository.getRandomChannel(activity) { channel -> diff --git a/uikit-samples/src/main/java/com/sendbird/uikit/samples/notification/FeedChannelListFragment.kt b/uikit-samples/src/main/java/com/sendbird/uikit/samples/notification/FeedChannelListFragment.kt new file mode 100644 index 00000000..5717c282 --- /dev/null +++ b/uikit-samples/src/main/java/com/sendbird/uikit/samples/notification/FeedChannelListFragment.kt @@ -0,0 +1,63 @@ +package com.sendbird.uikit.samples.notification + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import com.sendbird.android.SendbirdChat +import com.sendbird.uikit.SendbirdUIKit +import com.sendbird.uikit.activities.FeedNotificationChannelActivity +import com.sendbird.uikit.modules.components.HeaderComponent +import com.sendbird.uikit.samples.R +import com.sendbird.uikit.samples.common.extensions.setAppearance +import com.sendbird.uikit.samples.databinding.LayoutFeedChannelListBinding +import com.sendbird.uikit.samples.databinding.ViewFeedChannelItemBinding + +class FeedChannelListFragment : Fragment() { + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + return getContentView(inflater, savedInstanceState) + } + + private fun getContentView(inflater: LayoutInflater, savedInstanceState: Bundle?): View { + val binding = LayoutFeedChannelListBinding.inflate(inflater) + val themeMode = SendbirdUIKit.getDefaultThemeMode() + binding.feedChannelList.setBackgroundResource( + if (themeMode == SendbirdUIKit.ThemeMode.Light) R.color.background_50 else R.color.background_600 + ) + + HeaderComponent().apply { + this.params.title = getString(R.string.text_tab_channels) + this.params.setUseLeftButton(false) + this.params.setUseRightButton(false) + val header = this.onCreateView(requireContext(), inflater, binding.headerComponent, savedInstanceState) + binding.headerComponent.addView(header) + } + + SendbirdChat.appInfo?.notificationInfo?.feedChannels?.let { feedChannels -> + val background = if (themeMode == SendbirdUIKit.ThemeMode.Light) R.drawable.selector_rectangle_light else R.drawable.selector_rectangle_dark600 + val dividerColor = if (themeMode == SendbirdUIKit.ThemeMode.Light) R.color.onlight_04 else R.color.ondark_04 + val channelKeyStyle = if (themeMode == SendbirdUIKit.ThemeMode.Light) R.style.SendbirdSubtitle1OnLight01 else R.style.SendbirdSubtitle1OnDark01 + val channelUrlStyle = if (themeMode == SendbirdUIKit.ThemeMode.Light) R.style.SendbirdBody3OnLight03 else R.style.SendbirdBody3OnDark03 + feedChannels.entries.forEach { entry -> + val itemBinding = ViewFeedChannelItemBinding.inflate(inflater) + itemBinding.root.setBackgroundResource(background) + itemBinding.divider.setBackgroundResource(dividerColor) + itemBinding.tvChannelKey.text = entry.key + itemBinding.tvChannelUrl.text = entry.value + itemBinding.tvChannelKey.setAppearance(requireContext(), channelKeyStyle) + itemBinding.tvChannelUrl.setAppearance(requireContext(), channelUrlStyle) + itemBinding.root.setOnClickListener { + startActivity( + FeedNotificationChannelActivity.newIntent( + requireContext(), + entry.value + ) + ) + } + binding.feedChannelContainer.addView(itemBinding.root) + } + } + return binding.root + } +} diff --git a/uikit-samples/src/main/java/com/sendbird/uikit/samples/notification/FeedChannelListMainActivity.kt b/uikit-samples/src/main/java/com/sendbird/uikit/samples/notification/FeedChannelListMainActivity.kt new file mode 100644 index 00000000..55c01d5b --- /dev/null +++ b/uikit-samples/src/main/java/com/sendbird/uikit/samples/notification/FeedChannelListMainActivity.kt @@ -0,0 +1,186 @@ +package com.sendbird.uikit.samples.notification + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.view.View +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity +import androidx.viewpager2.adapter.FragmentStateAdapter +import com.google.android.material.tabs.TabLayoutMediator +import com.sendbird.android.SendbirdChat.addUserEventHandler +import com.sendbird.android.SendbirdChat.getTotalUnreadMessageCount +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 +import com.sendbird.uikit.activities.FeedNotificationChannelActivity +import com.sendbird.uikit.log.Logger +import com.sendbird.uikit.samples.BaseApplication.Companion.initStateChanges +import com.sendbird.uikit.samples.R +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.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 +import com.sendbird.uikit.samples.common.widgets.WaitingDialog +import com.sendbird.uikit.samples.databinding.ActivityNotificationMainBinding + +class FeedChannelListMainActivity : AppCompatActivity() { + private val binding: ActivityNotificationMainBinding by lazy { + ActivityNotificationMainBinding.inflate(layoutInflater) + } + private val feedChannelListTab: CustomTabView by lazy { + CustomTabView(this).apply { + setBadgeVisibility(View.GONE) + setTitle(getString(R.string.text_tab_notifications)) + setIcon(R.drawable.icon_notifications_filled) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setTheme(SendbirdUIKit.getDefaultThemeMode().resId) + setContentView(binding.root) + + // for redirecting to channel from push notification. + initStateChanges().observe(this) { initState: InitState -> + Logger.i("++ init state : %s", initState) + WaitingDialog.dismiss() + when (initState) { + InitState.NONE -> {} + InitState.MIGRATING -> WaitingDialog.show(this@FeedChannelListMainActivity) + InitState.FAILED, InitState.SUCCEED -> { + WaitingDialog.dismiss() + SendbirdUIKit.connect { _, _ -> initPage() } + } + } + } + } + + override fun onDestroy() { + super.onDestroy() + removeUserEventHandler(USER_EVENT_HANDLER_KEY) + } + + override fun onNewIntent(intent: Intent?) { + super.onNewIntent(intent) + redirectChannelIfNeeded(intent) + } + + private fun initPage() { + val adapter = MainAdapter(this@FeedChannelListMainActivity) + binding.viewPager.adapter = adapter + + val isDarkMode = PreferenceUtils.themeMode.isUsingDarkTheme() + val backgroundRedId = if (isDarkMode) R.color.background_600 else R.color.background_50 + binding.tabLayout.setBackgroundResource(backgroundRedId) + TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position -> + tab.customView = when (position) { + TAB_FEED_CHANNEL_LIST -> feedChannelListTab + TAB_SETTINGS -> CustomTabView(this).apply { + setBadgeVisibility(View.GONE) + setTitle(getString(R.string.text_tab_settings)) + setIcon(R.drawable.icon_settings_filled) + } + else -> null + } + }.attach() + redirectChannelIfNeeded(intent) + + getTotalUnreadMessageCount( + handler = UnreadMessageCountHandler { groupChannelCount: Int, feedChannelTotalCount: Int, e: SendbirdException? -> + if (e != null) { + return@UnreadMessageCountHandler + } + Logger.i("updateChannelListTab [API] groupChannelCount=$groupChannelCount, feedChannelUnreadCount=$feedChannelTotalCount") + drawUnreadCount(feedChannelListTab, feedChannelTotalCount) + } + ) + + addUserEventHandler(USER_EVENT_HANDLER_KEY, object : UserEventHandler() { + override fun onFriendsDiscovered(users: List) {} + override fun onTotalUnreadMessageCountChanged(unreadMessageCount: UnreadMessageCount) { + val groupChannelCount = unreadMessageCount.groupChannelCount + val feedChannelUnreadCount = unreadMessageCount.feedChannelCount + Logger.i("updateChannelListTab groupChannelCount=$groupChannelCount, feedChannelUnreadCount=$feedChannelUnreadCount") + drawUnreadCount(feedChannelListTab, feedChannelUnreadCount) + } + }) + } + + @Synchronized + private fun drawUnreadCount(tabView: CustomTabView, count: Int) { + if (count > 0) { + tabView.setBadgeVisibility(View.VISIBLE) + tabView.setBadgeCount(if (count > 99) getString(R.string.text_tab_badge_max_count) else count.toString()) + } else { + tabView.setBadgeVisibility(View.GONE) + } + } + + private fun redirectChannelIfNeeded(intent: Intent?) { + if (intent == null) return + 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() + 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.isNullOrEmpty()) return + + binding.viewPager.currentItem = TAB_FEED_CHANNEL_LIST + startActivity(FeedNotificationChannelActivity.newIntent(this, channelUrl)) + } + } + + private class MainAdapter(val fa: FragmentActivity) : FragmentStateAdapter(fa) { + override fun getItemCount(): Int = 2 + override fun createFragment(position: Int): Fragment { + return when (position) { + TAB_FEED_CHANNEL_LIST -> FeedChannelListFragment() + TAB_SETTINGS -> SampleSettingsFragment() + else -> Fragment() + } + } + + fun getItem(position: Int): Fragment? { + return fa.supportFragmentManager.findFragmentByTag("f$position") + } + } + + companion object { + private val USER_EVENT_HANDLER_KEY = "USER_EVENT_HANDLER_KEY" + System.currentTimeMillis() + private const val TAB_FEED_CHANNEL_LIST = 0 + private const val TAB_SETTINGS = 1 + fun newRedirectToChannelIntent( + context: Context, + channelUrl: String, + ): Intent { + return Intent(context, FeedChannelListMainActivity::class.java).apply { + putExtra(StringSet.PUSH_REDIRECT_CHANNEL, channelUrl) + } + } + } +} diff --git a/uikit-samples/src/main/java/com/sendbird/uikit/samples/notification/NotificationHomeActivity.kt b/uikit-samples/src/main/java/com/sendbird/uikit/samples/notification/NotificationHomeActivity.kt index f3b9d8e0..d00d5e66 100644 --- a/uikit-samples/src/main/java/com/sendbird/uikit/samples/notification/NotificationHomeActivity.kt +++ b/uikit-samples/src/main/java/com/sendbird/uikit/samples/notification/NotificationHomeActivity.kt @@ -13,10 +13,8 @@ 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 -import com.sendbird.uikit.samples.common.extensions.getFeedChannelUrl import com.sendbird.uikit.samples.common.extensions.logout import com.sendbird.uikit.samples.common.extensions.setTextColorResource import com.sendbird.uikit.samples.common.preferences.PreferenceUtils @@ -38,12 +36,7 @@ class NotificationHomeActivity : ThemeHomeActivity() { startActivity(Intent(this@NotificationHomeActivity, NotificationMainActivity::class.java)) } feedOnlyButton.setOnClickListener { - startActivity( - FeedNotificationChannelActivity.newIntent( - this@NotificationHomeActivity, - getFeedChannelUrl() - ) - ) + startActivity(Intent(this@NotificationHomeActivity, FeedChannelListMainActivity::class.java)) } btSignOut.setOnClickListener { logout() } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { diff --git a/uikit-samples/src/main/res/drawable-hdpi/icon_feed_channel.png b/uikit-samples/src/main/res/drawable-hdpi/icon_feed_channel.png new file mode 100644 index 00000000..69828bf1 Binary files /dev/null and b/uikit-samples/src/main/res/drawable-hdpi/icon_feed_channel.png differ diff --git a/uikit-samples/src/main/res/drawable-hdpi/logo_ai_chatbot.png b/uikit-samples/src/main/res/drawable-hdpi/logo_ai_chatbot.png new file mode 100644 index 00000000..3f75df51 Binary files /dev/null and b/uikit-samples/src/main/res/drawable-hdpi/logo_ai_chatbot.png differ diff --git a/uikit-samples/src/main/res/drawable-mdpi/icon_feed_channel.png b/uikit-samples/src/main/res/drawable-mdpi/icon_feed_channel.png new file mode 100644 index 00000000..c8ea1a60 Binary files /dev/null and b/uikit-samples/src/main/res/drawable-mdpi/icon_feed_channel.png differ diff --git a/uikit-samples/src/main/res/drawable-mdpi/logo_ai_chatbot.png b/uikit-samples/src/main/res/drawable-mdpi/logo_ai_chatbot.png new file mode 100644 index 00000000..7a0bbe62 Binary files /dev/null and b/uikit-samples/src/main/res/drawable-mdpi/logo_ai_chatbot.png differ diff --git a/uikit-samples/src/main/res/drawable-xhdpi/icon_feed_channel.png b/uikit-samples/src/main/res/drawable-xhdpi/icon_feed_channel.png new file mode 100644 index 00000000..c7d57a0a Binary files /dev/null and b/uikit-samples/src/main/res/drawable-xhdpi/icon_feed_channel.png differ diff --git a/uikit-samples/src/main/res/drawable-xhdpi/logo_ai_chatbot.png b/uikit-samples/src/main/res/drawable-xhdpi/logo_ai_chatbot.png new file mode 100644 index 00000000..f568d287 Binary files /dev/null and b/uikit-samples/src/main/res/drawable-xhdpi/logo_ai_chatbot.png differ diff --git a/uikit-samples/src/main/res/drawable-xxhdpi/icon_feed_channel.png b/uikit-samples/src/main/res/drawable-xxhdpi/icon_feed_channel.png new file mode 100644 index 00000000..88d29218 Binary files /dev/null and b/uikit-samples/src/main/res/drawable-xxhdpi/icon_feed_channel.png differ diff --git a/uikit-samples/src/main/res/drawable-xxhdpi/logo_ai_chatbot.png b/uikit-samples/src/main/res/drawable-xxhdpi/logo_ai_chatbot.png new file mode 100644 index 00000000..3013256d Binary files /dev/null and b/uikit-samples/src/main/res/drawable-xxhdpi/logo_ai_chatbot.png differ diff --git a/uikit-samples/src/main/res/drawable-xxxhdpi/icon_feed_channel.png b/uikit-samples/src/main/res/drawable-xxxhdpi/icon_feed_channel.png new file mode 100644 index 00000000..67ac9506 Binary files /dev/null and b/uikit-samples/src/main/res/drawable-xxxhdpi/icon_feed_channel.png differ diff --git a/uikit-samples/src/main/res/drawable-xxxhdpi/logo_ai_chatbot.png b/uikit-samples/src/main/res/drawable-xxxhdpi/logo_ai_chatbot.png new file mode 100644 index 00000000..dd72adc7 Binary files /dev/null and b/uikit-samples/src/main/res/drawable-xxxhdpi/logo_ai_chatbot.png differ diff --git a/uikit-samples/src/main/res/layout/activity_login.xml b/uikit-samples/src/main/res/layout/activity_login.xml index f131f689..7bbc24c5 100644 --- a/uikit-samples/src/main/res/layout/activity_login.xml +++ b/uikit-samples/src/main/res/layout/activity_login.xml @@ -26,17 +26,17 @@ - + app:layout_constraintEnd_toStartOf="@id/saveButton"> + + + +