From 8c4b4b992b8447f58e28035749640b775437cc74 Mon Sep 17 00:00:00 2001 From: Evgenii Kozlov Date: Thu, 22 May 2025 14:28:00 +0200 Subject: [PATCH] DROID-3637 Chats | Fix | Opening chats from push notifications - fixes (#2435) --- .../anytype/device/AnytypePushService.kt | 13 +++- .../anytype/ui/splash/SplashFragment.kt | 77 ++++++++++++++----- .../presentation/main/MainViewModel.kt | 1 + .../presentation/splash/SplashViewModel.kt | 18 +++++ 4 files changed, 87 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/com/anytypeio/anytype/device/AnytypePushService.kt b/app/src/main/java/com/anytypeio/anytype/device/AnytypePushService.kt index 92fc1bc3ac..61eeda1068 100644 --- a/app/src/main/java/com/anytypeio/anytype/device/AnytypePushService.kt +++ b/app/src/main/java/com/anytypeio/anytype/device/AnytypePushService.kt @@ -11,6 +11,7 @@ import androidx.core.app.NotificationCompat import com.anytypeio.anytype.R import com.anytypeio.anytype.app.AndroidApplication import com.anytypeio.anytype.core_models.DecryptedPushContent +import com.anytypeio.anytype.core_models.Id import com.anytypeio.anytype.core_models.Relations import com.anytypeio.anytype.core_ui.views.Relations1 import com.anytypeio.anytype.domain.device.DeviceTokenStoringService @@ -80,12 +81,18 @@ class AnytypePushService : FirebaseMessagingService() { private fun handleDecryptedContent(content: DecryptedPushContent) { Timber.d("Decrypted content: $content") when (content.type) { - 1 -> handleNewMessage(content.newMessage) + 1 -> handleNewMessage( + message = content.newMessage, + space = content.spaceId + ) else -> Timber.w("Unknown message type: ${content.type}") } } - private fun handleNewMessage(message: DecryptedPushContent.Message) { + private fun handleNewMessage( + message: DecryptedPushContent.Message, + space: Id + ) { Timber.d("New message received: $message") // Create an intent to open the app when notification is tapped @@ -93,7 +100,7 @@ class AnytypePushService : FirebaseMessagingService() { action = ACTION_OPEN_CHAT flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP putExtra(Relations.CHAT_ID, message.chatId) - putExtra(Relations.SPACE_ID, message.spaceName) + putExtra(Relations.SPACE_ID, space) } val pendingIntent = PendingIntent.getActivity( diff --git a/app/src/main/java/com/anytypeio/anytype/ui/splash/SplashFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/splash/SplashFragment.kt index fa34886205..9e9704c106 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/splash/SplashFragment.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/splash/SplashFragment.kt @@ -13,12 +13,14 @@ import androidx.navigation.fragment.findNavController import com.anytypeio.anytype.BuildConfig import com.anytypeio.anytype.R import com.anytypeio.anytype.app.DefaultAppActionManager.Companion.ACTION_CREATE_NEW_TYPE_KEY +import com.anytypeio.anytype.core_models.Relations import com.anytypeio.anytype.core_utils.ext.gone import com.anytypeio.anytype.core_utils.ext.orNull import com.anytypeio.anytype.core_utils.ext.toast import com.anytypeio.anytype.core_utils.ext.visible import com.anytypeio.anytype.core_utils.ui.BaseFragment import com.anytypeio.anytype.databinding.FragmentSplashBinding +import com.anytypeio.anytype.device.AnytypePushService import com.anytypeio.anytype.di.common.componentManager import com.anytypeio.anytype.other.DefaultDeepLinkResolver import com.anytypeio.anytype.presentation.confgs.ChatConfig @@ -200,6 +202,27 @@ class SplashFragment : BaseFragment(R.layout.fragment_spl Timber.e(it, "Error while navigating to object from splash") } } + is SplashViewModel.Command.NavigateToChat -> { + runCatching { + findNavController().navigate(R.id.actionOpenVaultFromSplash) + findNavController().navigate( + R.id.actionOpenSpaceFromVault, + args = HomeScreenFragment.args( + space = command.space, + deeplink = null + ) + ) + findNavController().navigate( + R.id.chatScreen, + args = ChatFragment.args( + space = command.space, + ctx = command.chat + ) + ) + }.onFailure { + Timber.e(it, "Error while navigating to chat from push") + } + } is SplashViewModel.Command.NavigateToObjectType -> { runCatching { findNavController().navigate(R.id.actionOpenVaultFromSplash) @@ -324,32 +347,48 @@ class SplashFragment : BaseFragment(R.layout.fragment_spl } is SplashViewModel.Command.CheckAppStartIntent -> { val intent = activity?.intent - if (intent != null && (intent.action == Intent.ACTION_VIEW || intent.action == Intent.ACTION_SEND)) { - val data = intent.dataString.orNull() ?: intent.extras?.getString(Intent.EXTRA_TEXT) - if (data != null && DefaultDeepLinkResolver.isDeepLink(data)) { - // Clearing intent to only handle it once: - with(intent) { - setAction(null) - setData(null) - putExtras(Bundle()) - } - vm.onDeepLinkLaunch(data) - } else { - val bundle = intent.extras - if (bundle != null) { - val type = bundle.getString(ACTION_CREATE_NEW_TYPE_KEY) - if (type != null) { - vm.onIntentCreateNewObject(type = type) + Timber.d("Checking app start intent: $intent, action: ${intent?.action}") + when { + intent != null && (intent.action == Intent.ACTION_VIEW || intent.action == Intent.ACTION_SEND) -> { + val data = + intent.dataString.orNull() ?: intent.extras?.getString(Intent.EXTRA_TEXT) + if (data != null && DefaultDeepLinkResolver.isDeepLink(data)) { + // Clearing intent to only handle it once: + with(intent) { + setAction(null) + setData(null) + putExtras(Bundle()) + } + vm.onDeepLinkLaunch(data) + } else { + val bundle = intent.extras + if (bundle != null) { + val type = bundle.getString(ACTION_CREATE_NEW_TYPE_KEY) + if (type != null) { + vm.onIntentCreateNewObject(type = type) + } else { + vm.onIntentActionNotFound() + } } else { vm.onIntentActionNotFound() } + } + } + intent?.action == AnytypePushService.ACTION_OPEN_CHAT -> { + val chatId = intent.getStringExtra(Relations.CHAT_ID) + val spaceId = intent.getStringExtra(Relations.SPACE_ID) + if (!chatId.isNullOrEmpty() && !spaceId.isNullOrEmpty()) { + vm.onIntentTriggeredByChatPush( + space = spaceId, + chat = chatId + ) } else { vm.onIntentActionNotFound() } } - } - else { - vm.onIntentActionNotFound() + else -> { + vm.onIntentActionNotFound() + } } } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/main/MainViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/main/MainViewModel.kt index 0367d04cae..9ea02691c4 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/main/MainViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/main/MainViewModel.kt @@ -453,6 +453,7 @@ class MainViewModel( } fun onOpenChatTriggeredByPush(chatId: String, spaceId: String) { + Timber.d("onOpenChatTriggeredByPush: $chatId, $spaceId") viewModelScope.launch { if (spaceManager.get() != spaceId) { spaceManager.set(spaceId) diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/splash/SplashViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/splash/SplashViewModel.kt index c0ded29a5e..345bfb8c6c 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/splash/SplashViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/splash/SplashViewModel.kt @@ -278,6 +278,23 @@ class SplashViewModel( } } + fun onIntentTriggeredByChatPush(space: Id, chat: Id) { + viewModelScope.launch { + spaceManager.set(space = space) + .onSuccess { + commands.emit( + Command.NavigateToChat( + space = space, + chat = chat + ) + ) + } + .onFailure { + Timber.e(it, "Error while setting space due to chat intent") + } + } + } + fun onIntentActionNotFound() { proceedWithNavigation() } @@ -463,6 +480,7 @@ class SplashViewModel( data object NavigateToAuthStart : Command() data object CheckAppStartIntent : Command() data class NavigateToObject(val id: Id, val space: Id, val chat: Id?) : Command() + data class NavigateToChat(val space: Id, val chat: Id) : Command() data class NavigateToObjectSet(val id: Id, val space: Id, val chat: Id?) : Command() data class NavigateToDateObject(val id: Id, val space: Id, val chat: Id?) : Command() data class NavigateToObjectType(val id: Id, val space: Id, val chat: Id?) : Command()