Skip to content

Commit

Permalink
Merge pull request #222 from WideChat/contact_online_status
Browse files Browse the repository at this point in the history
Added status indicator to the profile button in the home screen and to contacts screen
  • Loading branch information
ear-dev authored Feb 4, 2019
2 parents a99e30e + a2afbb7 commit 16281ec
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,11 @@ class ChatRoomsPresenter @Inject constructor(
}
}

private suspend fun getCurrentUser(): User? {
userHelper.user()?.let {
return it
suspend fun getCurrentUser(local: Boolean = true): User? {
if (local) {
userHelper.user()?.let {
return it
}
}
try {
val myself = retryIO { client.me() }
Expand All @@ -157,6 +159,7 @@ class ChatRoomsPresenter @Inject constructor(
roles = myself.roles
)
localRepository.saveCurrentUser(url = currentServer, user = user)
return user
} catch (ex: RocketChatException) {
Timber.e(ex)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import javax.inject.Inject
// WIDECHAT
import android.graphics.Color
import android.widget.*
import androidx.core.view.isGone
import chat.rocket.android.authentication.domain.model.DeepLinkInfo
import chat.rocket.android.chatrooms.adapter.model.RoomUiModel
import chat.rocket.android.helper.UserHelper
Expand All @@ -54,6 +55,7 @@ import chat.rocket.android.settings.ui.SettingsFragment
import chat.rocket.android.util.extensions.avatarUrl
import com.facebook.drawee.view.SimpleDraweeView
import kotlinx.android.synthetic.main.app_bar.*
import kotlinx.coroutines.experimental.launch

internal const val TAG_CHAT_ROOMS_FRAGMENT = "ChatRoomsFragment"

Expand Down Expand Up @@ -88,7 +90,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
private var searchText: TextView? = null
private var searchCloseButton: ImageView? = null
private var profileButton: SimpleDraweeView? = null
private var onlineStatusButton:ImageView?=null
private var currentUserStatusIcon: ImageView? = null
private var deepLinkInfo: DeepLinkInfo? = null
// handles that recurring connection status bug in widechat
private var currentlyConnected: Boolean? = false
Expand Down Expand Up @@ -132,6 +134,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
searchView?.setQuery("", false)
viewModel.showLastMessage = true
}
setCurrentUserStatusIcon()
super.onResume()
}

Expand Down Expand Up @@ -440,6 +443,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
is State.Connected -> {
text_connection_status.text = getString(R.string.status_connected)
handler.postDelayed(dismissStatus, 2000)
setCurrentUserStatusIcon()
}
is State.Disconnected -> text_connection_status.text =
getString(R.string.status_disconnected)
Expand Down Expand Up @@ -482,7 +486,6 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
val myAvatarUrl: String? = serverUrl?.avatarUrl(user?.username ?: "")

profileButton = this?.getCustomView()?.findViewById(R.id.profile_image_avatar)
onlineStatusButton=this?.getCustomView()?.findViewById(R.id.text_online)
profileButton?.setImageURI(myAvatarUrl)
profileButton?.setOnClickListener { v ->

Expand All @@ -501,6 +504,20 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
}
}

private fun setCurrentUserStatusIcon() {
with((activity as AppCompatActivity?)?.supportActionBar) {
currentUserStatusIcon = this?.getCustomView()?.findViewById(R.id.self_status)
}
launch {
val currentUser = presenter.getCurrentUser(false)
val drawable = DrawableHelper.getUserStatusDrawable(currentUser?.status, context!!)
ui {
currentUserStatusIcon?.isVisible = true
currentUserStatusIcon?.setImageDrawable(drawable)
}
}
}

private fun queryChatRoomsByName(name: String?): Boolean {
if (name.isNullOrEmpty()) {
updateSort()
Expand All @@ -512,6 +529,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {

private fun setupFab() {
create_new_channel_fab.setOnClickListener { view ->
currentUserStatusIcon?.isGone = true
val contactsFragment = ContactsFragment()
val transaction = activity?.supportFragmentManager?.beginTransaction();
transaction?.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package chat.rocket.android.contacts.adapter

import android.content.Intent
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.Button
Expand All @@ -9,8 +8,11 @@ import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R
import chat.rocket.android.chatrooms.adapter.*
import chat.rocket.android.contacts.models.Contact
import chat.rocket.android.db.model.UserEntity
import chat.rocket.android.main.ui.MainActivity
import chat.rocket.android.util.extensions.inflate
import kotlinx.coroutines.experimental.launch

class ContactRecyclerViewAdapter(
private val context: MainActivity,
Expand Down Expand Up @@ -65,26 +67,37 @@ class ContactRecyclerViewAdapter(
override fun onBindViewHolder(holder: ViewHolder<*>, position: Int) {
if (holder is ContactViewHolder) {
holder.bind(contactArrayList[position] as ContactItemHolder)

val contact: Contact = holder.data!!.data
val username = contact.getUsername()
var user: UserEntity?
if (username != null) {
launch {
user = context.presenter.getUser(username!!)
if (user != null) {
contact.setStatus(user!!.status)
}
holder.setContactStatus(contact)
}
}

val inviteButton: Button = holder.itemView.findViewById(R.id.invite_contact)
val dmButton: Button = holder.itemView.findViewById(R.id.chat_username)

inviteButton.setOnClickListener { view ->
run {
inviteButton.setText("INVITED")
val contact = holder.data!!.data

if (contact!!.isPhone()) {
context.presenter.inviteViaSMS(contact!!.getPhoneNumber()!!)
if (contact.isPhone()) {
context.presenter.inviteViaSMS(contact.getPhoneNumber()!!)
} else {
context.presenter.inviteViaEmail(contact!!.getEmailAddress()!!)
context.presenter.inviteViaEmail(contact.getEmailAddress()!!)
}
}
}

dmButton.setOnClickListener { view ->
run {
val contact = holder.data!!.data
context.presenter.openDirectMessageChatRoom(contact!!.getUsername().toString())
context.presenter.openDirectMessageChatRoom(contact.getUsername().toString())
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
package chat.rocket.android.contacts.adapter

import android.content.res.Resources
import android.graphics.drawable.Drawable
import android.view.View
import androidx.core.view.isGone
import androidx.core.view.isVisible
import chat.rocket.android.R
import chat.rocket.android.chatrooms.adapter.ViewHolder
import chat.rocket.android.contacts.models.Contact
import kotlinx.android.synthetic.main.item_contact.view.*

class ContactViewHolder(itemView: View) : ViewHolder<ContactItemHolder>(itemView) {

private val resources: Resources = itemView.resources
private val online: Drawable = resources.getDrawable(R.drawable.ic_status_online_12dp)
private val away: Drawable = resources.getDrawable(R.drawable.ic_status_away_12dp)
private val busy: Drawable = resources.getDrawable(R.drawable.ic_status_busy_12dp)
private val offline: Drawable = resources.getDrawable(R.drawable.ic_status_invisible_12dp)

override fun bindViews(data: ContactItemHolder) {
val contact = data.data
val contact: Contact = data.data
with(itemView) {
contact_image_avatar.setImageURI(contact.getAvatarUrl())
contact_name.text = contact.getName()
Expand All @@ -18,19 +28,37 @@ class ContactViewHolder(itemView: View) : ViewHolder<ContactItemHolder>(itemView
contact_detail.isVisible = true
invite_contact.isVisible = true
chat_username.isGone = true
contact_status.isGone = true

// EAR > maybe we want to show this detail in the view?
if (contact!!.isPhone()) {
contact_detail.text = contact!!.getPhoneNumber()
if (contact.isPhone()) {
contact_detail.text = contact.getPhoneNumber()
} else {
contact_detail.text = contact!!.getEmailAddress()
contact_detail.text = contact.getEmailAddress()
}

} else {
invite_contact.isGone = true
chat_username.isVisible = true
chat_username.text = "@"+contact!!.getUsername()
chat_username.text = "@${contact.getUsername()}"
contact_status.isVisible = true
}
}
}

fun setContactStatus(contact: Contact?) {
itemView.contact_status.setImageDrawable(getStatusDrawable(contact?.getStatus()))
}

private fun getStatusDrawable(status: String?): Drawable {
if (status == null) {
return offline
}
return when(status) {
"online" -> online
"away" -> away
"busy" -> busy
else -> offline
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class Contact() : Parcelable {
private var isPhone: Boolean = true
private var username: String? = null
private var avatarUrl: String? = null
private var status: String? = null

fun getUsername(): String? {
return username
Expand Down Expand Up @@ -69,6 +70,14 @@ class Contact() : Parcelable {
this.avatarUrl = url
}

fun getStatus(): String? {
return status
}

fun setStatus(status: String) {
this.status = status
}

constructor(parcel: Parcel) : this() {
this.name = parcel.readString()
this.phoneNumber = parcel.readString()
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/chat/rocket/android/db/UserDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ abstract class UserDao : BaseDao<UserEntity> {
@Query("SELECT * FROM users WHERE ID = :id")
abstract fun getUser(id:String): UserEntity?

@Query("SELECT * FROM users WHERE USERNAME = :username")
abstract fun getUserFromUsername(username:String): UserEntity?

@Transaction
open fun upsert(user: BaseUserEntity) {
internalUpsert(user)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.db.DatabaseManagerFactory
import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.db.model.ChatRoomEntity
import chat.rocket.android.db.model.UserEntity
import chat.rocket.android.dynamiclinks.DynamicLinksForFirebase
import chat.rocket.android.emoji.Emoji
import chat.rocket.android.emoji.EmojiRepository
Expand Down Expand Up @@ -120,6 +121,10 @@ class MainPresenter @Inject constructor(
}
}

fun getUser(username: String): UserEntity? {
return dbManager.userDao().getUserFromUsername(username)
}

private fun createDirectMessage(id: String) = launchUI(strategy) {
try {
val result = retryIO("createDirectMessage($id") {
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/res/layout/item_contact.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,26 @@
android:id="@+id/contact_image_avatar"
android:layout_width="40dp"
android:layout_height="40dp"
android:padding="1dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:roundedCornerRadius='@{shape.AVATAR_SHAPE_CIRCLE ? @dimen/circle_avatar_corner_radius : @dimen/square_avatar_corner_radius}'
tools:background="@drawable/widechat_circle_shadow" />

<ImageView
android:id="@+id/contact_status"
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_marginBottom="0dp"
android:layout_marginEnd="0dp"
android:background="@drawable/circle_background_white"
android:padding="1dp"
android:visibility="gone"
tools:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/contact_image_avatar" />

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
Expand Down
39 changes: 22 additions & 17 deletions app/src/main/res/layout/widechat_search_layout.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,22 @@
android:paddingEnd="8dp"
android:paddingStart="0dp">

<RelativeLayout
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/rl_image_avatar"
android:layout_width="48dp"
android:layout_height="48dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginEnd="24dp">
android:layout_marginRight="24dp">

<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/profile_image_avatar"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/widechat_circle_shadow"
android:foregroundGravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:roundedCornerRadius="3dp"
fresco:actualImageScaleType="centerCrop"
fresco:roundAsCircle="true"
Expand All @@ -29,18 +32,20 @@
fresco:roundingBorderWidth="2dp" />

<ImageView
android:id="@+id/text_online"
android:layout_width="12dp"
android:layout_height="12dp"
android:visibility="visible"
android:layout_alignRight="@+id/profile_image_avatar"
android:layout_alignBottom="@+id/profile_image_avatar"
android:src="@drawable/ic_status_online_12dp"
android:layout_marginBottom="8dp"
android:background="@drawable/circle_background_white" />
</RelativeLayout>
android:id="@+id/self_status"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginBottom="2dp"
android:layout_marginEnd="2dp"
android:background="@drawable/circle_background_white"
android:padding="1dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/profile_image_avatar" />

<androidx.appcompat.widget.SearchView
</androidx.constraintlayout.widget.ConstraintLayout>

<androidx.appcompat.widget.SearchView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="@+id/action_widechat_search"
Expand Down

0 comments on commit 16281ec

Please sign in to comment.