Skip to content
This repository has been archived by the owner on Jun 7, 2020. It is now read-only.

[NEW] Add FAB, Show list of contacts, Invite Contacts via Email / Phone #1853

Open
wants to merge 19 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />

<application
android:name=".app.RocketChatApplication"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,13 @@ import chat.rocket.android.chatrooms.viewmodel.ChatRoomsViewModel
import chat.rocket.android.chatrooms.viewmodel.ChatRoomsViewModelFactory
import chat.rocket.android.chatrooms.viewmodel.LoadingState
import chat.rocket.android.chatrooms.viewmodel.Query
import chat.rocket.android.contacts.ContactsFragment
import chat.rocket.android.helper.ChatRoomsSortOrder
import chat.rocket.android.helper.Constants
import chat.rocket.android.helper.SharedPreferenceHelper
import chat.rocket.android.main.ui.MainActivity
import chat.rocket.android.util.extension.onQueryTextListener
import chat.rocket.android.util.extensions.fadeIn
import chat.rocket.android.util.extensions.fadeOut
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.ui
import chat.rocket.android.util.extensions.*
import chat.rocket.android.widget.DividerItemDecoration
import chat.rocket.core.internal.realtime.socket.model.State
import dagger.android.support.AndroidSupportInjection
Expand Down Expand Up @@ -109,6 +107,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
subscribeUi()

setupToolbar()
setupFab()

analyticsManager.logScreenView(ScreenViewEvent.ChatRooms)
}
Expand Down Expand Up @@ -180,13 +179,15 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
// to recreate the entire menu...
viewModel.showLastMessage = true
activity?.invalidateOptionsMenu()
create_new_channel_fab.isVisible = true
queryChatRoomsByName(null)
return true
}

override fun onMenuItemActionExpand(item: MenuItem): Boolean {
viewModel.showLastMessage = false
sortView?.isVisible = false
create_new_channel_fab.isVisible = false
return true
}
}
Expand Down Expand Up @@ -344,6 +345,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {

private fun setupToolbar() {
(activity as AppCompatActivity?)?.supportActionBar?.title = getString(R.string.title_chats)
(activity as MainActivity).setupNavigationView()
}

private fun queryChatRoomsByName(name: String?): Boolean {
Expand All @@ -354,4 +356,14 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
}
return true
}

private fun setupFab() {
create_new_channel_fab.setOnClickListener { view ->
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);
transaction?.replace(this.id, contactsFragment, "contactsFragment");
transaction?.addToBackStack(null)?.commit();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package chat.rocket.android.contacts

import android.Manifest
import android.app.Activity
import android.content.pm.PackageManager
import android.os.Bundle
import android.provider.ContactsContract
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R
import chat.rocket.android.contacts.models.Contact
import chat.rocket.android.main.ui.MainActivity
import timber.log.Timber
import java.util.ArrayList
import kotlin.collections.HashMap


/**
* Load a list of contacts in a recycler view
*/
class ContactListFragment : Fragment() {
/**
* The list of contacts to load in the recycler view
*/
private var contactArrayList: ArrayList<Contact?>? = null

/**
* The mapping of contacts with their registration status
*/
private var contactHashMap: HashMap<String, String> = HashMap()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val bundle = arguments
if (bundle != null) {
contactArrayList = bundle.getParcelableArrayList("CONTACT_ARRAY_LIST")
contactHashMap= bundle.getSerializable("CONTACT_HASH_MAP") as HashMap<String, String>
}

}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_contacts, container, false)
val context = view.context

val recyclerView = view.findViewById(R.id.recycler_view) as RecyclerView
val emptyTextView = view.findViewById(R.id.text_no_data_to_display) as TextView

if (contactArrayList!!.size == 0) {
emptyTextView.visibility = View.VISIBLE
recyclerView.visibility = View.GONE
} else {
emptyTextView.visibility = View.GONE
recyclerView.visibility = View.VISIBLE

recyclerView.setHasFixedSize(true)
recyclerView.layoutManager = LinearLayoutManager(context)
recyclerView.adapter = ContactRecyclerViewAdapter(this.activity as MainActivity, contactArrayList!!, contactHashMap)
}

return view
}

companion object {

/**
* Create a new ContactList fragment that displays the given list of contacts
*
* @param contactArrayList the list of contacts to load in the recycler view
* @param contactHashMap the mapping of contacts with their registration status
* @return the newly created ContactList fragment
*/
fun newInstance(
contactArrayList: ArrayList<Contact>,
contactHashMap: HashMap<String, String>
): ContactListFragment {
val contactListFragment = ContactListFragment()

val arguments = Bundle()
arguments.putParcelableArrayList("CONTACT_ARRAY_LIST", contactArrayList)
arguments.putSerializable("CONTACT_HASH_MAP", contactHashMap)

contactListFragment.arguments = arguments

return contactListFragment
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package chat.rocket.android.contacts

import android.content.Context
import timber.log.Timber
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R
import chat.rocket.android.contacts.models.Contact
import chat.rocket.android.main.ui.MainActivity
import java.util.*
import kotlin.collections.HashMap
import chat.rocket.android.util.extensions.showToast

class ContactRecyclerViewAdapter(
private val context: MainActivity,
private val contactArrayList: ArrayList<Contact?>,
private val contactHashMap: HashMap<String, String>
) : RecyclerView.Adapter<ContactRecyclerViewAdapter.ViewHolder>() {

override fun getItemCount(): Int {
return contactArrayList.size
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater
.from(parent.context)
.inflate(R.layout.item_contact, parent, false)
return ViewHolder(view)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.contact = contactArrayList[position]
holder.status = contactHashMap.get(holder.contact!!.getPhoneNumber())
try {
holder.contactName.text = holder.contact!!.getName()
if (holder.contact!!.isPhone()) {
holder.contactDetail.text = holder.contact!!.getPhoneNumber()
} else {
holder.contactDetail.text = holder.contact!!.getEmailAddress()
}
} catch (exception: NullPointerException) {
Timber.e("Failed to send resolution. Exception is: $exception")
}

}

inner class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
var contact: Contact? = null
var status: String? = null

var contactName: TextView
var contactDetail: TextView
var inviteButton: Button

init {
this.contactName = view.findViewById(R.id.contact_name) as TextView
this.contactDetail = view.findViewById(R.id.contact_detail) as TextView
this.inviteButton = view.findViewById(R.id.invite_contact) as Button

this.inviteButton.setOnClickListener { view ->
run {
// Make API call using context.presenter
if(contact!!.isPhone()){
context.presenter.inviteViaSMS(contact!!.getPhoneNumber()!!);
}else{
context.presenter.inviteViaEmail(contact!!.getEmailAddress()!!);
}
}
}
}
}
}
Loading