Reworked chat room menu + prepared ephemeral session mode + fixed one-to-one not encrypted chat room menu visible
This commit is contained in:
parent
7f6078737c
commit
3a8b892ee1
13 changed files with 173 additions and 72 deletions
|
@ -26,14 +26,11 @@ import android.content.pm.PackageManager
|
|||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.provider.MediaStore
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import androidx.appcompat.view.menu.MenuBuilder
|
||||
import androidx.appcompat.view.menu.MenuPopupHelper
|
||||
import android.view.*
|
||||
import android.widget.PopupWindow
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.core.view.doOnPreDraw
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
|
@ -62,6 +59,7 @@ import org.linphone.compatibility.Compatibility
|
|||
import org.linphone.core.*
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.ChatRoomDetailFragmentBinding
|
||||
import org.linphone.databinding.ChatRoomMenuBindingImpl
|
||||
import org.linphone.utils.*
|
||||
import org.linphone.utils.Event
|
||||
|
||||
|
@ -620,53 +618,71 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
|||
}
|
||||
|
||||
private fun showPopupMenu(chatRoom: ChatRoom) {
|
||||
val builder = MenuBuilder(requireContext())
|
||||
val popupMenu = MenuPopupHelper(requireContext(), builder, binding.menu)
|
||||
popupMenu.setForceShowIcon(true)
|
||||
val popupView: ChatRoomMenuBindingImpl = DataBindingUtil.inflate(
|
||||
LayoutInflater.from(context),
|
||||
R.layout.chat_room_menu, null, false
|
||||
)
|
||||
|
||||
MenuInflater(requireContext()).inflate(R.menu.chat_room_menu, builder)
|
||||
val itemSize = AppUtils.getDimension(R.dimen.chat_room_popup_item_height).toInt()
|
||||
var totalSize = itemSize * 4
|
||||
|
||||
if (!viewModel.encryptedChatRoom) {
|
||||
popupView.devicesHidden = true
|
||||
totalSize -= itemSize
|
||||
popupView.ephemeralHidden = true
|
||||
totalSize -= itemSize
|
||||
} else {
|
||||
if (viewModel.oneToOneChatRoom) {
|
||||
builder.removeItem(R.id.chat_room_group_info)
|
||||
popupView.groupInfoHidden = true
|
||||
totalSize -= itemSize
|
||||
}
|
||||
|
||||
// If one participant one device, a click on security badge
|
||||
// will directly start a call or show the dialog, so don't show this menu
|
||||
if (viewModel.oneParticipantOneDevice) {
|
||||
builder.removeItem(R.id.chat_room_participants_devices)
|
||||
popupView.devicesHidden = true
|
||||
totalSize -= itemSize
|
||||
}
|
||||
|
||||
if (viewModel.ephemeralChatRoom) {
|
||||
if (chatRoom.currentParams.ephemeralMode == ChatRoomEphemeralMode.AdminManaged &&
|
||||
viewModel.meAdmin.value == false
|
||||
) {
|
||||
popupView.ephemeralHidden = true
|
||||
totalSize -= itemSize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!viewModel.encryptedChatRoom) {
|
||||
builder.removeItem(R.id.chat_room_participants_devices)
|
||||
builder.removeItem(R.id.chat_room_ephemeral_messages)
|
||||
}
|
||||
// When using WRAP_CONTENT instead of real size, fails to place the
|
||||
// popup window above if not enough space is available below
|
||||
val popupWindow = PopupWindow(
|
||||
popupView.root,
|
||||
AppUtils.getDimension(R.dimen.chat_room_popup_width).toInt(),
|
||||
totalSize,
|
||||
true
|
||||
)
|
||||
// Elevation is for showing a shadow around the popup
|
||||
popupWindow.elevation = 20f
|
||||
|
||||
builder.setCallback(object : MenuBuilder.Callback {
|
||||
override fun onMenuModeChange(menu: MenuBuilder) {}
|
||||
|
||||
override fun onMenuItemSelected(menu: MenuBuilder, item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
R.id.chat_room_group_info -> {
|
||||
popupView.setGroupInfoListener {
|
||||
showGroupInfo(chatRoom)
|
||||
true
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
R.id.chat_room_participants_devices -> {
|
||||
popupView.setDevicesListener {
|
||||
showParticipantsDevices()
|
||||
true
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
R.id.chat_room_ephemeral_messages -> {
|
||||
popupView.setEphemeralListener {
|
||||
showEphemeralMessages()
|
||||
true
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
R.id.chat_room_delete_messages -> {
|
||||
popupView.setEditionModeListener {
|
||||
enterEditionMode()
|
||||
true
|
||||
popupWindow.dismiss()
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
popupMenu.show()
|
||||
popupWindow.showAsDropDown(binding.menu, 0, 0, Gravity.BOTTOM)
|
||||
}
|
||||
|
||||
private fun scrollToBottom() {
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.linphone.activities.main.chat.viewmodels
|
|||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.main.viewmodels.ErrorReportingViewModel
|
||||
import org.linphone.contact.ContactsUpdatedListenerStub
|
||||
|
@ -163,6 +164,11 @@ class ChatRoomCreationViewModel : ErrorReportingViewModel() {
|
|||
if (encrypted) {
|
||||
params.enableEncryption(true)
|
||||
params.backend = ChatRoomBackend.FlexisipChat
|
||||
params.ephemeralMode = if (corePreferences.useEphemeralPerDeviceMode)
|
||||
ChatRoomEphemeralMode.DeviceManaged
|
||||
else
|
||||
ChatRoomEphemeralMode.AdminManaged
|
||||
params.ephemeralLifetime = 0 // Make sure ephemeral is disabled by default
|
||||
params.subject = AppUtils.getString(R.string.chat_room_dummy_subject)
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,11 @@ class ChatRoomViewModel(val chatRoom: ChatRoom) : ViewModel(), ContactDataInterf
|
|||
|
||||
val encryptedChatRoom: Boolean = chatRoom.hasCapability(ChatRoomCapabilities.Encrypted.toInt())
|
||||
|
||||
val basicChatRoom: Boolean = chatRoom.hasCapability(ChatRoomCapabilities.Basic.toInt())
|
||||
val ephemeralChatRoom: Boolean = chatRoom.hasCapability(ChatRoomCapabilities.Ephemeral.toInt())
|
||||
|
||||
val meAdmin: MutableLiveData<Boolean> by lazy {
|
||||
MutableLiveData<Boolean>()
|
||||
}
|
||||
|
||||
var oneParticipantOneDevice: Boolean = false
|
||||
|
||||
|
@ -174,6 +178,10 @@ class ChatRoomViewModel(val chatRoom: ChatRoom) : ViewModel(), ContactDataInterf
|
|||
Log.i("[Chat Room] Ephemeral message deleted, updated last message displayed")
|
||||
lastMessageText.value = formatLastMessage(chatRoom.lastMessageInHistory)
|
||||
}
|
||||
|
||||
override fun onParticipantAdminStatusChanged(chatRoom: ChatRoom, eventLog: EventLog) {
|
||||
meAdmin.value = chatRoom.me?.isAdmin ?: false
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
|
@ -187,6 +195,7 @@ class ChatRoomViewModel(val chatRoom: ChatRoom) : ViewModel(), ContactDataInterf
|
|||
|
||||
subject.value = chatRoom.subject
|
||||
updateSecurityIcon()
|
||||
meAdmin.value = chatRoom.me?.isAdmin ?: false
|
||||
|
||||
contactLookup()
|
||||
updateParticipants()
|
||||
|
@ -206,6 +215,10 @@ class ChatRoomViewModel(val chatRoom: ChatRoom) : ViewModel(), ContactDataInterf
|
|||
chatRoom.core.removeListener(coreListener)
|
||||
}
|
||||
|
||||
fun hideMenu(): Boolean {
|
||||
return chatRoom.hasCapability(ChatRoomCapabilities.Basic.toInt()) || (oneToOneChatRoom && !encryptedChatRoom)
|
||||
}
|
||||
|
||||
fun contactLookup() {
|
||||
displayName.value = when {
|
||||
chatRoom.hasCapability(ChatRoomCapabilities.Basic.toInt()) -> LinphoneUtils.getDisplayName(
|
||||
|
@ -304,7 +317,7 @@ class ChatRoomViewModel(val chatRoom: ChatRoom) : ViewModel(), ContactDataInterf
|
|||
}
|
||||
|
||||
private fun updateParticipants() {
|
||||
peerSipUri.value = if (oneToOneChatRoom && !basicChatRoom)
|
||||
peerSipUri.value = if (oneToOneChatRoom && !chatRoom.hasCapability(ChatRoomCapabilities.Basic.toInt()))
|
||||
chatRoom.participants.firstOrNull()?.address?.asStringUriOnly()
|
||||
?: chatRoom.peerAddress.asStringUriOnly()
|
||||
else chatRoom.peerAddress.asStringUriOnly()
|
||||
|
|
|
@ -23,6 +23,7 @@ import androidx.lifecycle.MutableLiveData
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.main.chat.GroupChatRoomMember
|
||||
import org.linphone.activities.main.chat.data.GroupInfoParticipantData
|
||||
|
@ -117,6 +118,13 @@ class GroupInfoViewModel(val chatRoom: ChatRoom?) : ErrorReportingViewModel() {
|
|||
val params: ChatRoomParams = coreContext.core.createDefaultChatRoomParams()
|
||||
params.enableEncryption(isEncrypted.value == true)
|
||||
params.enableGroup(true)
|
||||
if (isEncrypted.value == true) {
|
||||
params.ephemeralMode = if (corePreferences.useEphemeralPerDeviceMode)
|
||||
ChatRoomEphemeralMode.DeviceManaged
|
||||
else
|
||||
ChatRoomEphemeralMode.AdminManaged
|
||||
}
|
||||
params.ephemeralLifetime = 0 // Make sure ephemeral is disabled by default
|
||||
params.subject = subject.value
|
||||
|
||||
val addresses = arrayOfNulls<Address>(participants.value.orEmpty().size)
|
||||
|
|
|
@ -417,6 +417,10 @@ class CorePreferences constructor(private val context: Context) {
|
|||
val voiceMessagesFormatMkv: Boolean
|
||||
get() = config.getBool("app", "record_voice_messages_in_mkv_format", true)
|
||||
|
||||
// TODO FIXME: Keeping it device based until we have the API to know if all participants support the new mode
|
||||
val useEphemeralPerDeviceMode: Boolean
|
||||
get() = config.getBool("app", "ephemeral_chat_messages_settings_per_device", true)
|
||||
|
||||
/* Default values related */
|
||||
|
||||
val echoCancellerCalibration: Int
|
||||
|
|
|
@ -627,7 +627,7 @@ class NotificationsManager(private val context: Context) {
|
|||
val notifiableMessage = getNotifiableMessage(message, contact)
|
||||
notifiable.messages.add(notifiableMessage)
|
||||
} else {
|
||||
for (chatMessage in room.getUnreadHistory()) {
|
||||
for (chatMessage in room.unreadHistory) {
|
||||
val notifiableMessage = getNotifiableMessage(chatMessage, contact)
|
||||
notifiable.messages.add(notifiableMessage)
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 12 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 12 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 14 KiB |
|
@ -110,7 +110,7 @@
|
|||
|
||||
<ImageView
|
||||
android:id="@+id/menu"
|
||||
android:visibility="@{viewModel.basicChatRoom || chatSendingViewModel.isReadOnly ? View.GONE : View.VISIBLE}"
|
||||
android:visibility="@{viewModel.hideMenu() || chatSendingViewModel.isReadOnly ? View.GONE : View.VISIBLE}"
|
||||
android:onClick="@{menuClickListener}"
|
||||
android:contentDescription="@string/content_description_show_chat_room_menu"
|
||||
android:layout_width="0dp"
|
||||
|
@ -122,7 +122,7 @@
|
|||
|
||||
<ImageView
|
||||
android:onClick="@{editClickListener}"
|
||||
android:visibility="@{viewModel.basicChatRoom || chatSendingViewModel.isReadOnly ? View.VISIBLE : View.GONE}"
|
||||
android:visibility="@{menu.visibility == View.GONE ? View.VISIBLE : View.GONE}"
|
||||
android:contentDescription="@string/content_description_enter_edition_mode"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
|
|
76
app/src/main/res/layout/chat_room_menu.xml
Normal file
76
app/src/main/res/layout/chat_room_menu.xml
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<data>
|
||||
<import type="android.view.View" />
|
||||
<variable
|
||||
name="groupInfoListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="devicesListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="ephemeralListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="editionModeListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="groupInfoHidden"
|
||||
type="Boolean" />
|
||||
<variable
|
||||
name="devicesHidden"
|
||||
type="Boolean" />
|
||||
<variable
|
||||
name="ephemeralHidden"
|
||||
type="Boolean" />
|
||||
</data>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="@dimen/chat_message_popup_width"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:background="?attr/backgroundColor">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/chat_room_popup_item_height"
|
||||
android:visibility="@{groupInfoHidden ? View.GONE : View.VISIBLE}"
|
||||
android:background="@drawable/menu_background"
|
||||
android:onClick="@{groupInfoListener}"
|
||||
android:drawableRight="@drawable/menu_group_info_default"
|
||||
style="@style/popup_item_font"
|
||||
android:text="@string/chat_room_context_menu_group_info" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/chat_room_popup_item_height"
|
||||
android:visibility="@{devicesHidden ? View.GONE : View.VISIBLE}"
|
||||
android:background="@drawable/menu_background"
|
||||
android:onClick="@{devicesListener}"
|
||||
android:drawableRight="@drawable/menu_security_default"
|
||||
style="@style/popup_item_font"
|
||||
android:text="@string/chat_room_context_menu_participants_devices" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/chat_room_popup_item_height"
|
||||
android:visibility="@{ephemeralHidden ? View.GONE : View.VISIBLE}"
|
||||
android:background="@drawable/menu_background"
|
||||
android:onClick="@{ephemeralListener}"
|
||||
android:drawableRight="@drawable/chat_room_menu_ephemeral"
|
||||
style="@style/popup_item_font"
|
||||
android:text="@string/chat_message_context_menu_ephemeral_messages" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/chat_room_popup_item_height"
|
||||
android:background="@drawable/menu_background"
|
||||
android:onClick="@{editionModeListener}"
|
||||
android:drawableRight="@drawable/chat_room_menu_delete"
|
||||
style="@style/popup_item_font"
|
||||
android:text="@string/chat_message_context_menu_delete_messages" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</layout>
|
|
@ -1,24 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/chat_room_group_info"
|
||||
android:icon="@drawable/chat_room_menu_group_info"
|
||||
android:title="@string/chat_room_context_menu_group_info" />
|
||||
|
||||
<item
|
||||
android:id="@+id/chat_room_participants_devices"
|
||||
android:icon="@drawable/chat_room_menu_security"
|
||||
android:title="@string/chat_room_context_menu_participants_devices" />
|
||||
|
||||
<item
|
||||
android:id="@+id/chat_room_ephemeral_messages"
|
||||
android:icon="@drawable/chat_room_menu_ephemeral"
|
||||
android:title="@string/chat_message_context_menu_ephemeral_messages" />
|
||||
|
||||
<item
|
||||
android:id="@+id/chat_room_delete_messages"
|
||||
android:icon="@drawable/chat_room_menu_delete"
|
||||
android:title="@string/chat_message_context_menu_delete_messages" />
|
||||
|
||||
</menu>
|
|
@ -26,7 +26,9 @@
|
|||
<dimen name="field_shape_margin">3dp</dimen>
|
||||
<dimen name="call_overlay_size">60dp</dimen>
|
||||
<dimen name="chat_message_popup_width">250dp</dimen>
|
||||
<dimen name="chat_room_popup_width">250dp</dimen>
|
||||
<dimen name="chat_message_popup_item_height">50dp</dimen>
|
||||
<dimen name="chat_room_popup_item_height">50dp</dimen>
|
||||
<dimen name="chat_message_round_corner_radius">6.7dp</dimen>
|
||||
<dimen name="play_pause_button_size">30dp</dimen>
|
||||
<dimen name="progress_bar_height">40dp</dimen>
|
||||
|
|
Loading…
Reference in a new issue