From f7710e2ae217d9a886bbc7a1dcd744f6810b3d39 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 4 Jun 2021 17:03:55 +0200 Subject: [PATCH] Added reply to chat message feature --- app/build.gradle | 4 +- .../chat/adapters/ChatMessagesListAdapter.kt | 28 ++++++- .../main/chat/data/ChatMessageData.kt | 16 ++++ .../chat/fragments/DetailChatRoomFragment.kt | 49 +++++++++++ .../viewmodels/ChatMessageSendingViewModel.kt | 19 ++++- .../java/org/linphone/utils/LinphoneUtils.kt | 9 ++ .../res/drawable-xhdpi/menu_reply_default.png | Bin 0 -> 11588 bytes .../replied_message_default.png | Bin 0 -> 8230 bytes .../drawable-xhdpi/reply_message_default.png | Bin 0 -> 10985 bytes .../drawable/chat_bubble_incoming_full.xml | 2 +- .../drawable/chat_bubble_incoming_split_1.xml | 2 +- .../drawable/chat_bubble_incoming_split_2.xml | 2 +- .../drawable/chat_bubble_incoming_split_3.xml | 2 +- .../drawable/chat_bubble_outgoing_full.xml | 2 +- .../drawable/chat_bubble_outgoing_split_1.xml | 2 +- .../drawable/chat_bubble_outgoing_split_2.xml | 2 +- .../drawable/chat_bubble_outgoing_split_3.xml | 2 +- .../drawable/chat_bubble_reply_background.xml | 6 ++ .../chat_bubble_reply_file_background.xml | 7 ++ .../chat_bubble_reply_incoming_indicator.xml | 5 ++ .../chat_bubble_reply_outgoing_indicator.xml | 5 ++ app/src/main/res/drawable/menu_reply.xml | 7 ++ .../res/layout/chat_message_list_cell.xml | 50 ++++++++++- .../layout/chat_message_long_press_menu.xml | 12 +++ .../main/res/layout/chat_message_reply.xml | 74 ++++++++++++++++ .../res/layout/chat_message_reply_bubble.xml | 79 ++++++++++++++++++ .../chat_message_reply_content_cell.xml | 61 ++++++++++++++ ...hat_message_reply_preview_content_cell.xml | 55 ++++++++++++ .../res/layout/chat_room_detail_fragment.xml | 11 ++- app/src/main/res/values-fr/strings.xml | 4 + app/src/main/res/values/colors.xml | 5 ++ app/src/main/res/values/dimen.xml | 2 + app/src/main/res/values/strings.xml | 6 ++ app/src/main/res/values/styles.xml | 14 ++++ 34 files changed, 528 insertions(+), 16 deletions(-) create mode 100644 app/src/main/res/drawable-xhdpi/menu_reply_default.png create mode 100644 app/src/main/res/drawable-xhdpi/replied_message_default.png create mode 100644 app/src/main/res/drawable-xhdpi/reply_message_default.png create mode 100644 app/src/main/res/drawable/chat_bubble_reply_background.xml create mode 100644 app/src/main/res/drawable/chat_bubble_reply_file_background.xml create mode 100644 app/src/main/res/drawable/chat_bubble_reply_incoming_indicator.xml create mode 100644 app/src/main/res/drawable/chat_bubble_reply_outgoing_indicator.xml create mode 100644 app/src/main/res/drawable/menu_reply.xml create mode 100644 app/src/main/res/layout/chat_message_reply.xml create mode 100644 app/src/main/res/layout/chat_message_reply_bubble.xml create mode 100644 app/src/main/res/layout/chat_message_reply_content_cell.xml create mode 100644 app/src/main/res/layout/chat_message_reply_preview_content_cell.xml diff --git a/app/build.gradle b/app/build.gradle index 8f5382cf1..9810fcd74 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -29,7 +29,7 @@ if (crashlyticsEnabled()) { def gitBranch = new ByteArrayOutputStream() task getGitVersion() { - def gitVersion = "4.5.0" + def gitVersion = "4.6.0" def gitVersionStream = new ByteArrayOutputStream() def gitCommitsCount = new ByteArrayOutputStream() def gitCommitHash = new ByteArrayOutputStream() @@ -269,7 +269,7 @@ dependencies { implementation 'com.google.firebase:firebase-messaging' } - implementation 'org.linphone:linphone-sdk-android:5.0+' + implementation 'org.linphone:linphone-sdk-android:5.1+' // Only enable leak canary prior to release //debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4' diff --git a/app/src/main/java/org/linphone/activities/main/chat/adapters/ChatMessagesListAdapter.kt b/app/src/main/java/org/linphone/activities/main/chat/adapters/ChatMessagesListAdapter.kt index 5808807b9..76c051b9b 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/adapters/ChatMessagesListAdapter.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/adapters/ChatMessagesListAdapter.kt @@ -69,6 +69,10 @@ class ChatMessagesListAdapter( MutableLiveData>() } + val replyMessageEvent: MutableLiveData> by lazy { + MutableLiveData>() + } + val showImdnForMessageEvent: MutableLiveData> by lazy { MutableLiveData>() } @@ -81,6 +85,10 @@ class ChatMessagesListAdapter( MutableLiveData>() } + val scrollToChatMessageEvent: MutableLiveData> by lazy { + MutableLiveData>() + } + private val contentClickedListener = object : OnContentClickedListener { override fun onContentClicked(content: Content) { openContentEvent.value = Event(content) @@ -155,6 +163,13 @@ class ChatMessagesListAdapter( } } + setReplyClickListener { + val reply = chatMessageViewModel.replyData.value?.chatMessage + if (reply != null) { + scrollToChatMessageEvent.value = Event(reply) + } + } + // Grouping var hasPrevious = false var hasNext = false @@ -196,7 +211,7 @@ class ChatMessagesListAdapter( ) val itemSize = AppUtils.getDimension(R.dimen.chat_message_popup_item_height).toInt() - var totalSize = itemSize * 6 + var totalSize = itemSize * 7 if (chatMessage.chatRoom.hasCapability(ChatRoomCapabilities.OneToOne.toInt()) || chatMessage.state == ChatMessage.State.NotDelivered) { // No message id popupView.imdnHidden = true @@ -237,6 +252,10 @@ class ChatMessagesListAdapter( forwardMessage() popupWindow.dismiss() } + popupView.setReplyClickListener { + replyMessage() + popupWindow.dismiss() + } popupView.setImdnClickListener { showImdnDeliveryFragment() popupWindow.dismiss() @@ -287,6 +306,13 @@ class ChatMessagesListAdapter( } } + private fun replyMessage() { + val chatMessage = binding.data?.chatMessage + if (chatMessage != null) { + replyMessageEvent.value = Event(chatMessage) + } + } + private fun showImdnDeliveryFragment() { val chatMessage = binding.data?.chatMessage if (chatMessage != null) { diff --git a/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageData.kt b/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageData.kt index cfd7c51a9..cd8230096 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageData.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageData.kt @@ -28,6 +28,7 @@ import org.linphone.R import org.linphone.contact.GenericContactData import org.linphone.core.ChatMessage import org.linphone.core.ChatMessageListenerStub +import org.linphone.core.tools.Log import org.linphone.utils.AppUtils import org.linphone.utils.TimestampUtils @@ -56,6 +57,8 @@ class ChatMessageData(val chatMessage: ChatMessage) : GenericContactData(chatMes val text = MutableLiveData() + val replyData = MutableLiveData() + private var countDownTimer: CountDownTimer? = null private val listener = object : ChatMessageListenerStub() { @@ -74,6 +77,15 @@ class ChatMessageData(val chatMessage: ChatMessage) : GenericContactData(chatMes backgroundRes.value = if (chatMessage.isOutgoing) R.drawable.chat_bubble_outgoing_full else R.drawable.chat_bubble_incoming_full hideAvatar.value = false + + if (chatMessage.isReply) { + val reply = chatMessage.replyMessage + if (reply != null) { + Log.i("[Chat Message Data] Message is a reply of message id [${chatMessage.replyMessageId}] sent by [${chatMessage.replyMessageSenderAddress?.asStringUriOnly()}]") + replyData.value = ChatMessageData(reply) + } + } + time.value = TimestampUtils.toString(chatMessage.time) updateEphemeralTimer() @@ -84,6 +96,10 @@ class ChatMessageData(val chatMessage: ChatMessage) : GenericContactData(chatMes override fun destroy() { super.destroy() + if (chatMessage.isReply) { + replyData.value?.destroy() + } + contents.value.orEmpty().forEach(ChatMessageContentData::destroy) chatMessage.removeListener(listener) contentListener = null diff --git a/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt b/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt index 65461790e..d4c564946 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt @@ -39,6 +39,7 @@ import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import java.io.File +import java.lang.IllegalArgumentException import kotlinx.coroutines.launch import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.LinphoneApplication.Companion.corePreferences @@ -47,6 +48,7 @@ import org.linphone.activities.* import org.linphone.activities.main.MainActivity import org.linphone.activities.main.chat.ChatScrollListener import org.linphone.activities.main.chat.adapters.ChatMessagesListAdapter +import org.linphone.activities.main.chat.data.ChatMessageData import org.linphone.activities.main.chat.data.EventLogData import org.linphone.activities.main.chat.viewmodels.* import org.linphone.activities.main.fragments.MasterFragment @@ -166,6 +168,28 @@ class DetailChatRoomFragment : MasterFragment + chatSendingViewModel.pendingChatMessageToReplyTo.value?.destroy() + chatSendingViewModel.pendingChatMessageToReplyTo.value = ChatMessageData(chatMessage) + chatSendingViewModel.isPendingAnswer.value = true + } + }) + adapter.showImdnForMessageEvent.observe(viewLifecycleOwner, { it.consume { chatMessage -> val args = Bundle() @@ -278,6 +310,23 @@ class DetailChatRoomFragment : MasterFragment + val events = listViewModel.events.value.orEmpty() + val eventLog = events.find { eventLog -> + if (eventLog.eventLog.type == EventLog.Type.ConferenceChatMessage) { + (eventLog.data as ChatMessageData).chatMessage.messageId == chatMessage.messageId + } else false + } + val index = events.indexOf(eventLog) + try { + binding.chatMessagesList.smoothScrollToPosition(index) + } catch (iae: IllegalArgumentException) { + Log.e("[Chat Room] Can't scroll to position $index") + } + } + }) + binding.setBackClickListener { goBack() } diff --git a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageSendingViewModel.kt b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageSendingViewModel.kt index 2a71f99dd..6d26ac077 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageSendingViewModel.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageSendingViewModel.kt @@ -25,6 +25,7 @@ import androidx.lifecycle.ViewModelProvider import java.io.File import org.linphone.LinphoneApplication.Companion.corePreferences import org.linphone.activities.main.chat.data.ChatMessageAttachmentData +import org.linphone.activities.main.chat.data.ChatMessageData import org.linphone.core.ChatMessage import org.linphone.core.ChatRoom import org.linphone.core.ChatRoomCapabilities @@ -53,6 +54,10 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel() var textToSend = MutableLiveData() + val isPendingAnswer = MutableLiveData() + + var pendingChatMessageToReplyTo = MutableLiveData() + init { attachments.value = arrayListOf() @@ -108,14 +113,18 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel() } fun sendMessage() { - val isBasicChatRoom: Boolean = chatRoom.hasCapability(ChatRoomCapabilities.Basic.toInt()) - val message: ChatMessage = chatRoom.createEmptyMessage() + val pendingMessageToReplyTo = pendingChatMessageToReplyTo.value + val message: ChatMessage = if (isPendingAnswer.value == true && pendingMessageToReplyTo != null) + chatRoom.createReplyMessage(pendingMessageToReplyTo.chatMessage) + else + chatRoom.createEmptyMessage() val toSend = textToSend.value if (toSend != null && toSend.isNotEmpty()) { message.addUtf8TextContent(toSend.trim()) } + val isBasicChatRoom: Boolean = chatRoom.hasCapability(ChatRoomCapabilities.Basic.toInt()) var fileContent = false for (attachment in attachments.value.orEmpty()) { val content = Factory.instance().createContent() @@ -144,6 +153,7 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel() message.send() } + cancelReply() attachments.value.orEmpty().forEach(ChatMessageAttachmentData::destroy) attachments.value = arrayListOf() } @@ -152,4 +162,9 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel() val message = chatRoom.createForwardMessage(chatMessage) message.send() } + + fun cancelReply() { + pendingChatMessageToReplyTo.value?.destroy() + isPendingAnswer.value = false + } } diff --git a/app/src/main/java/org/linphone/utils/LinphoneUtils.kt b/app/src/main/java/org/linphone/utils/LinphoneUtils.kt index 8743e7d3f..a7d9bd209 100644 --- a/app/src/main/java/org/linphone/utils/LinphoneUtils.kt +++ b/app/src/main/java/org/linphone/utils/LinphoneUtils.kt @@ -41,6 +41,15 @@ class LinphoneUtils { private const val RECORDING_DATE_PATTERN = "dd-MM-yyyy-HH-mm-ss" fun getDisplayName(address: Address): String { + if (address.displayName == null) { + val account = coreContext.core.accountList.find { account -> + account.params.identityAddress?.asStringUriOnly() == address.asStringUriOnly() + } + val localDisplayName = account?.params?.identityAddress?.displayName + if (localDisplayName != null) { + return localDisplayName + } + } return address.displayName ?: address.username ?: "" } diff --git a/app/src/main/res/drawable-xhdpi/menu_reply_default.png b/app/src/main/res/drawable-xhdpi/menu_reply_default.png new file mode 100644 index 0000000000000000000000000000000000000000..47fc5db73e7b33dc47cc841be905cf2d63138b3a GIT binary patch literal 11588 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 ai^3pAlD4EqA9uG40H8{miuL!cBK`;UWg$xd literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/replied_message_default.png b/app/src/main/res/drawable-xhdpi/replied_message_default.png new file mode 100644 index 0000000000000000000000000000000000000000..de2fe76492795788ce0445d09701d7c8378736dd GIT binary patch literal 8230 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/reply_message_default.png b/app/src/main/res/drawable-xhdpi/reply_message_default.png new file mode 100644 index 0000000000000000000000000000000000000000..f0d2ff97f83f9aa49ed4156e179c632c013622ad GIT binary patch literal 10985 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 YFHr*8V*S*fT)nw!sN7M0t!N(fKMlSqu>b%7 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/chat_bubble_incoming_full.xml b/app/src/main/res/drawable/chat_bubble_incoming_full.xml index f541f2504..a8d9a3b32 100644 --- a/app/src/main/res/drawable/chat_bubble_incoming_full.xml +++ b/app/src/main/res/drawable/chat_bubble_incoming_full.xml @@ -1,5 +1,5 @@ - + diff --git a/app/src/main/res/drawable/chat_bubble_incoming_split_1.xml b/app/src/main/res/drawable/chat_bubble_incoming_split_1.xml index 46f1fe172..d531a9917 100644 --- a/app/src/main/res/drawable/chat_bubble_incoming_split_1.xml +++ b/app/src/main/res/drawable/chat_bubble_incoming_split_1.xml @@ -1,5 +1,5 @@ - + diff --git a/app/src/main/res/drawable/chat_bubble_incoming_split_2.xml b/app/src/main/res/drawable/chat_bubble_incoming_split_2.xml index a3a9cfcc2..277b01a2f 100644 --- a/app/src/main/res/drawable/chat_bubble_incoming_split_2.xml +++ b/app/src/main/res/drawable/chat_bubble_incoming_split_2.xml @@ -1,5 +1,5 @@ - + diff --git a/app/src/main/res/drawable/chat_bubble_incoming_split_3.xml b/app/src/main/res/drawable/chat_bubble_incoming_split_3.xml index af2af2629..7bc997138 100644 --- a/app/src/main/res/drawable/chat_bubble_incoming_split_3.xml +++ b/app/src/main/res/drawable/chat_bubble_incoming_split_3.xml @@ -1,5 +1,5 @@ - + diff --git a/app/src/main/res/drawable/chat_bubble_outgoing_full.xml b/app/src/main/res/drawable/chat_bubble_outgoing_full.xml index 53c64a052..2117a9a5e 100644 --- a/app/src/main/res/drawable/chat_bubble_outgoing_full.xml +++ b/app/src/main/res/drawable/chat_bubble_outgoing_full.xml @@ -1,5 +1,5 @@ - + diff --git a/app/src/main/res/drawable/chat_bubble_outgoing_split_1.xml b/app/src/main/res/drawable/chat_bubble_outgoing_split_1.xml index 74894387e..42f873e03 100644 --- a/app/src/main/res/drawable/chat_bubble_outgoing_split_1.xml +++ b/app/src/main/res/drawable/chat_bubble_outgoing_split_1.xml @@ -1,5 +1,5 @@ - + diff --git a/app/src/main/res/drawable/chat_bubble_outgoing_split_2.xml b/app/src/main/res/drawable/chat_bubble_outgoing_split_2.xml index 6d58ce71a..97bd2976e 100644 --- a/app/src/main/res/drawable/chat_bubble_outgoing_split_2.xml +++ b/app/src/main/res/drawable/chat_bubble_outgoing_split_2.xml @@ -1,5 +1,5 @@ - + diff --git a/app/src/main/res/drawable/chat_bubble_outgoing_split_3.xml b/app/src/main/res/drawable/chat_bubble_outgoing_split_3.xml index e0df185f3..e1c6f9d03 100644 --- a/app/src/main/res/drawable/chat_bubble_outgoing_split_3.xml +++ b/app/src/main/res/drawable/chat_bubble_outgoing_split_3.xml @@ -1,5 +1,5 @@ - + diff --git a/app/src/main/res/drawable/chat_bubble_reply_background.xml b/app/src/main/res/drawable/chat_bubble_reply_background.xml new file mode 100644 index 000000000..5e5b435c7 --- /dev/null +++ b/app/src/main/res/drawable/chat_bubble_reply_background.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/src/main/res/drawable/chat_bubble_reply_file_background.xml b/app/src/main/res/drawable/chat_bubble_reply_file_background.xml new file mode 100644 index 000000000..c181b358a --- /dev/null +++ b/app/src/main/res/drawable/chat_bubble_reply_file_background.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/app/src/main/res/drawable/chat_bubble_reply_incoming_indicator.xml b/app/src/main/res/drawable/chat_bubble_reply_incoming_indicator.xml new file mode 100644 index 000000000..3bb03b37b --- /dev/null +++ b/app/src/main/res/drawable/chat_bubble_reply_incoming_indicator.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/chat_bubble_reply_outgoing_indicator.xml b/app/src/main/res/drawable/chat_bubble_reply_outgoing_indicator.xml new file mode 100644 index 000000000..3cd2b9b0b --- /dev/null +++ b/app/src/main/res/drawable/chat_bubble_reply_outgoing_indicator.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/menu_reply.xml b/app/src/main/res/drawable/menu_reply.xml new file mode 100644 index 000000000..c3099128f --- /dev/null +++ b/app/src/main/res/drawable/menu_reply.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/app/src/main/res/layout/chat_message_list_cell.xml b/app/src/main/res/layout/chat_message_list_cell.xml index c76c28acf..0d56b3f67 100644 --- a/app/src/main/res/layout/chat_message_list_cell.xml +++ b/app/src/main/res/layout/chat_message_list_cell.xml @@ -13,6 +13,9 @@ + @@ -90,7 +93,6 @@ android:layout_marginBottom="1dp" android:layout_marginRight="@{data.chatMessage.outgoing ? @dimen/outgoing_chat_message_bubble_right_margin : @dimen/incoming_chat_message_bubble_right_margin}" android:layout_marginLeft="@{selectionListViewModel.isEditionEnabled ? @dimen/edit_chat_message_bubble_left_margin : !data.chatMessage.outgoing ? @dimen/incoming_chat_message_bubble_left_margin : @dimen/outgoing_chat_message_bubble_left_margin}" - android:paddingTop="5dp" android:paddingBottom="5dp"> @@ -123,9 +126,52 @@ + + + + + + + + + + + @@ -70,6 +73,15 @@ style="@style/popup_item_font" android:text="@string/chat_message_context_menu_forward" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/chat_message_reply_bubble.xml b/app/src/main/res/layout/chat_message_reply_bubble.xml new file mode 100644 index 000000000..61a2b5207 --- /dev/null +++ b/app/src/main/res/layout/chat_message_reply_bubble.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/chat_message_reply_content_cell.xml b/app/src/main/res/layout/chat_message_reply_content_cell.xml new file mode 100644 index 000000000..9da6290dd --- /dev/null +++ b/app/src/main/res/layout/chat_message_reply_content_cell.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/chat_message_reply_preview_content_cell.xml b/app/src/main/res/layout/chat_message_reply_preview_content_cell.xml new file mode 100644 index 000000000..ccea18ba3 --- /dev/null +++ b/app/src/main/res/layout/chat_message_reply_preview_content_cell.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/chat_room_detail_fragment.xml b/app/src/main/res/layout/chat_room_detail_fragment.xml index 393f9cc4b..12db0e4be 100644 --- a/app/src/main/res/layout/chat_room_detail_fragment.xml +++ b/app/src/main/res/layout/chat_room_detail_fragment.xml @@ -147,6 +147,12 @@ android:background="?attr/lightToolbarBackgroundColor" android:orientation="vertical"> + + Sélectionnez ou créez une conversation pour partager le(s) fichier(s) Sélectionnez ou créez une conversation pour partager le texte Messages éphémères (bêta) + Répondre + Réponse + Message + Réponse diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index a493e51c1..3bbc1bda6 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -20,13 +20,18 @@ #e1e1e1 #f3f3f3 #c2c2c2 + #a1a1a1 #f3f3f3 + #9b9b9b #ffeee5 + #ff9e67 + #f4f4f4 + #dedede #808080 #99ffffff diff --git a/app/src/main/res/values/dimen.xml b/app/src/main/res/values/dimen.xml index 8739f7fb6..3f8ea7826 100644 --- a/app/src/main/res/values/dimen.xml +++ b/app/src/main/res/values/dimen.xml @@ -9,6 +9,7 @@ 100dp 120dp 30dp + 50dp 600dp 200dp 45dp @@ -26,4 +27,5 @@ 60dp 250dp 50dp + 6.7dp \ 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 ef17326af..b4aa86075 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -168,9 +168,11 @@ Undelivered Sent Forwarded + Reply Resend Copy text Forward + Reply Delivery status Delete Add to contacts @@ -214,6 +216,8 @@ Would you like to open it as text or export it (unencrypted) to a third party app if available? Export Open as text + Reply + Message No recordings @@ -622,6 +626,7 @@ Attached file Message delivery status Message has been forwarded + Message is a reply Forward message in this conversation Message is ephemeral Contact is a &appName; user @@ -636,6 +641,7 @@ Show chat room menu Enter edition mode Attach a file to the message + File attached to the message Send message Show or hide the participant devices Ephemeral duration selected diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 347f78728..ab7875f81 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -111,6 +111,20 @@ 13sp + + + + + +