From 34936eaec849e03aedeadf93947330d4fb7ec360 Mon Sep 17 00:00:00 2001 From: Marcel Hibbe Date: Thu, 28 May 2026 14:09:48 +0200 Subject: [PATCH] fix: navigate back to primary task when leaving permanent call room When multiple app instances run in separate tasks (e.g. opened via a notification), leaving a voice/permanent call room previously started a new ConversationsListActivity on top of the call task instead of returning to the existing app task. This caused duplicate task stacks. Now the call task finds the existing primary task (preferring one rooted at MainActivity) and navigates it to ConversationsListActivity, removes any stray non-call tasks, and uses finishAndRemoveTask() to fully clean up the call task. Falls back to launching MainActivity fresh if no existing task is found. AI-assistant: Claude Code v2.1.142 (Claude Sonnet 4.6) Signed-off-by: Marcel Hibbe --- .../nextcloud/talk/activities/CallActivity.kt | 55 ++++++++++++++++++- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt index bc4026a087..c8189ccec2 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt @@ -11,6 +11,7 @@ package com.nextcloud.talk.activities import android.Manifest import android.annotation.SuppressLint +import android.app.ActivityManager import android.app.PendingIntent import android.app.RemoteAction import android.content.BroadcastReceiver @@ -78,6 +79,7 @@ import com.nextcloud.talk.camera.BackgroundBlurFrameProcessor import com.nextcloud.talk.camera.BlurBackgroundViewModel import com.nextcloud.talk.camera.BlurBackgroundViewModel.BackgroundBlurOn import com.nextcloud.talk.chat.ChatActivity +import com.nextcloud.talk.callnotification.CallNotificationActivity import com.nextcloud.talk.conversationlist.ConversationsListActivity import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.databinding.CallActivityBinding @@ -2049,9 +2051,8 @@ class CallActivity : CallBaseActivity() { } if (conversationModel?.checkIfVoiceRoom() == true) { - val intent = Intent(context, ConversationsListActivity::class.java) - startActivity(intent) - finish() + openConversationListInPrimaryTask() + finishAndRemoveTask() } else if (switchToRoomToken.isNotEmpty()) { val intent = Intent(context, ChatActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) @@ -2083,6 +2084,54 @@ class CallActivity : CallBaseActivity() { }) } + private fun openConversationListInPrimaryTask() { + val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as? ActivityManager + val appTasks = activityManager + ?.appTasks + ?.filter { appTask -> appTask.taskInfo?.baseActivity?.packageName == packageName } + .orEmpty() + + val primaryTask = appTasks.firstOrNull { appTask -> + val taskInfo = appTask.taskInfo + val baseActivityName = taskInfo?.baseActivity?.className + taskInfo != null && + taskInfo.taskId != taskId && + baseActivityName == MainActivity::class.java.name + } ?: appTasks.firstOrNull { appTask -> + val taskInfo = appTask.taskInfo + val baseActivityName = taskInfo?.baseActivity?.className + taskInfo != null && + taskInfo.taskId != taskId && + baseActivityName != CallActivity::class.java.name && + baseActivityName != CallNotificationActivity::class.java.name + } + + if (primaryTask != null) { + val intent = Intent(context, ConversationsListActivity::class.java).apply { + addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP) + } + primaryTask.startActivity(context, intent, null) + primaryTask.moveToFront() + val primaryTaskId = primaryTask.taskInfo?.taskId + appTasks + .filter { appTask -> + val taskInfo = appTask.taskInfo + val baseActivityName = taskInfo?.baseActivity?.className + val isCallTask = baseActivityName == CallActivity::class.java.name || + baseActivityName == CallNotificationActivity::class.java.name + taskInfo != null && !isCallTask && taskInfo.taskId != primaryTaskId && taskInfo.taskId != taskId + } + .forEach { it.finishAndRemoveTask() } + } else { + val mainIntent = Intent(context, MainActivity::class.java).apply { + action = Intent.ACTION_MAIN + addCategory(Intent.CATEGORY_LAUNCHER) + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) + } + startActivity(mainIntent) + } + } + private fun startVideoCapture(isPortrait: Boolean) { val (width, height) = if (isPortrait) { WIDTH_4_TO_3_RATIO to HEIGHT_4_TO_3_RATIO