From 9416305f6112a87fba479e7b73d1dcb26658ee14 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 28 Mar 2024 16:26:37 +0100 Subject: [PATCH] Added locus ID management in conversation --- .../compatibility/Api29Compatibility.kt | 17 ++++++++++++++ .../linphone/compatibility/Compatibility.kt | 18 +++++++++++++++ .../java/org/linphone/ui/main/MainActivity.kt | 22 +++++++++++++++++++ .../chat/fragment/ConversationFragment.kt | 10 ++++----- .../AbstractConversationViewModel.kt | 4 ++-- 5 files changed, 63 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/linphone/compatibility/Api29Compatibility.kt b/app/src/main/java/org/linphone/compatibility/Api29Compatibility.kt index a3525ea92..d7bcd9d9a 100644 --- a/app/src/main/java/org/linphone/compatibility/Api29Compatibility.kt +++ b/app/src/main/java/org/linphone/compatibility/Api29Compatibility.kt @@ -19,10 +19,15 @@ */ package org.linphone.compatibility +import android.content.Intent import android.net.Uri import android.os.Build import android.provider.MediaStore +import android.view.View +import android.view.contentcapture.ContentCaptureContext +import android.view.contentcapture.ContentCaptureSession import androidx.annotation.RequiresApi +import org.linphone.utils.LinphoneUtils @RequiresApi(Build.VERSION_CODES.Q) class Api29Compatibility { @@ -49,5 +54,17 @@ class Api29Compatibility { else -> Uri.EMPTY } } + + fun extractLocusIdFromIntent(intent: Intent): String? { + return intent.getStringExtra(Intent.EXTRA_LOCUS_ID) + } + + fun setLocusIdInContentCaptureSession(root: View, localSipUri: String, remoteSipUri: String) { + val session: ContentCaptureSession? = root.contentCaptureSession + if (session != null) { + val id = LinphoneUtils.getChatRoomId(localSipUri, remoteSipUri) + session.contentCaptureContext = ContentCaptureContext.forLocusId(id) + } + } } } diff --git a/app/src/main/java/org/linphone/compatibility/Compatibility.kt b/app/src/main/java/org/linphone/compatibility/Compatibility.kt index 13f5f3a75..385c0ee56 100644 --- a/app/src/main/java/org/linphone/compatibility/Compatibility.kt +++ b/app/src/main/java/org/linphone/compatibility/Compatibility.kt @@ -24,6 +24,7 @@ import android.annotation.SuppressLint import android.app.Notification import android.app.Service import android.content.Context +import android.content.Intent import android.net.Uri import android.view.View import androidx.appcompat.app.AppCompatDelegate @@ -133,5 +134,22 @@ class Compatibility { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) } } + + fun extractLocusIdFromIntent(intent: Intent): String? { + if (Version.sdkAboveOrEqual(Version.API29_ANDROID_10)) { + return Api29Compatibility.extractLocusIdFromIntent(intent) + } + return null + } + + fun setLocusIdInContentCaptureSession(root: View, localSipUri: String, remoteSipUri: String) { + if (Version.sdkAboveOrEqual(Version.API29_ANDROID_10)) { + return Api29Compatibility.setLocusIdInContentCaptureSession( + root, + localSipUri, + remoteSipUri + ) + } + } } } diff --git a/app/src/main/java/org/linphone/ui/main/MainActivity.kt b/app/src/main/java/org/linphone/ui/main/MainActivity.kt index 9fa787437..21d6a161b 100644 --- a/app/src/main/java/org/linphone/ui/main/MainActivity.kt +++ b/app/src/main/java/org/linphone/ui/main/MainActivity.kt @@ -51,6 +51,7 @@ import kotlinx.coroutines.withContext import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.LinphoneApplication.Companion.corePreferences import org.linphone.R +import org.linphone.compatibility.Compatibility import org.linphone.core.tools.Log import org.linphone.databinding.MainActivityBinding import org.linphone.ui.GenericActivity @@ -396,12 +397,33 @@ class MainActivity : GenericActivity() { Intent.ACTION_VIEW, Intent.ACTION_DIAL, Intent.ACTION_CALL -> { handleCallIntent(intent) } + Intent.ACTION_VIEW_LOCUS -> { + val locus = Compatibility.extractLocusIdFromIntent(intent) + if (locus != null) { + Log.i("$TAG Found chat room locus intent extra: $locus") + handleLocusOrShortcut(locus) + } + } else -> { handleMainIntent(intent, isNewIntent) } } } + @MainThread + private fun handleLocusOrShortcut(id: String) { + Log.i("$TAG Found locus ID [$id]") + val pair = LinphoneUtils.getLocalAndPeerSipUrisFromChatRoomId(id) + if (pair != null) { + val localSipUri = pair.first + val remoteSipUri = pair.second + Log.i( + "$TAG Navigating to conversation with local [$localSipUri] and peer [$remoteSipUri] addresses, computed from shortcut ID" + ) + sharedViewModel.showConversationEvent.value = Event(pair) + } + } + @MainThread private fun handleMainIntent(intent: Intent, isNewIntent: Boolean) { // Prevent navigating to default fragment upon rotation (we only want to do it on first start) diff --git a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt index 7d5c496a2..21faecaf3 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt @@ -185,10 +185,7 @@ class ConversationFragment : SlidingPaneChildFragment() { private val dataObserver = object : AdapterDataObserver() { override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { - if (positionStart > 0 && positionStart == adapter.itemCount - itemCount) { - Log.i( - "$TAG Item(s) inserted at the end, notify item changed at position [${positionStart - 1}]" - ) + if (positionStart > 0) { adapter.notifyItemChanged(positionStart - 1) // For grouping purposes } @@ -202,14 +199,14 @@ class ConversationFragment : SlidingPaneChildFragment() { if (positionStart == 0 && adapter.itemCount == itemCount) { // First time we fill the list with messages Log.i( - "$TAG [$itemCount] events have been loaded, scrolling to first unread message" + "$TAG [$itemCount] events have been loaded" ) } else { Log.i( "$TAG [$itemCount] new events have been loaded, scrolling to first unread message" ) + scrollToFirstUnreadMessageOrBottom() } - scrollToFirstUnreadMessageOrBottom() } } @@ -372,6 +369,7 @@ class ConversationFragment : SlidingPaneChildFragment() { ) val chatRoom = sharedViewModel.displayedChatRoom viewModel.findChatRoom(chatRoom, localSipUri, remoteSipUri) + Compatibility.setLocusIdInContentCaptureSession(binding.root, localSipUri, remoteSipUri) viewModel.chatRoomFoundEvent.observe(viewLifecycleOwner) { it.consume { found -> diff --git a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/AbstractConversationViewModel.kt b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/AbstractConversationViewModel.kt index 14f8416ee..8a55a5d6d 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/AbstractConversationViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/AbstractConversationViewModel.kt @@ -23,7 +23,7 @@ import androidx.annotation.UiThread import androidx.annotation.WorkerThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import org.linphone.LinphoneApplication +import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.core.ChatRoom import org.linphone.core.Factory import org.linphone.core.tools.Log @@ -61,7 +61,7 @@ abstract class AbstractConversationViewModel : ViewModel() { this.localSipUri = localSipUri this.remoteSipUri = remoteSipUri - LinphoneApplication.coreContext.postOnCoreThread { core -> + coreContext.postOnCoreThread { core -> Log.i( "$TAG Looking for conversation with local SIP URI [$localSipUri] and remote SIP URI [$remoteSipUri]" )