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 f0c7719a3..2522beff2 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 @@ -32,11 +32,13 @@ import android.net.Uri import android.os.Bundle import android.text.Editable import android.text.TextWatcher +import android.view.Gravity import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.view.Window import android.view.WindowManager +import android.widget.PopupWindow import androidx.activity.result.PickVisualMediaRequest import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.UiThread @@ -68,6 +70,7 @@ import org.linphone.core.ChatMessage import org.linphone.core.tools.Log import org.linphone.databinding.ChatBubbleLongPressMenuBinding import org.linphone.databinding.ChatConversationFragmentBinding +import org.linphone.databinding.ChatConversationPopupMenuBinding import org.linphone.ui.main.MainActivity import org.linphone.ui.main.chat.adapter.ConversationEventAdapter import org.linphone.ui.main.chat.adapter.MessageBottomSheetAdapter @@ -180,13 +183,12 @@ class ConversationFragment : SlidingPaneChildFragment() { Log.i( "$TAG [$itemCount] events have been loaded, scrolling to first unread message" ) - scrollToFirstUnreadMessageOrBottom(false) } else { Log.i( "$TAG [$itemCount] new events have been loaded, scrolling to first unread message" ) - scrollToFirstUnreadMessageOrBottom(true) } + scrollToFirstUnreadMessageOrBottom(false) } } @@ -384,6 +386,10 @@ class ConversationFragment : SlidingPaneChildFragment() { } } + binding.setShowMenuClickListener { + showPopupMenu(binding.showMenu) + } + binding.setOpenFilePickerClickListener { Log.i("$TAG Opening media picker") pickMedia.launch( @@ -426,14 +432,7 @@ class ConversationFragment : SlidingPaneChildFragment() { } binding.setGoToInfoClickListener { - if (findNavController().currentDestination?.id == R.id.conversationFragment) { - val action = - ConversationFragmentDirections.actionConversationFragmentToConversationInfoFragment( - localSipUri, - remoteSipUri - ) - findNavController().navigate(action) - } + goToInfoFragment() } binding.setScrollToBottomClickListener { @@ -679,6 +678,49 @@ class ConversationFragment : SlidingPaneChildFragment() { } } + private fun goToInfoFragment() { + Log.i("TAG Navigating to info fragment") + if (findNavController().currentDestination?.id == R.id.conversationFragment) { + val action = + ConversationFragmentDirections.actionConversationFragmentToConversationInfoFragment( + viewModel.localSipUri, + viewModel.remoteSipUri + ) + findNavController().navigate(action) + } + } + + private fun showPopupMenu(view: View) { + val popupView: ChatConversationPopupMenuBinding = DataBindingUtil.inflate( + LayoutInflater.from(requireContext()), + R.layout.chat_conversation_popup_menu, + null, + false + ) + + val popupWindow = PopupWindow( + popupView.root, + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT, + true + ) + + popupView.setGoToInfoClickListener { + goToInfoFragment() + popupWindow.dismiss() + } + + popupView.setSearchClickListener { + Log.i("$TAG Opening search bar") + viewModel.openSearchBar() + popupWindow.dismiss() + } + + // Elevation is for showing a shadow around the popup + popupWindow.elevation = 20f + popupWindow.showAsDropDown(view, 0, 0, Gravity.BOTTOM) + } + private fun showChatMessageLongPressMenu(chatMessageModel: MessageModel) { Compatibility.setBlurRenderEffect(binding.root) diff --git a/app/src/main/java/org/linphone/ui/main/chat/model/MessageModel.kt b/app/src/main/java/org/linphone/ui/main/chat/model/MessageModel.kt index f12377e55..7d3fc46ce 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/model/MessageModel.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/model/MessageModel.kt @@ -375,6 +375,9 @@ class MessageModel @WorkerThread constructor( if (name.isNotEmpty()) { val fileModel = if (isOutgoing && chatMessage.isFileTransferInProgress) { val path = content.filePath ?: "" + if (filesContentCount == 1) { + firstImagePath.postValue(path) + } FileModel(path, name, content.fileSize.toLong(), false) { model -> onContentClicked?.invoke(model.file) } diff --git a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationInfoViewModel.kt b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationInfoViewModel.kt index 197fbd0dd..b0aca27e6 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationInfoViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationInfoViewModel.kt @@ -288,11 +288,12 @@ class ConversationInfoViewModel @UiThread constructor() : ViewModel() { fun call() { coreContext.postOnCoreThread { core -> if (LinphoneUtils.isChatRoomAGroup(chatRoom)) { - // TODO + // TODO: group chat room call } else { val firstParticipant = chatRoom.participants.firstOrNull() val address = firstParticipant?.address if (address != null) { + Log.i("$TAG Audio calling SIP address [${address.asStringUriOnly()}]") val params = core.createCallParams(null) params?.isVideoEnabled = false coreContext.startCall(address, params) diff --git a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationViewModel.kt b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationViewModel.kt index 6841f053e..e8fadef6e 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/ConversationViewModel.kt @@ -91,6 +91,10 @@ class ConversationViewModel @UiThread constructor() : ViewModel() { lateinit var chatRoom: ChatRoom + lateinit var localSipUri: String + + lateinit var remoteSipUri: String + private val chatRoomListener = object : ChatRoomListenerStub() { @WorkerThread override fun onStateChanged(chatRoom: ChatRoom, newState: ChatRoom.State?) { @@ -269,6 +273,9 @@ class ConversationViewModel @UiThread constructor() : ViewModel() { @UiThread fun findChatRoom(room: ChatRoom?, localSipUri: String, remoteSipUri: String) { + this.localSipUri = localSipUri + this.remoteSipUri = remoteSipUri + coreContext.postOnCoreThread { core -> Log.i( "$TAG Looking for conversation with local SIP URI [$localSipUri] and remote SIP URI [$remoteSipUri]" @@ -361,6 +368,24 @@ class ConversationViewModel @UiThread constructor() : ViewModel() { } } + @UiThread + fun startCall() { + coreContext.postOnCoreThread { core -> + if (LinphoneUtils.isChatRoomAGroup(chatRoom)) { + // TODO: group chat room call + } else { + val firstParticipant = chatRoom.participants.firstOrNull() + val address = firstParticipant?.address + if (address != null) { + Log.i("$TAG Audio calling SIP address [${address.asStringUriOnly()}]") + val params = core.createCallParams(null) + params?.isVideoEnabled = false + coreContext.startCall(address, params) + } + } + } + } + @WorkerThread private fun configureChatRoom() { scrollingPosition = SCROLLING_POSITION_NOT_SET diff --git a/app/src/main/res/layout/chat_conversation_fragment.xml b/app/src/main/res/layout/chat_conversation_fragment.xml index 05c40ac03..e89742b3c 100644 --- a/app/src/main/res/layout/chat_conversation_fragment.xml +++ b/app/src/main/res/layout/chat_conversation_fragment.xml @@ -10,15 +10,12 @@ - - + @@ -48,7 +45,7 @@ diff --git a/app/src/main/res/layout/chat_conversation_popup_menu.xml b/app/src/main/res/layout/chat_conversation_popup_menu.xml new file mode 100644 index 000000000..105cea437 --- /dev/null +++ b/app/src/main/res/layout/chat_conversation_popup_menu.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 333ad17d8..7fbfbcbba 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -408,6 +408,8 @@ Add participants Replying to: + Search + Conversation info Group members Add participants