Added sub menu for file picker in conversation to allow picking files other than media

This commit is contained in:
Sylvain Berfini 2024-12-07 21:14:34 +01:00
parent f9cf90fecd
commit 6476bb518d
8 changed files with 180 additions and 44 deletions

View file

@ -126,6 +126,7 @@ open class ConversationFragment : SlidingPaneChildFragment() {
maxItems = SendMessageInConversationViewModel.MAX_FILES_TO_ATTACH
)
) { list ->
sendMessageViewModel.closeFilePickerBottomSheet()
if (list.isNotEmpty()) {
for (uri in list) {
lifecycleScope.launch {
@ -147,9 +148,21 @@ open class ConversationFragment : SlidingPaneChildFragment() {
private var pendingImageCaptureFile: File? = null
private val pickDocument = registerForActivityResult(
ActivityResultContracts.OpenMultipleDocuments()
) { files ->
sendMessageViewModel.closeFilePickerBottomSheet()
for (fileUri in files) {
val path = fileUri.toString()
Log.i("$TAG Picked file [$path]")
sendMessageViewModel.addAttachment(path)
}
}
private val startCameraCapture = registerForActivityResult(
ActivityResultContracts.TakePicture()
) { captured ->
sendMessageViewModel.closeFilePickerBottomSheet()
val path = pendingImageCaptureFile?.absolutePath
if (path != null) {
if (captured) {
@ -257,13 +270,13 @@ open class ConversationFragment : SlidingPaneChildFragment() {
}
override fun afterTextChanged(p0: Editable?) {
sendMessageViewModel.isParticipantsListOpen.value = false
sendMessageViewModel.closeParticipantsList()
val split = p0.toString().split(" ")
for (part in split) {
if (part == "@") {
Log.i("$TAG '@' found, opening participants list")
sendMessageViewModel.isParticipantsListOpen.value = true
sendMessageViewModel.openParticipantsList()
}
}
}
@ -608,6 +621,11 @@ open class ConversationFragment : SlidingPaneChildFragment() {
}
binding.setOpenFilePickerClickListener {
Log.i("$TAG Opening file picker")
pickDocument.launch(arrayOf("*/*"))
}
binding.setOpenMediaPickerClickListener {
Log.i("$TAG Opening media picker")
pickMedia.launch(
PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageAndVideo)

View file

@ -323,6 +323,7 @@ class ConversationViewModel @UiThread constructor() : AbstractConversationViewMo
itemToScrollTo.value = -1
}
@UiThread
override fun onCleared() {
super.onCleared()
@ -335,6 +336,7 @@ class ConversationViewModel @UiThread constructor() : AbstractConversationViewMo
}
}
@WorkerThread
override fun beforeNotifyingChatRoomFound(sameOne: Boolean) {
if (!sameOne) {
Log.i("$TAG Conversation found and not the same as before, configuring it...")

View file

@ -70,6 +70,8 @@ class SendMessageInConversationViewModel @UiThread constructor() : GenericViewMo
val isEmojiPickerOpen = MutableLiveData<Boolean>()
val areFilePickersOpen = MutableLiveData<Boolean>()
val isParticipantsListOpen = MutableLiveData<Boolean>()
val participants = MutableLiveData<ArrayList<ParticipantModel>>()
@ -151,6 +153,7 @@ class SendMessageInConversationViewModel @UiThread constructor() : GenericViewMo
}
isEmojiPickerOpen.value = false
areFilePickersOpen.value = false
isPlayingVoiceRecord.value = false
isCallConversation.value = false
maxNumberOfAttachmentsReached.value = false
@ -199,6 +202,8 @@ class SendMessageInConversationViewModel @UiThread constructor() : GenericViewMo
if (isEmojiPickerOpen.value == true) {
requestKeyboardHidingEvent.value = Event(true)
}
closeFilePickerBottomSheet()
closeParticipantsList()
}
@UiThread
@ -206,6 +211,18 @@ class SendMessageInConversationViewModel @UiThread constructor() : GenericViewMo
emojiToAddEvent.value = Event(emoji)
}
@UiThread
fun toggleFilePickersVisibility() {
areFilePickersOpen.value = areFilePickersOpen.value == false
isEmojiPickerOpen.value = false
closeParticipantsList()
}
@UiThread
fun closeFilePickerBottomSheet() {
areFilePickersOpen.value = false
}
@UiThread
fun replyToMessage(model: MessageModel) {
coreContext.postOnCoreThread {
@ -302,6 +319,13 @@ class SendMessageInConversationViewModel @UiThread constructor() : GenericViewMo
}
}
@UiThread
fun openParticipantsList() {
isParticipantsListOpen.value = true
isEmojiPickerOpen.value = false
closeFilePickerBottomSheet()
}
@UiThread
fun closeParticipantsList() {
isParticipantsListOpen.value = false
@ -418,6 +442,10 @@ class SendMessageInConversationViewModel @UiThread constructor() : GenericViewMo
return
}
isEmojiPickerOpen.value = false
closeFilePickerBottomSheet()
closeParticipantsList()
coreContext.postOnCoreThread {
requestKeyboardHidingEvent.postValue(Event(true))
isVoiceRecording.postValue(true)

View file

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View" />
<variable
name="openMediaPickerClickListener"
type="View.OnClickListener" />
<variable
name="openCameraClickListener"
type="View.OnClickListener" />
<variable
name="openFilePickerClickListener"
type="View.OnClickListener" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/color_main2_000">
<View
android:id="@+id/file_pickers_separator"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/color_main2_300"
app:layout_constraintTop_toTopOf="parent"/>
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style"
android:id="@+id/capture_image"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:onClick="@{openCameraClickListener}"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:drawableTop="@drawable/camera"
android:text="@string/conversation_take_picture_label"
android:textAlignment="center"
android:drawablePadding="5dp"
app:drawableTint="@color/icon_color_selector"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/attach_media"
app:layout_constraintTop_toBottomOf="@id/file_pickers_separator"
app:layout_constraintBottom_toBottomOf="parent"/>
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style"
android:id="@+id/attach_media"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:onClick="@{openMediaPickerClickListener}"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:drawableTop="@drawable/image"
android:text="@string/conversation_pick_file_from_gallery_label"
android:textAlignment="center"
android:drawablePadding="5dp"
app:drawableTint="@color/icon_color_selector"
app:layout_constraintStart_toEndOf="@id/capture_image"
app:layout_constraintEnd_toStartOf="@id/attach_file"
app:layout_constraintTop_toBottomOf="@id/file_pickers_separator"
app:layout_constraintBottom_toBottomOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style"
android:id="@+id/attach_file"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:onClick="@{openFilePickerClickListener}"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:drawableTop="@drawable/file"
android:text="@string/conversation_pick_any_file_label"
android:textAlignment="center"
android:drawablePadding="5dp"
app:drawableTint="@color/icon_color_selector"
app:layout_constraintStart_toEndOf="@id/attach_media"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/file_pickers_separator"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -15,11 +15,14 @@
name="showMenuClickListener"
type="View.OnClickListener" />
<variable
name="openFilePickerClickListener"
name="openMediaPickerClickListener"
type="View.OnClickListener" />
<variable
name="openCameraClickListener"
type="View.OnClickListener" />
<variable
name="openFilePickerClickListener"
type="View.OnClickListener" />
<variable
name="scrollToBottomClickListener"
type="View.OnClickListener" />
@ -313,8 +316,9 @@
android:visibility="@{viewModel.isReadOnly || viewModel.isDisabledBecauseNotSecured || viewModel.searchBarVisible ? View.GONE : View.VISIBLE}"
layout="@layout/chat_conversation_send_area"
app:layout_constraintBottom_toBottomOf="parent"
bind:openFilePickerClickListener="@{openFilePickerClickListener}"
bind:openMediaPickerClickListener="@{openMediaPickerClickListener}"
bind:openCameraClickListener="@{openCameraClickListener}"
bind:openFilePickerClickListener="@{openFilePickerClickListener}"
bind:viewModel="@{sendMessageViewModel}"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton

View file

@ -6,11 +6,14 @@
<data>
<import type="android.view.View" />
<variable
name="openFilePickerClickListener"
name="openMediaPickerClickListener"
type="View.OnClickListener" />
<variable
name="openCameraClickListener"
type="View.OnClickListener" />
<variable
name="openFilePickerClickListener"
type="View.OnClickListener" />
<variable
name="viewModel"
type="org.linphone.ui.main.chat.viewmodel.SendMessageInConversationViewModel" />
@ -29,13 +32,6 @@
android:visibility="@{viewModel.isVoiceRecording ? View.INVISIBLE : View.VISIBLE}"
app:constraint_referenced_ids="attach_file, message_area_background, message_to_send" />
<androidx.constraintlayout.widget.Group
android:id="@+id/extra_actions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{viewModel.isVoiceRecording ? View.INVISIBLE : (viewModel.isKeyboardOpen || viewModel.isCallConversation || !viewModel.isFileTransferServerAvailable) ? View.GONE : View.VISIBLE}"
app:constraint_referenced_ids="emoji_picker_toggle, capture_image" />
<include
android:id="@+id/reply_area"
layout="@layout/chat_conversation_reply_area"
@ -52,15 +48,6 @@
android:visibility="@{viewModel.isFileAttachmentsListOpen ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintTop_toBottomOf="@id/reply_area" />
<include
android:id="@+id/participants"
layout="@layout/chat_conversation_participants_area"
bind:viewModel="@{viewModel}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="@{viewModel.isParticipantsListOpen ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintTop_toBottomOf="@id/attachments" />
<androidx.emoji2.emojipicker.EmojiPickerView
android:id="@+id/emoji_picker"
android:layout_width="match_parent"
@ -70,12 +57,32 @@
app:emojiPickedListener="@{(emoji) -> viewModel.insertEmoji(emoji.emoji)}"
app:layout_constraintTop_toBottomOf="@id/attachments" />
<include
android:id="@+id/file_pickers"
layout="@layout/chat_conversation_file_pickers"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="@{viewModel.areFilePickersOpen ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintTop_toBottomOf="@id/emoji_picker"
bind:openMediaPickerClickListener="@{openMediaPickerClickListener}"
bind:openCameraClickListener="@{openCameraClickListener}"
bind:openFilePickerClickListener="@{openFilePickerClickListener}" />
<include
android:id="@+id/participants"
layout="@layout/chat_conversation_participants_area"
bind:viewModel="@{viewModel}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="@{viewModel.isParticipantsListOpen ? View.VISIBLE : View.GONE, default=gone}"
app:layout_constraintTop_toBottomOf="@id/file_pickers" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/top_barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="emoji_picker, participants, attachments, reply_area" />
app:constraint_referenced_ids="file_pickers, emoji_picker, participants, attachments, reply_area" />
<ImageView
android:id="@+id/emoji_picker_toggle"
@ -96,30 +103,15 @@
android:layout_width="40dp"
android:layout_height="0dp"
android:layout_marginStart="5dp"
android:onClick="@{openFilePickerClickListener}"
android:onClick="@{() -> viewModel.toggleFilePickersVisibility()}"
android:enabled="@{!viewModel.maxNumberOfAttachmentsReached}"
android:padding="8dp"
android:src="@drawable/paperclip"
android:contentDescription="@string/content_description_chat_open_attach_media"
app:layout_constraintBottom_toBottomOf="@id/message_area_background"
app:layout_constraintEnd_toStartOf="@id/capture_image"
app:layout_constraintStart_toEndOf="@id/emoji_picker_toggle"
app:layout_constraintTop_toTopOf="@id/message_area_background"
app:tint="@color/icon_color_selector" />
<ImageView
android:id="@+id/capture_image"
android:layout_width="40dp"
android:layout_height="0dp"
android:layout_marginStart="5dp"
android:onClick="@{openCameraClickListener}"
android:enabled="@{!viewModel.maxNumberOfAttachmentsReached}"
android:padding="8dp"
android:src="@drawable/camera"
android:contentDescription="@string/content_description_chat_take_picture"
android:contentDescription="@string/content_description_chat_open_attach_file"
android:src="@{viewModel.areFilePickersOpen ? @drawable/x : @drawable/paperclip, default=@drawable/paperclip}"
android:visibility="@{viewModel.isVoiceRecording ? View.INVISIBLE : (viewModel.isKeyboardOpen || viewModel.isCallConversation || !viewModel.isFileTransferServerAvailable) ? View.GONE : View.VISIBLE}"
app:layout_constraintBottom_toBottomOf="@id/message_area_background"
app:layout_constraintEnd_toStartOf="@id/message_area_background"
app:layout_constraintStart_toEndOf="@id/attach_file"
app:layout_constraintStart_toEndOf="@id/emoji_picker_toggle"
app:layout_constraintTop_toTopOf="@id/message_area_background"
app:tint="@color/icon_color_selector" />
@ -133,7 +125,7 @@
android:contentDescription="@null"
app:layout_constraintBottom_toBottomOf="@id/message_to_send"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/capture_image"
app:layout_constraintStart_toEndOf="@id/attach_file"
app:layout_constraintTop_toTopOf="@id/message_to_send" />
<org.linphone.ui.main.chat.view.RichEditText

View file

@ -476,6 +476,9 @@
<string name="conversation_to_display_no_found_toast">Conversation non trouvée</string>
<string name="conversation_search_no_match_found">Aucun résultat trouvé</string>
<string name="conversation_search_no_more_match">Dernier résultat atteint</string>
<string name="conversation_take_picture_label">Prendre une photo</string>
<string name="conversation_pick_file_from_gallery_label">Ouvrir la gallerie</string>
<string name="conversation_pick_any_file_label">Choisir un fichier</string>
<string name="conversation_info_participants_list_title">Membres du groupe (%s)</string>
<string name="conversation_info_add_participants_label">Ajouter des membres</string>

View file

@ -514,6 +514,9 @@
<string name="conversation_to_display_no_found_toast">Conversation was not found</string>
<string name="conversation_search_no_match_found">No matching result found</string>
<string name="conversation_search_no_more_match">Last matching result reached</string>
<string name="conversation_take_picture_label">Take picture</string>
<string name="conversation_pick_file_from_gallery_label">Open gallery</string>
<string name="conversation_pick_any_file_label">Pick file</string>
<string name="conversation_info_participants_list_title">Group members (%s)</string>
<string name="conversation_info_add_participants_label">Add participants</string>
@ -857,7 +860,7 @@
<string name="content_description_chat_send_message">Sends message in conversation</string>
<string name="content_description_chat_cancel_reply">Message will no longer be a reply to a previous message</string>
<string name="content_description_chat_open_emoji_picker">Opens emoji picker</string>
<string name="content_description_chat_open_attach_media">Opens media picker</string>
<string name="content_description_chat_open_attach_file">Opens file picker</string>
<string name="content_description_chat_take_picture">Opens camera to take a picture</string>
<string name="content_description_chat_edit_conversation_subject">Click to edit the subject of this conversation</string>
<string name="content_description_chat_toggle_mute">Silences on/off this conversation</string>