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

Merge pull request #833 from RocketChat/feature/login-with-email

[NEW] Login with email
parents 7c68c702 508b2d2f
...@@ -7,12 +7,14 @@ import chat.rocket.android.helper.NetworkHelper ...@@ -7,12 +7,14 @@ import chat.rocket.android.helper.NetworkHelper
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.* import chat.rocket.android.server.domain.*
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extensions.isEmailValid
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extensions.launchUI
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.RocketChatTwoFactorException import chat.rocket.common.RocketChatTwoFactorException
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
import chat.rocket.core.RocketChatClient import chat.rocket.core.RocketChatClient
import chat.rocket.core.internal.rest.login import chat.rocket.core.internal.rest.login
import chat.rocket.core.internal.rest.loginWithEmail
import chat.rocket.core.internal.rest.me import chat.rocket.core.internal.rest.me
import chat.rocket.core.internal.rest.registerPushToken import chat.rocket.core.internal.rest.registerPushToken
import javax.inject.Inject import javax.inject.Inject
...@@ -93,7 +95,12 @@ class LoginPresenter @Inject constructor(private val view: LoginView, ...@@ -93,7 +95,12 @@ class LoginPresenter @Inject constructor(private val view: LoginView,
view.showLoading() view.showLoading()
try { try {
val token = client.login(usernameOrEmail, password) val token = if (usernameOrEmail.isEmailValid()) {
client.loginWithEmail(usernameOrEmail, password)
} else {
client.login(usernameOrEmail, password)
}
val me = client.me() val me = client.me()
multiServerRepository.save( multiServerRepository.save(
server, server,
......
...@@ -10,14 +10,20 @@ import chat.rocket.android.util.extensions.inflate ...@@ -10,14 +10,20 @@ import chat.rocket.android.util.extensions.inflate
import kotlinx.android.synthetic.main.avatar.view.* import kotlinx.android.synthetic.main.avatar.view.*
import kotlinx.android.synthetic.main.item_member.view.* import kotlinx.android.synthetic.main.item_member.view.*
class MembersAdapter(private var dataSet: List<MemberViewModel>) : RecyclerView.Adapter<MembersAdapter.ViewHolder>() { class MembersAdapter(private val listener: (MemberViewModel) -> Unit) : RecyclerView.Adapter<MembersAdapter.ViewHolder>() {
private var dataSet: List<MemberViewModel> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MembersAdapter.ViewHolder = ViewHolder(parent.inflate(R.layout.item_member)) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MembersAdapter.ViewHolder = ViewHolder(parent.inflate(R.layout.item_member))
override fun onBindViewHolder(holder: MembersAdapter.ViewHolder, position: Int) = holder.bind(dataSet[position]) override fun onBindViewHolder(holder: MembersAdapter.ViewHolder, position: Int) = holder.bind(dataSet[position], listener)
override fun getItemCount(): Int = dataSet.size override fun getItemCount(): Int = dataSet.size
fun prependData(dataSet: List<MemberViewModel>) {
this.dataSet = dataSet
notifyItemRangeInserted(0, dataSet.size)
}
fun appendData(dataSet: List<MemberViewModel>) { fun appendData(dataSet: List<MemberViewModel>) {
val previousDataSetSize = this.dataSet.size val previousDataSetSize = this.dataSet.size
this.dataSet += dataSet this.dataSet += dataSet
...@@ -26,9 +32,11 @@ class MembersAdapter(private var dataSet: List<MemberViewModel>) : RecyclerView. ...@@ -26,9 +32,11 @@ class MembersAdapter(private var dataSet: List<MemberViewModel>) : RecyclerView.
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(memberViewModel: MemberViewModel) = with(itemView) { fun bind(memberViewModel: MemberViewModel, listener: (MemberViewModel) -> Unit) = with(itemView) {
image_avatar.setImageURI(memberViewModel.avatarUri) image_avatar.setImageURI(memberViewModel.avatarUri)
text_member.content = memberViewModel.memberName text_member.content = memberViewModel.displayName
setOnClickListener { listener(memberViewModel) }
} }
} }
} }
\ No newline at end of file
package chat.rocket.android.members.ui package chat.rocket.android.members.ui
import android.os.Bundle import android.os.Bundle
import android.support.design.widget.BottomSheetBehavior
import android.support.v4.app.Fragment import android.support.v4.app.Fragment
import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.LinearLayoutManager
...@@ -15,12 +16,11 @@ import chat.rocket.android.members.adapter.MembersAdapter ...@@ -15,12 +16,11 @@ import chat.rocket.android.members.adapter.MembersAdapter
import chat.rocket.android.members.presentation.MembersPresenter import chat.rocket.android.members.presentation.MembersPresenter
import chat.rocket.android.members.presentation.MembersView import chat.rocket.android.members.presentation.MembersView
import chat.rocket.android.members.viewmodel.MemberViewModel import chat.rocket.android.members.viewmodel.MemberViewModel
import chat.rocket.android.util.extensions.inflate import chat.rocket.android.util.extensions.*
import chat.rocket.android.util.extensions.setVisible
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.widget.DividerItemDecoration import chat.rocket.android.widget.DividerItemDecoration
import dagger.android.support.AndroidSupportInjection import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_members.* import kotlinx.android.synthetic.main.fragment_members.*
import kotlinx.android.synthetic.main.member_bottom_sheet.*
import javax.inject.Inject import javax.inject.Inject
fun newInstance(chatRoomId: String, chatRoomType: String): Fragment { fun newInstance(chatRoomId: String, chatRoomType: String): Fragment {
...@@ -37,7 +37,9 @@ private const val BUNDLE_CHAT_ROOM_TYPE = "chat_room_type" ...@@ -37,7 +37,9 @@ private const val BUNDLE_CHAT_ROOM_TYPE = "chat_room_type"
class MembersFragment : Fragment(), MembersView { class MembersFragment : Fragment(), MembersView {
@Inject lateinit var presenter: MembersPresenter @Inject lateinit var presenter: MembersPresenter
private lateinit var adapter: MembersAdapter private val adapter: MembersAdapter = MembersAdapter { memberViewModel -> showMemberDetails(memberViewModel) }
private val linearLayoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
private val bottomSheetBehavior by lazy { BottomSheetBehavior.from(member_bottom_sheet) }
private lateinit var chatRoomId: String private lateinit var chatRoomId: String
private lateinit var chatRoomType: String private lateinit var chatRoomType: String
...@@ -60,18 +62,16 @@ class MembersFragment : Fragment(), MembersView { ...@@ -60,18 +62,16 @@ class MembersFragment : Fragment(), MembersView {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
(activity as AppCompatActivity).supportActionBar?.title = "" (activity as AppCompatActivity).supportActionBar?.title = ""
setupRecyclerView()
presenter.loadChatRoomsMembers(chatRoomId, chatRoomType) presenter.loadChatRoomsMembers(chatRoomId, chatRoomType)
} }
override fun showMembers(dataSet: List<MemberViewModel>, total: Long) { override fun showMembers(dataSet: List<MemberViewModel>, total: Long) {
activity?.apply { activity?.apply {
setupToolbar(total) setupToolbar(total)
if (recycler_view.adapter == null) { if (adapter.itemCount == 0) {
adapter = MembersAdapter(dataSet) adapter.prependData(dataSet)
recycler_view.adapter = adapter
val linearLayoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
recycler_view.layoutManager = linearLayoutManager
recycler_view.addItemDecoration(DividerItemDecoration(this))
if (dataSet.size >= 60) { if (dataSet.size >= 60) {
recycler_view.addOnScrollListener(object : EndlessRecyclerViewScrollListener(linearLayoutManager) { recycler_view.addOnScrollListener(object : EndlessRecyclerViewScrollListener(linearLayoutManager) {
override fun onLoadMore(page: Int, totalItemsCount: Int, recyclerView: RecyclerView?) { override fun onLoadMore(page: Int, totalItemsCount: Int, recyclerView: RecyclerView?) {
...@@ -95,6 +95,32 @@ class MembersFragment : Fragment(), MembersView { ...@@ -95,6 +95,32 @@ class MembersFragment : Fragment(), MembersView {
override fun showGenericErrorMessage() = showMessage(getString(R.string.msg_generic_error)) override fun showGenericErrorMessage() = showMessage(getString(R.string.msg_generic_error))
private fun setupRecyclerView() {
activity?.apply {
recycler_view.layoutManager = linearLayoutManager
recycler_view.addItemDecoration(DividerItemDecoration(this))
recycler_view.adapter = adapter
}
}
private fun showMemberDetails(memberViewModel: MemberViewModel) {
image_bottom_sheet_avatar.setImageURI(memberViewModel.avatarUri)
text_bottom_sheet_member_name.content = memberViewModel.realName
text_bottom_sheet_member_username.content = "@${memberViewModel.username}"
val memberEmail = memberViewModel.email
if (memberEmail != null) {
text_member_email_address.textContent = memberEmail
} else {
text_email_address.setVisible(false)
text_member_email_address.setVisible(false)
}
text_member_utc.content = memberViewModel.utcOffset.toString()
bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
}
private fun setupToolbar(totalMembers: Long) { private fun setupToolbar(totalMembers: Long) {
(activity as ChatRoomActivity).setupToolbarTitle(getString(R.string.title_members, totalMembers)) (activity as ChatRoomActivity).setupToolbarTitle(getString(R.string.title_members, totalMembers))
} }
......
...@@ -7,11 +7,19 @@ import chat.rocket.core.model.Value ...@@ -7,11 +7,19 @@ import chat.rocket.core.model.Value
class MemberViewModel(private val member: User, private val settings: Map<String, Value<Any>>, private val baseUrl: String?) { class MemberViewModel(private val member: User, private val settings: Map<String, Value<Any>>, private val baseUrl: String?) {
val avatarUri: String? val avatarUri: String?
val memberName: CharSequence val displayName: String
val realName: String?
val username: String?
val email: String?
val utcOffset: Float?
init { init {
avatarUri = getUserAvatar() avatarUri = getUserAvatar()
memberName = getUserName() displayName = getUserDisplayName()
realName = getUserRealName()
username = getUserUsername()
email = getUserEmail()
utcOffset = getUserUtcOffset()
} }
private fun getUserAvatar(): String? { private fun getUserAvatar(): String? {
...@@ -21,10 +29,18 @@ class MemberViewModel(private val member: User, private val settings: Map<String ...@@ -21,10 +29,18 @@ class MemberViewModel(private val member: User, private val settings: Map<String
} }
} }
private fun getUserName(): CharSequence { private fun getUserDisplayName(): String {
val username = member.username val username = member.username
val realName = member.name val realName = member.name
val senderName = if (settings.useRealName()) realName else username val senderName = if (settings.useRealName()) realName else username
return senderName ?: username.toString() return senderName ?: username.toString()
} }
private fun getUserRealName(): String? = member.name
private fun getUserUsername(): String? = member.username
private fun getUserEmail(): String? = member.emails?.get(0)?.address
private fun getUserUtcOffset(): Float? = member.utcOffset
} }
\ No newline at end of file
...@@ -3,6 +3,7 @@ package chat.rocket.android.util.extensions ...@@ -3,6 +3,7 @@ package chat.rocket.android.util.extensions
import android.text.Spannable import android.text.Spannable
import android.text.Spanned import android.text.Spanned
import android.text.TextUtils import android.text.TextUtils
import android.util.Patterns
import android.widget.EditText import android.widget.EditText
import android.widget.TextView import android.widget.TextView
import chat.rocket.android.widget.emoji.EmojiParser import chat.rocket.android.widget.emoji.EmojiParser
...@@ -31,6 +32,8 @@ fun EditText.erase() { ...@@ -31,6 +32,8 @@ fun EditText.erase() {
} }
} }
fun String.isEmailValid(): Boolean = Patterns.EMAIL_ADDRESS.matcher(this).matches()
var TextView.textContent: String var TextView.textContent: String
get() = text.toString() get() = text.toString()
set(value) { set(value) {
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
...@@ -11,12 +11,15 @@ ...@@ -11,12 +11,15 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent" />
<include layout="@layout/member_bottom_sheet" />
<com.wang.avi.AVLoadingIndicatorView <com.wang.avi.AVLoadingIndicatorView
android:id="@+id/view_loading" android:id="@+id/view_loading"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_centerInParent="true" android:layout_centerInParent="true"
app:indicatorColor="@color/black" app:indicatorColor="@color/black"
app:indicatorName="BallPulseIndicator" /> app:indicatorName="BallPulseIndicator" />
</RelativeLayout> </android.support.design.widget.CoordinatorLayout>
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/member_bottom_sheet"
android:layout_width="match_parent"
android:layout_height="340dp"
app:behavior_hideable="true"
app:behavior_peekHeight="0dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/image_bottom_sheet_avatar"
android:layout_width="match_parent"
android:layout_height="200dp" />
<TextView
android:id="@+id/text_bottom_sheet_member_name"
style="@style/TextAppearance.AppCompat.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:textColor="@color/white"
app:layout_constraintBottom_toTopOf="@+id/text_bottom_sheet_member_username"
app:layout_constraintLeft_toLeftOf="parent"
tools:text="Ronald Perkins" />
<TextView
android:id="@+id/text_bottom_sheet_member_username"
style="@style/Sender.Name.TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginStart="16dp"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="@+id/image_bottom_sheet_avatar"
app:layout_constraintLeft_toLeftOf="parent"
tools:text="\@ronaldPerkins" />
<TextView
android:id="@+id/text_email_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="@string/msg_email_address"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/image_bottom_sheet_avatar" />
<TextView
android:id="@+id/text_member_email_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="10dp"
android:textColor="@color/colorPrimaryText"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_email_address"
tools:text="ronald@perkins.com" />
<TextView
android:id="@+id/text_utc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="@string/msg_utc_offset"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_member_email_address" />
<TextView
android:id="@+id/text_member_utc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="10dp"
android:textColor="@color/colorPrimaryText"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_utc"
tools:text="+01:00" />
</android.support.constraint.ConstraintLayout>
\ No newline at end of file
...@@ -51,6 +51,8 @@ ...@@ -51,6 +51,8 @@
<string name="msg_content_description_show_attachment_options">Mostrar opções de anexo</string> <string name="msg_content_description_show_attachment_options">Mostrar opções de anexo</string>
<string name="msg_you">Você</string> <string name="msg_you">Você</string>
<string name="msg_unknown">Desconhecido</string> <string name="msg_unknown">Desconhecido</string>
<string name="msg_email_address">Endereço de e-mail</string>
<string name="msg_utc_offset">Deslocamento de UTC</string>
<!-- System messages --> <!-- System messages -->
<string name="message_room_name_changed">Nome da sala alterado para: %1$s por %2$s</string> <string name="message_room_name_changed">Nome da sala alterado para: %1$s por %2$s</string>
......
...@@ -53,6 +53,8 @@ ...@@ -53,6 +53,8 @@
<string name="msg_content_description_show_attachment_options">Show attachment options</string> <string name="msg_content_description_show_attachment_options">Show attachment options</string>
<string name="msg_you">You</string> <string name="msg_you">You</string>
<string name="msg_unknown">Unknown</string> <string name="msg_unknown">Unknown</string>
<string name="msg_email_address">E-mail address</string>
<string name="msg_utc_offset">UTC offset</string>
<!-- System messages --> <!-- System messages -->
<string name="message_room_name_changed">Room name changed to: %1$s by %2$s</string> <string name="message_room_name_changed">Room name changed to: %1$s by %2$s</string>
......
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