Commit 4a86cd34 authored by Filipe de Lima Brito's avatar Filipe de Lima Brito

Prevents losing all entered text when a new message arrives on the chat room. Also,

Keeps the keyboard open after sending a message.
Shows the entire new message when it arrives on the chat room.
Adds a widget to easily show the latest messages when moving the list up.
parent befa16fc
......@@ -39,7 +39,6 @@ class ChatRoomPresenter @Inject constructor(private val view: ChatRoomView,
private val client = factory.create(serverInteractor.get()!!)
private var subId: String? = null
private var settings: Map<String, Value<Any>> = getSettingsInteractor.get(serverInteractor.get()!!)!!
private val stateChannel = Channel<State>()
fun loadMessages(chatRoomId: String, chatRoomType: String, offset: Long = 0) {
......@@ -72,23 +71,23 @@ class ChatRoomPresenter @Inject constructor(private val view: ChatRoomView,
fun sendMessage(chatRoomId: String, text: String, messageId: String?) {
launchUI(strategy) {
view.disableMessageInput()
view.disableSendMessageButton()
try {
// ignore message for now, will receive it on the stream
val message = if (messageId == null) {
client.sendMessage(chatRoomId, text)
} else {
client.updateMessage(chatRoomId, messageId, text)
}
// ignore message for now, will receive it on the stream
view.enableMessageInput(clear = true)
view.clearMessageComposition()
} catch (ex: Exception) {
ex.printStackTrace()
ex.message?.let {
view.showMessage(it)
}.ifNull {
view.showGenericErrorMessage()
}
view.enableMessageInput()
} finally {
view.enableSendMessageButton()
}
}
}
......
......@@ -75,7 +75,19 @@ interface ChatRoomView : LoadingView, MessageView {
*/
fun showEditingAction(roomId: String, messageId: String, text: String)
fun disableMessageInput()
/**
* Disabling the send message button avoids the user tap this button multiple
* times to send a same message.
*/
fun disableSendMessageButton()
fun enableMessageInput(clear: Boolean = false)
/**
* Enables the send message button.
*/
fun enableSendMessageButton()
/**
* Clears the message composition.
*/
fun clearMessageComposition()
}
\ No newline at end of file
......@@ -24,6 +24,8 @@ import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_chat_room.*
import kotlinx.android.synthetic.main.message_attachment_options.*
import kotlinx.android.synthetic.main.message_composer.*
import kotlinx.android.synthetic.main.message_list.*
import timber.log.Timber
import javax.inject.Inject
fun newInstance(chatRoomId: String, chatRoomName: String, chatRoomType: String, isChatRoomReadOnly: Boolean): Fragment {
......@@ -85,7 +87,10 @@ class ChatRoomFragment : Fragment(), ChatRoomView {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
presenter.loadMessages(chatRoomId, chatRoomType)
setupComposer()
setupRecyclerView()
setupFab()
setupMessageComposer()
setupActionSnackbar()
}
......@@ -156,20 +161,23 @@ class ChatRoomFragment : Fragment(), ChatRoomView {
override fun showInvalidFileMessage() = showMessage(getString(R.string.msg_invalid_file))
override fun showNewMessage(message: MessageViewModel) {
text_message.textContent = ""
adapter.addItem(message)
recycler_view.smoothScrollToPosition(0)
recycler_view.scrollToPosition(0)
}
override fun disableMessageInput() {
override fun disableSendMessageButton() {
button_send.isEnabled = false
text_message.isEnabled = false
}
override fun enableMessageInput(clear: Boolean) {
override fun enableSendMessageButton() {
button_send.isEnabled = true
text_message.isEnabled = true
if (clear) text_message.textContent = ""
}
override fun clearMessageComposition() {
citation = null
editingMessageId = null
text_message.textContent = ""
actionSnackbar.dismiss()
}
override fun dispatchUpdateMessage(index: Int, message: MessageViewModel) {
......@@ -217,7 +225,32 @@ class ChatRoomFragment : Fragment(), ChatRoomView {
}
private fun setupComposer() {
private fun setupRecyclerView() {
recycler_view.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
Timber.i("Scrolling vertically: $dy")
if (!recyclerView.canScrollVertically(1)) {
button_fab.hide()
} else {
if (dy > 0 && !button_fab.isVisible()) {
button_fab.show()
} else if (dy < 0 && button_fab.isVisible()) {
button_fab.hide()
}
}
}
})
}
private fun setupFab() {
button_fab.setOnClickListener {
recycler_view.scrollToPosition(0)
button_fab.hide()
}
}
private fun setupMessageComposer() {
if (isChatRoomReadOnly) {
text_room_is_read_only.setVisible(true)
input_container.setVisible(false)
......@@ -239,10 +272,9 @@ class ChatRoomFragment : Fragment(), ChatRoomView {
})
button_send.setOnClickListener {
var textMessage = citation ?: ""
textMessage += text_message.textContent
sendMessage(textMessage)
clearActionMessage()
var message = citation ?: ""
message += text_message.textContent
sendMessage(message)
}
......@@ -271,17 +303,10 @@ class ChatRoomFragment : Fragment(), ChatRoomView {
private fun setupActionSnackbar() {
actionSnackbar = ActionSnackbar.make(message_list_container, parser = parser)
actionSnackbar.cancelView.setOnClickListener({
clearActionMessage()
clearMessageComposition()
})
}
private fun clearActionMessage() {
citation = null
editingMessageId = null
text_message.text.clear()
actionSnackbar.dismiss()
}
private fun showAttachmentOptions() {
view_dim.setVisible(true)
......
......@@ -18,6 +18,7 @@ import chat.rocket.core.model.ChatRoom
import com.facebook.drawee.view.SimpleDraweeView
import kotlinx.android.synthetic.main.avatar.view.*
import kotlinx.android.synthetic.main.item_chat.view.*
import kotlinx.android.synthetic.main.unread_messages_badge.view.*
class ChatRoomsAdapter(private val context: Context,
private val listener: (ChatRoom) -> Unit) : RecyclerView.Adapter<ChatRoomsAdapter.ViewHolder>() {
......
......@@ -21,6 +21,10 @@ fun View.setVisible(visible: Boolean) {
}
}
fun View.isVisible(): Boolean {
return visibility == View.VISIBLE
}
fun ViewGroup.inflate(@LayoutRes resource: Int): View = LayoutInflater.from(context).inflate(resource, this, false)
fun AppCompatActivity.addFragment(tag: String, layoutId: Int, newInstance: () -> Fragment) {
......
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#010101"
android:pathData="M20,12l-1.41,-1.41L13,16.17V4h-2v12.17l-5.58,-5.59L4,12l8,8 8,-8z" />
</vector>
\ No newline at end of file
......@@ -4,8 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:layout_height="match_parent">
<com.wang.avi.AVLoadingIndicatorView
android:id="@+id/view_loading"
......@@ -20,16 +19,23 @@
<FrameLayout
android:id="@+id/message_list_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:layout_above="@+id/layout_message_composer">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
<include
android:id="@+id/layout_message_list"
layout="@layout/message_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
android:layout_height="match_parent" />
</FrameLayout>
<include
android:id="@+id/layout_message_composer"
layout="@layout/message_composer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
<View
android:id="@+id/view_dim"
android:layout_width="match_parent"
......@@ -45,14 +51,6 @@
android:layout_height="wrap_content"
android:layout_above="@+id/layout_message_composer"
android:layout_margin="5dp"
android:visibility="gone"
tools:visibility="visible" />
<include
android:id="@+id/layout_message_composer"
layout="@layout/message_composer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
android:visibility="gone" />
</RelativeLayout>
......@@ -78,23 +78,16 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/guideline_one"
app:layout_constraintRight_toRightOf="@+id/text_total_unread_messages"
app:layout_constraintRight_toRightOf="@+id/layout_unread_messages_badge"
tools:text="11:45" />
<TextView
android:id="@+id/text_total_unread_messages"
style="@style/TextAppearance.AppCompat.Caption"
<include
android:id="@+id/layout_unread_messages_badge"
layout="@layout/unread_messages_badge"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@drawable/style_total_unread_messages"
android:gravity="center"
android:textColor="@color/white"
android:textSize="10sp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/guideline_two"
app:layout_constraintRight_toRightOf="parent"
tools:text="99+"
tools:visibility="visible" />
app:layout_constraintRight_toRightOf="parent" />
<android.support.constraint.Guideline
android:id="@+id/guideline_one"
......
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/button_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@drawable/ic_arrow_downward_black_24dp"
android:theme="@style/Theme.AppCompat"
android:tint="@color/gray_material"
android:visibility="invisible"
app:backgroundTint="@color/white"
app:fabSize="mini"
app:layout_anchor="@id/recycler_view"
app:layout_anchorGravity="bottom|end" />
</android.support.design.widget.CoordinatorLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text_total_unread_messages"
style="@style/TextAppearance.AppCompat.Caption"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@drawable/style_total_unread_messages"
android:gravity="center"
android:textColor="@color/white"
android:textSize="10sp"
android:visibility="gone"
tools:text="99+"
tools:visibility="visible" />
</LinearLayout>
\ No newline at end of file
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