Unverified Commit d2429363 authored by Rafael Kellermann Streit's avatar Rafael Kellermann Streit Committed by GitHub

Merge pull request #1953 from RocketChat/fix/emoji-keyboard

[FIX] Emoji keyboard
parents 39defb0a 593b38d8
...@@ -317,8 +317,8 @@ class ChatRoomPresenter @Inject constructor( ...@@ -317,8 +317,8 @@ class ChatRoomPresenter @Inject constructor(
launchUI(strategy) { launchUI(strategy) {
try { try {
// ignore message for now, will receive it on the stream // ignore message for now, will receive it on the stream
val id = UUID.randomUUID().toString()
if (messageId == null) { if (messageId == null) {
val id = UUID.randomUUID().toString()
val username = userHelper.username() val username = userHelper.username()
val newMessage = Message( val newMessage = Message(
id = id, id = id,
...@@ -371,13 +371,12 @@ class ChatRoomPresenter @Inject constructor( ...@@ -371,13 +371,12 @@ class ChatRoomPresenter @Inject constructor(
} else { } else {
client.updateMessage(chatRoomId, messageId, text) client.updateMessage(chatRoomId, messageId, text)
} }
clearDraftMessage()
clearUnfinishedMessage()
view.enableSendMessageButton()
} catch (ex: Exception) { } catch (ex: Exception) {
Timber.d(ex, "Error sending message...") Timber.e(ex, "Error sending message...")
jobSchedulerInteractor.scheduleSendingMessages() jobSchedulerInteractor.scheduleSendingMessages()
} finally { } finally {
view.clearMessageComposition(true)
view.enableSendMessageButton() view.enableSendMessageButton()
} }
} }
...@@ -1265,10 +1264,9 @@ class ChatRoomPresenter @Inject constructor( ...@@ -1265,10 +1264,9 @@ class ChatRoomPresenter @Inject constructor(
launchUI(strategy) { launchUI(strategy) {
val viewModelStreamedMessage = mapper.map( val viewModelStreamedMessage = mapper.map(
streamedMessage, RoomUiModel( streamedMessage, RoomUiModel(
roles = chatRoles, isBroadcast = chatIsBroadcast, isRoom = true roles = chatRoles, isBroadcast = chatIsBroadcast, isRoom = true
) )
) )
val roomMessages = messagesRepository.getByRoomId(streamedMessage.roomId) val roomMessages = messagesRepository.getByRoomId(streamedMessage.roomId)
val index = roomMessages.indexOfFirst { msg -> msg.id == streamedMessage.id } val index = roomMessages.indexOfFirst { msg -> msg.id == streamedMessage.id }
if (index > -1) { if (index > -1) {
...@@ -1294,13 +1292,13 @@ class ChatRoomPresenter @Inject constructor( ...@@ -1294,13 +1292,13 @@ class ChatRoomPresenter @Inject constructor(
* *
* @param unfinishedMessage The unfinished message to save. * @param unfinishedMessage The unfinished message to save.
*/ */
fun saveUnfinishedMessage(unfinishedMessage: String) { fun saveDraftMessage(unfinishedMessage: String) {
if (unfinishedMessage.isNotBlank()) { if (unfinishedMessage.isNotBlank()) {
localRepository.save(draftKey, unfinishedMessage) localRepository.save(draftKey, unfinishedMessage)
} }
} }
fun clearUnfinishedMessage() { fun clearDraftMessage() {
localRepository.clear(draftKey) localRepository.clear(draftKey)
} }
/** /**
...@@ -1309,7 +1307,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -1309,7 +1307,7 @@ class ChatRoomPresenter @Inject constructor(
* *
* @return Returns the unfinished message, null otherwise. * @return Returns the unfinished message, null otherwise.
*/ */
fun getUnfinishedMessage(): String? { fun getDraftUnfinishedMessage(): String? {
return localRepository.get(draftKey) return localRepository.get(draftKey)
} }
} }
...@@ -6,7 +6,6 @@ import android.content.ClipData ...@@ -6,7 +6,6 @@ import android.content.ClipData
import android.content.ClipboardManager import android.content.ClipboardManager
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.res.Configuration
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
...@@ -308,7 +307,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -308,7 +307,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
showToolbarTitle(chatRoomName) showToolbarTitle(chatRoomName)
showToolbarChatRoomIcon(chatRoomType) showToolbarChatRoomIcon(chatRoomType)
} }
getUnfinishedMessage() getDraftMessage()
analyticsManager.logScreenView(ScreenViewEvent.ChatRoom) analyticsManager.logScreenView(ScreenViewEvent.ChatRoom)
} }
...@@ -323,7 +322,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -323,7 +322,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
recycler_view.removeOnScrollListener(onScrollListener) recycler_view.removeOnScrollListener(onScrollListener)
recycler_view.removeOnLayoutChangeListener(layoutChangeListener) recycler_view.removeOnLayoutChangeListener(layoutChangeListener)
presenter.saveUnfinishedMessage(text_message.text.toString()) presenter.saveDraftMessage(text_message.text.toString())
handler.removeCallbacksAndMessages(null) handler.removeCallbacksAndMessages(null)
unsubscribeComposeTextMessage() unsubscribeComposeTextMessage()
presenter.disconnect() presenter.disconnect()
...@@ -437,6 +436,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -437,6 +436,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
} }
presenter.loadActiveMembers(chatRoomId, chatRoomType, filterSelfOut = true) presenter.loadActiveMembers(chatRoomId, chatRoomType, filterSelfOut = true)
empty_chat_view.isVisible = adapter.itemCount == 0 empty_chat_view.isVisible = adapter.itemCount == 0
dismissEmojiKeyboard()
} }
} }
...@@ -445,6 +445,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -445,6 +445,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
adapter.clearData() adapter.clearData()
adapter.prependData(dataSet) adapter.prependData(dataSet)
empty_chat_view.isVisible = adapter.itemCount == 0 empty_chat_view.isVisible = adapter.itemCount == 0
dismissEmojiKeyboard()
} }
override fun onRoomUpdated(roomUiModel: RoomUiModel) { override fun onRoomUpdated(roomUiModel: RoomUiModel) {
...@@ -502,25 +503,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -502,25 +503,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
showMessage(getString(R.string.msg_invalid_file)) showMessage(getString(R.string.msg_invalid_file))
} }
override fun showNewMessage(message: List<BaseUiModel<*>>, isMessageReceived: Boolean) {
ui {
adapter.prependData(message)
if (isMessageReceived && button_fab.isVisible) {
newMessageCount++
if (newMessageCount <= 99)
text_count.text = newMessageCount.toString()
else
text_count.text = "99+"
text_count.isVisible = true
} else if (!button_fab.isVisible)
recycler_view.scrollToPosition(0)
verticalScrollOffset.set(0)
empty_chat_view.isVisible = adapter.itemCount == 0
}
}
override fun disableSendMessageButton() { override fun disableSendMessageButton() {
ui { button_send.isEnabled = false } ui { button_send.isEnabled = false }
} }
...@@ -544,6 +526,28 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -544,6 +526,28 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
} }
} }
override fun showNewMessage(message: List<BaseUiModel<*>>, isMessageReceived: Boolean) {
ui {
adapter.prependData(message)
if (isMessageReceived && button_fab.isVisible) {
newMessageCount++
if (newMessageCount <= 99) {
text_count.text = newMessageCount.toString()
} else {
text_count.text = "99+"
}
text_count.isVisible = true
}
else if (!button_fab.isVisible) {
recycler_view.scrollToPosition(0)
}
verticalScrollOffset.set(0)
empty_chat_view.isVisible = adapter.itemCount == 0
dismissEmojiKeyboard()
}
}
override fun dispatchUpdateMessage(index: Int, message: List<BaseUiModel<*>>) { override fun dispatchUpdateMessage(index: Int, message: List<BaseUiModel<*>>) {
ui { ui {
// TODO - investigate WHY we get a empty list here // TODO - investigate WHY we get a empty list here
...@@ -556,6 +560,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -556,6 +560,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
} else { } else {
showNewMessage(message, true) showNewMessage(message, true)
} }
dismissEmojiKeyboard()
} }
} }
...@@ -723,8 +728,8 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -723,8 +728,8 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
} }
private fun setReactionButtonIcon(@DrawableRes drawableId: Int) { private fun setReactionButtonIcon(@DrawableRes drawableId: Int) {
button_add_reaction.setImageResource(drawableId) button_add_reaction_or_show_keyboard.setImageResource(drawableId)
button_add_reaction.tag = drawableId button_add_reaction_or_show_keyboard.tag = drawableId
} }
override fun showFileSelection(filter: Array<String>?) { override fun showFileSelection(filter: Array<String>?) {
...@@ -841,9 +846,13 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -841,9 +846,13 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
subscribeComposeTextMessage() subscribeComposeTextMessage()
emojiKeyboardPopup = EmojiKeyboardPopup(activity!!, activity!!.findViewById(R.id.fragment_container)) emojiKeyboardPopup = EmojiKeyboardPopup(activity!!, activity!!.findViewById(R.id.fragment_container))
emojiKeyboardPopup.listener = this emojiKeyboardPopup.listener = this
text_message.listener = object : ComposerEditText.ComposerEditTextListener { text_message.listener = object : ComposerEditText.ComposerEditTextListener {
override fun onKeyboardOpened() {} override fun onKeyboardOpened() {
KeyboardHelper.showSoftKeyboard(text_message)
}
override fun onKeyboardClosed() { override fun onKeyboardClosed() {
activity?.let { activity?.let {
...@@ -860,7 +869,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -860,7 +869,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
var textMessage = citation ?: "" var textMessage = citation ?: ""
textMessage += text_message.textContent textMessage += text_message.textContent
sendMessage(textMessage) sendMessage(textMessage)
clearMessageComposition(true)
} }
button_show_attachment_options.setOnClickListener { button_show_attachment_options.setOnClickListener {
...@@ -875,9 +883,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -875,9 +883,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
hideAttachmentOptions() hideAttachmentOptions()
} }
button_add_reaction.setOnClickListener { _ -> button_add_reaction_or_show_keyboard.setOnClickListener { toggleKeyboard() }
openEmojiKeyboardPopup()
}
button_take_a_photo.setOnClickListener { button_take_a_photo.setOnClickListener {
dispatchTakePictureIntent() dispatchTakePictureIntent()
...@@ -934,8 +940,8 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -934,8 +940,8 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
} }
} }
private fun getUnfinishedMessage() { private fun getDraftMessage() {
val unfinishedMessage = presenter.getUnfinishedMessage() val unfinishedMessage = presenter.getDraftUnfinishedMessage()
if (unfinishedMessage.isNotNullNorEmpty()) { if (unfinishedMessage.isNotNullNorEmpty()) {
text_message.setText(unfinishedMessage) text_message.setText(unfinishedMessage)
} }
...@@ -969,19 +975,10 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -969,19 +975,10 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
presenter.loadCommands() presenter.loadCommands()
} }
private fun openEmojiKeyboardPopup() { // Shows the emoji or the system keyboard.
private fun toggleKeyboard() {
if (!emojiKeyboardPopup.isShowing) { if (!emojiKeyboardPopup.isShowing) {
// If keyboard is visible, simply show the popup openEmojiKeyboard()
if (emojiKeyboardPopup.isKeyboardOpen) {
emojiKeyboardPopup.showAtBottom()
} else {
// Open the text keyboard first and immediately after that show the emoji popup
text_message.isFocusableInTouchMode = true
text_message.requestFocus()
emojiKeyboardPopup.showAtBottomPending()
KeyboardHelper.showSoftKeyboard(text_message)
}
setReactionButtonIcon(R.drawable.ic_keyboard_black_24dp)
} else { } else {
// If popup is showing, simply dismiss it to show the underlying text keyboard // If popup is showing, simply dismiss it to show the underlying text keyboard
dismissEmojiKeyboard() dismissEmojiKeyboard()
...@@ -1149,6 +1146,20 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -1149,6 +1146,20 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
description = "This message was reported by a user from the Android app") description = "This message was reported by a user from the Android app")
} }
fun openEmojiKeyboard() {
// If keyboard is visible, simply show the popup
if (emojiKeyboardPopup.isKeyboardOpen) {
emojiKeyboardPopup.showAtBottom()
} else {
// Open the text keyboard first and immediately after that show the emoji popup
text_message.isFocusableInTouchMode = true
text_message.requestFocus()
emojiKeyboardPopup.showAtBottomPending()
KeyboardHelper.showSoftKeyboard(text_message)
}
setReactionButtonIcon(R.drawable.ic_keyboard_black_24dp)
}
fun dismissEmojiKeyboard() { fun dismissEmojiKeyboard() {
// Check if the keyboard was ever initialized. // Check if the keyboard was ever initialized.
// It may be the case when you are looking a not joined room // It may be the case when you are looking a not joined room
......
...@@ -7,13 +7,7 @@ ...@@ -7,13 +7,7 @@
<path <path
android:fillColor="#000000" android:fillColor="#000000"
android:pathData="M20,5 L4,5 C2.9,5,2.01,5.9,2.01,7 L2,17 C2,18.1,2.9,19,4,19 L20,19 android:pathData="M20,5 L4,5 C2.9,5,2.01,5.9,2.01,7 L2,17 C2,18.1,2.9,19,4,19 L20,19 C21.1,19,22,18.1,22,17 L22,7 C22,5.9,21.1,5,20,5 Z M11,8 L13,8 L13,10 L11,10 L11,8 Z M11,11 L13,11 L13,13 L11,13 L11,11 Z M8,8 L10,8 L10,10 L8,10 L8,8 Z M8,11 L10,11 L10,13 L8,13 L8,11 Z M7,13 L5,13 L5,11 L7,11 L7,13 Z M7,10 L5,10 L5,8 L7,8 L7,10 Z M16,17 L8,17 L8,15 L16,15 L16,17 Z M16,13 L14,13 L14,11 L16,11 L16,13 Z M16,10 L14,10 L14,8 L16,8 L16,10 Z M19,13 L17,13 L17,11 L19,11 L19,13 Z M19,10 L17,10 L17,8 L19,8 L19,10 Z" />
C21.1,19,22,18.1,22,17 L22,7 C22,5.9,21.1,5,20,5 Z M11,8 L13,8 L13,10 L11,10
L11,8 Z M11,11 L13,11 L13,13 L11,13 L11,11 Z M8,8 L10,8 L10,10 L8,10 L8,8 Z <path android:pathData="M0,0 L24,0 L24,24 L0,24 Z M-24,0 L0,0 L0,24 L0,24 Z" />
M8,11 L10,11 L10,13 L8,13 L8,11 Z M7,13 L5,13 L5,11 L7,11 L7,13 Z M7,10 L5,10
L5,8 L7,8 L7,10 Z M16,17 L8,17 L8,15 L16,15 L16,17 Z M16,13 L14,13 L14,11 L16,11
L16,13 Z M16,10 L14,10 L14,8 L16,8 L16,10 Z M19,13 L17,13 L17,11 L19,11 L19,13 Z
M19,10 L17,10 L17,8 L19,8 L19,10 Z" />
<path
android:pathData="M0,0 L24,0 L24,24 L0,24 Z M-24,0 L0,0 L0,24 L0,24 Z" />
</vector> </vector>
\ No newline at end of file
...@@ -59,13 +59,12 @@ ...@@ -59,13 +59,12 @@
app:layout_constraintTop_toBottomOf="@+id/divider"> app:layout_constraintTop_toBottomOf="@+id/divider">
<ImageButton <ImageButton
android:id="@+id/button_add_reaction" android:id="@+id/button_add_reaction_or_show_keyboard"
android:layout_width="32dp" android:layout_width="32dp"
android:layout_height="32dp" android:layout_height="32dp"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/msg_content_description_show_attachment_options"
android:src="@drawable/ic_reaction_24dp" /> android:src="@drawable/ic_reaction_24dp" />
<chat.rocket.android.emoji.ComposerEditText <chat.rocket.android.emoji.ComposerEditText
......
...@@ -25,9 +25,7 @@ import kotlinx.android.synthetic.main.dialog_skin_tone_chooser.view.* ...@@ -25,9 +25,7 @@ import kotlinx.android.synthetic.main.dialog_skin_tone_chooser.view.*
import kotlinx.coroutines.experimental.android.UI import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.launch import kotlinx.coroutines.experimental.launch
class EmojiKeyboardPopup(context: Context, view: View) : OverKeyboardPopupWindow(context, view) { class EmojiKeyboardPopup(context: Context, view: View) : OverKeyboardPopupWindow(context, view) {
private lateinit var viewPager: ViewPager private lateinit var viewPager: ViewPager
private lateinit var tabLayout: TabLayout private lateinit var tabLayout: TabLayout
private lateinit var searchView: View private lateinit var searchView: View
...@@ -84,7 +82,7 @@ class EmojiKeyboardPopup(context: Context, view: View) : OverKeyboardPopupWindow ...@@ -84,7 +82,7 @@ class EmojiKeyboardPopup(context: Context, view: View) : OverKeyboardPopupWindow
.setCancelable(true) .setCancelable(true)
.create() .create()
with (view) { with(view) {
image_view_default_tone.setOnClickListener { image_view_default_tone.setOnClickListener {
dialog.dismiss() dialog.dismiss()
changeSkinTone(Fitzpatrick.Default) changeSkinTone(Fitzpatrick.Default)
...@@ -138,7 +136,10 @@ class EmojiKeyboardPopup(context: Context, view: View) : OverKeyboardPopupWindow ...@@ -138,7 +136,10 @@ class EmojiKeyboardPopup(context: Context, view: View) : OverKeyboardPopupWindow
return when (tone) { return when (tone) {
Fitzpatrick.Default -> ContextCompat.getColor(context, R.color.tone_default) Fitzpatrick.Default -> ContextCompat.getColor(context, R.color.tone_default)
Fitzpatrick.LightTone -> ContextCompat.getColor(context, R.color.tone_light) Fitzpatrick.LightTone -> ContextCompat.getColor(context, R.color.tone_light)
Fitzpatrick.MediumLightTone -> ContextCompat.getColor(context, R.color.tone_medium_light) Fitzpatrick.MediumLightTone -> ContextCompat.getColor(
context,
R.color.tone_medium_light
)
Fitzpatrick.MediumTone -> ContextCompat.getColor(context, R.color.tone_medium) Fitzpatrick.MediumTone -> ContextCompat.getColor(context, R.color.tone_medium)
Fitzpatrick.MediumDarkTone -> ContextCompat.getColor(context, R.color.tone_medium_dark) Fitzpatrick.MediumDarkTone -> ContextCompat.getColor(context, R.color.tone_medium_dark)
Fitzpatrick.DarkTone -> ContextCompat.getColor(context, R.color.tone_dark) Fitzpatrick.DarkTone -> ContextCompat.getColor(context, R.color.tone_dark)
...@@ -151,7 +152,7 @@ class EmojiKeyboardPopup(context: Context, view: View) : OverKeyboardPopupWindow ...@@ -151,7 +152,7 @@ class EmojiKeyboardPopup(context: Context, view: View) : OverKeyboardPopupWindow
is EmojiKeyboardListener -> it is EmojiKeyboardListener -> it
else -> { else -> {
val fragments = (it as AppCompatActivity).supportFragmentManager.fragments val fragments = (it as AppCompatActivity).supportFragmentManager.fragments
if (fragments.size == 0 || !(fragments[0] is EmojiKeyboardListener)) { if (fragments.size == 0 || fragments[0] !is EmojiKeyboardListener) {
// Since the app can arrive in an inconsistent state at this point, do not throw // Since the app can arrive in an inconsistent state at this point, do not throw
// throw IllegalStateException("activity/fragment should implement Listener interface") // throw IllegalStateException("activity/fragment should implement Listener interface")
null null
...@@ -190,7 +191,6 @@ class EmojiKeyboardPopup(context: Context, view: View) : OverKeyboardPopupWindow ...@@ -190,7 +191,6 @@ class EmojiKeyboardPopup(context: Context, view: View) : OverKeyboardPopupWindow
} }
class EmojiTextWatcher(private val editor: EditText) : TextWatcher { class EmojiTextWatcher(private val editor: EditText) : TextWatcher {
@Volatile @Volatile
private var emojiToRemove = mutableListOf<EmojiTypefaceSpan>() private var emojiToRemove = mutableListOf<EmojiTypefaceSpan>()
......
...@@ -21,7 +21,6 @@ package chat.rocket.android.emoji ...@@ -21,7 +21,6 @@ package chat.rocket.android.emoji
import android.content.Context import android.content.Context
import android.graphics.Point import android.graphics.Point
import android.graphics.Rect import android.graphics.Rect
import android.os.Build
import android.view.Gravity import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment