mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 03:18:06 +00:00
Use newly added chat room compose APIs to notify wether text or voice recording is being composed
This commit is contained in:
parent
6cdcdec373
commit
595ff96d50
10 changed files with 97 additions and 60 deletions
|
|
@ -280,11 +280,11 @@ open class ConversationFragment : SlidingPaneChildFragment() {
|
|||
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
|
||||
}
|
||||
|
||||
override fun afterTextChanged(p0: Editable?) {
|
||||
override fun afterTextChanged(editable: Editable?) {
|
||||
if (viewModel.isGroup.value == true) {
|
||||
sendMessageViewModel.closeParticipantsList()
|
||||
|
||||
val split = p0.toString().split(" ")
|
||||
val split = editable.toString().split(" ")
|
||||
for (part in split) {
|
||||
if (part == "@") {
|
||||
Log.i("$TAG '@' found, opening participants list")
|
||||
|
|
@ -293,9 +293,7 @@ open class ConversationFragment : SlidingPaneChildFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
if (p0.toString().isNotEmpty()) {
|
||||
sendMessageViewModel.notifyChatMessageIsBeingComposed()
|
||||
}
|
||||
sendMessageViewModel.notifyComposing(editable.toString().isNotEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@ class ConversationModel
|
|||
|
||||
val lastMessageContentIcon = MutableLiveData<Int>()
|
||||
|
||||
val composingIcon = MutableLiveData<Int>()
|
||||
|
||||
val isLastMessageOutgoing = MutableLiveData<Boolean>()
|
||||
|
||||
val dateTime = MutableLiveData<String>()
|
||||
|
|
@ -428,30 +430,10 @@ class ConversationModel
|
|||
private fun computeComposingLabel() {
|
||||
val composing = chatRoom.isRemoteComposing
|
||||
isComposing.postValue(composing)
|
||||
if (!composing) {
|
||||
composingLabel.postValue("")
|
||||
return
|
||||
}
|
||||
|
||||
val composingFriends = arrayListOf<String>()
|
||||
var label = ""
|
||||
for (address in chatRoom.composingAddresses) {
|
||||
val avatar = coreContext.contactsManager.getContactAvatarModelForAddress(address)
|
||||
val name = avatar.name.value ?: LinphoneUtils.getDisplayName(address)
|
||||
composingFriends.add(name)
|
||||
label += "$name, "
|
||||
}
|
||||
if (composingFriends.isNotEmpty()) {
|
||||
label = label.dropLast(2)
|
||||
|
||||
val format = AppUtils.getStringWithPlural(
|
||||
R.plurals.conversation_composing_label,
|
||||
composingFriends.size,
|
||||
label
|
||||
)
|
||||
composingLabel.postValue(format)
|
||||
} else {
|
||||
composingLabel.postValue("")
|
||||
}
|
||||
val pair = LinphoneUtils.getComposingIconAndText(chatRoom)
|
||||
val icon = pair.first
|
||||
composingIcon.postValue(icon)
|
||||
val label = pair.second
|
||||
composingLabel.postValue(label)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ import org.linphone.ui.main.chat.model.EventLogModel
|
|||
import org.linphone.ui.main.chat.model.FileModel
|
||||
import org.linphone.ui.main.chat.model.MessageModel
|
||||
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.FileUtils
|
||||
import org.linphone.utils.LinphoneUtils
|
||||
|
|
@ -89,6 +88,8 @@ class ConversationViewModel
|
|||
|
||||
val composingLabel = MutableLiveData<String>()
|
||||
|
||||
val composingIcon = MutableLiveData<Int>()
|
||||
|
||||
val searchBarVisible = MutableLiveData<Boolean>()
|
||||
|
||||
val searchFilter = MutableLiveData<String>()
|
||||
|
|
@ -906,26 +907,12 @@ class ConversationViewModel
|
|||
@WorkerThread
|
||||
private fun computeComposingLabel() {
|
||||
if (!isChatRoomInitialized()) return
|
||||
val composingFriends = arrayListOf<String>()
|
||||
var label = ""
|
||||
for (address in chatRoom.composingAddresses) {
|
||||
val avatar = coreContext.contactsManager.getContactAvatarModelForAddress(address)
|
||||
val name = avatar.name.value ?: LinphoneUtils.getDisplayName(address)
|
||||
composingFriends.add(name)
|
||||
label += "$name, "
|
||||
}
|
||||
if (composingFriends.isNotEmpty()) {
|
||||
label = label.dropLast(2)
|
||||
|
||||
val format = AppUtils.getStringWithPlural(
|
||||
R.plurals.conversation_composing_label,
|
||||
composingFriends.size,
|
||||
label
|
||||
)
|
||||
composingLabel.postValue(format)
|
||||
} else {
|
||||
composingLabel.postValue("")
|
||||
}
|
||||
val pair = LinphoneUtils.getComposingIconAndText(chatRoom)
|
||||
val icon = pair.first
|
||||
composingIcon.postValue(icon)
|
||||
val label = pair.second
|
||||
composingLabel.postValue(label)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
|
|
|
|||
|
|
@ -344,10 +344,14 @@ class SendMessageInConversationViewModel
|
|||
}
|
||||
|
||||
@UiThread
|
||||
fun notifyChatMessageIsBeingComposed() {
|
||||
fun notifyComposing(composing: Boolean) {
|
||||
coreContext.postOnCoreThread {
|
||||
if (::chatRoom.isInitialized) {
|
||||
chatRoom.compose()
|
||||
if (composing) {
|
||||
chatRoom.composeTextMessage()
|
||||
} else {
|
||||
chatRoom.stopComposing()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -489,6 +493,7 @@ class SendMessageInConversationViewModel
|
|||
@UiThread
|
||||
fun stopVoiceMessageRecording() {
|
||||
coreContext.postOnCoreThread {
|
||||
chatRoom.stopComposing()
|
||||
stopVoiceRecorder()
|
||||
}
|
||||
}
|
||||
|
|
@ -496,6 +501,7 @@ class SendMessageInConversationViewModel
|
|||
@UiThread
|
||||
fun cancelVoiceMessageRecording() {
|
||||
coreContext.postOnCoreThread {
|
||||
chatRoom.stopComposing()
|
||||
stopVoiceRecorder()
|
||||
|
||||
val path = voiceMessageRecorder.file
|
||||
|
|
@ -589,6 +595,7 @@ class SendMessageInConversationViewModel
|
|||
}
|
||||
else -> {}
|
||||
}
|
||||
chatRoom.composeVoiceMessage()
|
||||
|
||||
val duration = voiceMessageRecorder.duration
|
||||
val formattedDuration = SimpleDateFormat("mm:ss", Locale.getDefault()).format(duration) // duration is in ms
|
||||
|
|
|
|||
|
|
@ -470,6 +470,38 @@ class LinphoneUtils {
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getComposingIconAndText(chatRoom: ChatRoom): Pair<Int, String> {
|
||||
val composing = chatRoom.isRemoteComposing
|
||||
if (!composing) {
|
||||
return Pair(0, "")
|
||||
}
|
||||
|
||||
var icon = R.drawable.chat_teardrop_dots
|
||||
val composingFriends = arrayListOf<String>()
|
||||
var label = ""
|
||||
for (participant in chatRoom.composingParticipants) {
|
||||
val address = participant.address
|
||||
val avatar = coreContext.contactsManager.getContactAvatarModelForAddress(address)
|
||||
val name = avatar.name.value ?: getDisplayName(address)
|
||||
composingFriends.add(name)
|
||||
label += "$name, "
|
||||
}
|
||||
if (composingFriends.isNotEmpty()) {
|
||||
label = label.dropLast(2)
|
||||
|
||||
// TODO: use voice recording content type to change icon/text
|
||||
val format = AppUtils.getStringWithPlural(
|
||||
R.plurals.conversation_composing_label,
|
||||
composingFriends.size,
|
||||
label
|
||||
)
|
||||
return Pair(icon, format)
|
||||
}
|
||||
|
||||
return Pair(icon, label)
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
fun formatEphemeralExpiration(duration: Long): String {
|
||||
return when (duration) {
|
||||
|
|
|
|||
9
app/src/main/res/drawable/chat_teardrop_dots.xml
Normal file
9
app/src/main/res/drawable/chat_teardrop_dots.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="256"
|
||||
android:viewportHeight="256">
|
||||
<path
|
||||
android:pathData="M132,24A100.11,100.11 0,0 0,32 124v84a16,16 0,0 0,16 16h84a100,100 0,0 0,0 -200ZM132,208L48,208L48,124a84,84 0,1 1,84 84ZM144,128a12,12 0,1 1,-12 -12A12,12 0,0 1,144 128ZM100,128a12,12 0,1 1,-12 -12A12,12 0,0 1,100 128ZM188,128a12,12 0,1 1,-12 -12A12,12 0,0 1,188 128Z"
|
||||
android:fillColor="#4e6074"/>
|
||||
</vector>
|
||||
|
|
@ -326,19 +326,33 @@
|
|||
app:layout_constraintStart_toStartOf="@id/events_list"
|
||||
app:layout_constraintEnd_toEndOf="@id/events_list" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/composing_icon"
|
||||
android:layout_width="@dimen/small_icon_size"
|
||||
android:layout_height="@dimen/small_icon_size"
|
||||
android:layout_marginStart="10dp"
|
||||
android:src="@{viewModel.composingIcon, default=@drawable/microphone}"
|
||||
android:visibility="@{viewModel.composingLabel.length() == 0 ? View.GONE : View.VISIBLE}"
|
||||
android:contentDescription="@null"
|
||||
app:tint="?attr/color_main2_600"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/composing"
|
||||
app:layout_constraintTop_toTopOf="@id/composing"
|
||||
app:layout_constraintBottom_toBottomOf="@id/composing"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style_300"
|
||||
android:id="@+id/composing"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginStart="5dp"
|
||||
android:paddingBottom="5dp"
|
||||
android:background="?attr/color_main2_000"
|
||||
android:text="@{viewModel.composingLabel, default=`John Doe is composing...`}"
|
||||
android:textSize="12sp"
|
||||
android:visibility="@{viewModel.composingLabel.length() == 0 ? View.GONE : View.VISIBLE}"
|
||||
app:layout_constraintBottom_toTopOf="@id/warning_disabled_not_secured"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/composing_icon"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<include
|
||||
|
|
|
|||
|
|
@ -92,21 +92,21 @@
|
|||
android:textSize="14sp"
|
||||
android:textColor="?attr/color_main2_500"
|
||||
android:visibility="@{model.isBeingDeleted || model.lastMessageTextSender.length() == 0 || model.isComposing ? View.GONE : View.VISIBLE}"
|
||||
textFont="@{model.isBeingDeleted || model.unreadMessageCount > 0 || model.isComposing ? NotoSansFont.NotoSansBold : NotoSansFont.NotoSansRegular}"
|
||||
textFont="@{model.unreadMessageCount > 0 ? NotoSansFont.NotoSansBold : NotoSansFont.NotoSansRegular}"
|
||||
app:layout_constraintStart_toStartOf="@id/title"
|
||||
app:layout_constraintEnd_toStartOf="@id/last_message_forward"
|
||||
app:layout_constraintEnd_toStartOf="@id/last_message_icon"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:layout_constraintBottom_toTopOf="@id/separator"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/last_message_forward"
|
||||
android:id="@+id/last_message_icon"
|
||||
android:layout_width="@dimen/small_icon_size"
|
||||
android:layout_height="@dimen/small_icon_size"
|
||||
android:layout_marginStart="@{model.lastMessageTextSender.length() > 0 ? @dimen/five : @dimen/zero}"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_marginTop="3dp"
|
||||
android:src="@{model.lastMessageContentIcon, default=@drawable/forward}"
|
||||
android:visibility="@{model.lastMessageContentIcon > 0 && !model.isComposing ? View.VISIBLE : View.GONE}"
|
||||
android:src="@{model.isComposing ? model.composingIcon : model.lastMessageContentIcon, default=@drawable/forward}"
|
||||
android:visibility="@{model.lastMessageContentIcon > 0 || model.isComposing ? View.VISIBLE : View.GONE}"
|
||||
android:contentDescription="@null"
|
||||
app:tint="?attr/color_main2_600"
|
||||
app:layout_constraintStart_toEndOf="@id/last_message_sender"
|
||||
|
|
@ -126,7 +126,7 @@
|
|||
android:textSize="14sp"
|
||||
android:textColor="?attr/color_main2_500"
|
||||
textFont="@{model.isBeingDeleted || model.unreadMessageCount > 0 || model.isComposing ? NotoSansFont.NotoSansBold : NotoSansFont.NotoSansRegular}"
|
||||
app:layout_constraintStart_toEndOf="@id/last_message_forward"
|
||||
app:layout_constraintStart_toEndOf="@id/last_message_icon"
|
||||
app:layout_constraintEnd_toStartOf="@id/right_border"
|
||||
app:layout_constraintTop_toTopOf="@id/last_message_sender"
|
||||
app:layout_constraintBottom_toBottomOf="@id/last_message_sender" />
|
||||
|
|
|
|||
|
|
@ -490,6 +490,10 @@
|
|||
<item quantity="one">%s est en train d\'écrire…</item>
|
||||
<item quantity="other">%s sont en train d\'écrire…</item>
|
||||
</plurals>
|
||||
<plurals name="conversation_composing_voice_message_label">
|
||||
<item quantity="one">%s est en train d\'enregistrer un message vocal…</item>
|
||||
<item quantity="other">%s sont en train d\'enregistrer un message vocal…</item>
|
||||
</plurals>
|
||||
<string name="conversation_add_participants_title">Ajouter des participants</string>
|
||||
<string name="conversation_reply_to_message_title">En réponse à :</string>
|
||||
<string name="conversation_menu_search_in_messages">Chercher</string>
|
||||
|
|
|
|||
|
|
@ -533,6 +533,10 @@
|
|||
<item quantity="one">%s is composing…</item>
|
||||
<item quantity="other">%s are composing…</item>
|
||||
</plurals>
|
||||
<plurals name="conversation_composing_voice_message_label">
|
||||
<item quantity="one">%s is recording a voice message…</item>
|
||||
<item quantity="other">%s are recording a voice message…</item>
|
||||
</plurals>
|
||||
<string name="conversation_add_participants_title">Add participants</string>
|
||||
<string name="conversation_reply_to_message_title">Replying to:</string>
|
||||
<string name="conversation_menu_search_in_messages">Search</string>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue