feat(friends): Interactions, taps, reload

parent 2e335df3
...@@ -2,18 +2,23 @@ package fr.plnech.dunbar ...@@ -2,18 +2,23 @@ package fr.plnech.dunbar
import android.graphics.Bitmap import android.graphics.Bitmap
import android.provider.ContactsContract.Contacts import android.provider.ContactsContract.Contacts
import java.util.*
data class Friend(val map: MutableMap<String, String?>, val photo: Bitmap?) { data class Friend(val map: MutableMap<String, String?>, val photo: Bitmap?) {
override fun toString(): String = "$name" override fun toString(): String = "$name"
fun mapString(): String = map.entries.filter { !it.value.isNullOrEmpty() }.toString()
val name: String? val name: String?
get() = map[Contacts.DISPLAY_NAME] get() = map[Contacts.DISPLAY_NAME]
val id: Int val id: Int
get() = map[Contacts._ID]!!.toInt() get() = map[Contacts._ID]!!.toInt()
val lastTime: String? val lastTimeStamp = map[Contacts.LAST_TIME_CONTACTED]!!.toLong()
get() = map[Contacts.LAST_TIME_CONTACTED]
val lastDate: Date?
get() = if (lastTimeStamp > 0) Date(lastTimeStamp) else null
val timesContacted: Int val timesContacted: Int
get() = map[Contacts.TIMES_CONTACTED]?.toInt() ?: 0 get() = map[Contacts.TIMES_CONTACTED]?.toInt() ?: 0
......
package fr.plnech.dunbar
import android.text.format.DateUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.contact.view.*
class FriendsAdapter(
private var friends: List<Friend> = mutableListOf()
) : RecyclerView.Adapter<FriendsViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FriendsViewHolder =
FriendsViewHolder(LayoutInflater.from(parent.context).inflate(viewType, parent, false))
override fun getItemCount(): Int = friends.size
override fun getItemViewType(position: Int): Int = R.layout.contact
override fun onBindViewHolder(holder: FriendsViewHolder, position: Int): Unit =
holder.bind(friends[position])
}
class FriendsViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
private val name = view.contactName
private val data = view.contactData
private val pic = view.pic
fun bind(friend: Friend) {
name.text = friend.name
data.text = buildString {
if (friend.lastDate != null ) {
append(friend.timesContacted)
append(" interactions, last ")
append(DateUtils.getRelativeTimeSpanString(friend.lastTimeStamp))
} else {
append("Never interacted")
}
}
view.setOnClickListener {
Toast.makeText(view.context, friend.mapString(), Toast.LENGTH_LONG).show()
}
}
}
...@@ -8,10 +8,9 @@ import android.provider.ContactsContract ...@@ -8,10 +8,9 @@ import android.provider.ContactsContract
import android.util.Log import android.util.Log
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.widget.ArrayAdapter
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.snackbar.Snackbar import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.content_main.* import kotlinx.android.synthetic.main.content_main.*
import java.io.IOException import java.io.IOException
...@@ -27,11 +26,10 @@ class MainActivity : AppCompatActivity() { ...@@ -27,11 +26,10 @@ class MainActivity : AppCompatActivity() {
setSupportActionBar(toolbar) setSupportActionBar(toolbar)
fab.setOnClickListener { view -> fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) reloadFriends()
.setAction("Action", null).show()
} }
fetchFriends() reloadFriends()
} }
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
...@@ -50,8 +48,15 @@ class MainActivity : AppCompatActivity() { ...@@ -50,8 +48,15 @@ class MainActivity : AppCompatActivity() {
} }
} }
fun fetchFriends() { private fun reloadFriends() {
Toast.makeText(this@MainActivity, "Fetching friends...", Toast.LENGTH_SHORT).show() fetchFriends()
displayFriends()
Toast.makeText(this, "Friends reloaded.", Toast.LENGTH_SHORT).show()
}
private fun fetchFriends() {
val newFriends = mutableListOf<Friend>()
contentResolver.query( contentResolver.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI, ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
...@@ -62,41 +67,43 @@ class MainActivity : AppCompatActivity() { ...@@ -62,41 +67,43 @@ class MainActivity : AppCompatActivity() {
)?.let { )?.let {
while (it.moveToNext()) { while (it.moveToNext()) {
mutableMapOf<String, String?>().also { map -> mutableMapOf<String, String?>().also { map ->
val indexId = it.getColumnIndex(ContactsContract.Contacts._ID)
val indexID = it.getColumnIndex(ContactsContract.Contacts._ID) val id = it.getLong(indexId)
val id = it.getLong(indexID)
val photo: Bitmap? = getPhoto(id) val photo: Bitmap? = getPhoto(id)
it.columnNames.forEach { name -> it.columnNames.forEach { name ->
val index = it.getColumnIndex(name) val index = it.getColumnIndex(name)
map[name] = it.getString(index) map[name] = it.getString(index)
} }
friends.add(Friend(map, photo)) newFriends.add(Friend(map, photo))
} }
} }
it.close()
val adapter = ArrayAdapter<Friend>( friends.clear()
this, R.layout.contact, R.id.name, friends.addAll(newFriends)
friends }
)
friendsList.adapter = adapter
friendsList.setOnItemClickListener { parent, view, position, id ->
val contact: String = adapter.getItem(position)?.toString() ?: "NONE"
// Snackbar.make(friendsList, contact, Snackbar.LENGTH_INDEFINITE).show()
Toast.makeText(this, contact, Toast.LENGTH_LONG).show()
}
val nbFriends = adapter.count friends.sortByDescending { it.timesContacted }
welcomeTitle.text = "$nbFriends ${"friend".plural(nbFriends)} on Dunbar" }
Toast.makeText(this@MainActivity, "$nbFriends ", Toast.LENGTH_LONG).show() private fun displayFriends() {
val adapter = FriendsAdapter(friends)
it.close() friendsList.layoutManager = LinearLayoutManager(this)
} friendsList.setHasFixedSize(true)
friendsList.adapter = adapter
// friendsList.setOnItemClickListener { parent, view, position, id ->
// val contact: String = adapter.getItem(position)?.toString() ?: "NONE"
//
// Snackbar.make(friendsList, contact, Snackbar.LENGTH_INDEFINITE).show()
// Toast.makeText(this, contact, Toast.LENGTH_LONG).show()
// }
val nbFriends = adapter.itemCount
welcomeTitle.text = "$nbFriends ${"friend".plural(nbFriends)} on Dunbar"
Toast.makeText(this@MainActivity, "$nbFriends ", Toast.LENGTH_LONG).show()
} }
private fun getPhoto(id: Long): Bitmap? { private fun getPhoto(id: Long): Bitmap? {
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
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"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:elevation="5dp"> android:elevation="5dp">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
...@@ -24,12 +24,12 @@ ...@@ -24,12 +24,12 @@
android:elevation="2dp" android:elevation="2dp"
android:src="@drawable/user" android:src="@drawable/user"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toLeftOf="@id/name" app:layout_constraintRight_toLeftOf="@id/contactName"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<TextView <TextView
android:id="@+id/name" android:id="@+id/contactName"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:focusable="false" android:focusable="false"
...@@ -38,15 +38,15 @@ ...@@ -38,15 +38,15 @@
android:gravity="end" android:gravity="end"
android:maxLines="2" android:maxLines="2"
android:textAppearance="@style/TextAppearance.AppCompat.Title" android:textAppearance="@style/TextAppearance.AppCompat.Title"
app:layout_constraintBottom_toTopOf="@id/metadata" app:layout_constraintBottom_toTopOf="@id/contactData"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toRightOf="@id/pic" app:layout_constraintLeft_toRightOf="@id/pic"
app:layout_constraintRight_toLeftOf="@id/name" app:layout_constraintRight_toLeftOf="@id/contactName"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/full_names" /> tools:text="@tools:sample/full_names" />
<TextView <TextView
android:id="@+id/metadata" android:id="@+id/contactData"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="15dp" android:layout_marginBottom="15dp"
...@@ -58,8 +58,8 @@ ...@@ -58,8 +58,8 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toRightOf="@id/pic" app:layout_constraintLeft_toRightOf="@id/pic"
app:layout_constraintRight_toLeftOf="@id/name" app:layout_constraintRight_toLeftOf="@id/contactName"
app:layout_constraintTop_toBottomOf="@id/name" app:layout_constraintTop_toBottomOf="@id/contactName"
tools:text="@tools:sample/full_names" /> tools:text="@tools:sample/full_names" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
......
...@@ -10,17 +10,19 @@ ...@@ -10,17 +10,19 @@
<TextView <TextView
android:id="@+id/welcomeTitle" android:id="@+id/welcomeTitle"
android:layout_marginTop="50dp" android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:text="N friends on Dunbar"
android:textSize="24sp" android:textSize="24sp"
app:layout_constraintBottom_toTopOf="@id/friendsList" app:layout_constraintBottom_toTopOf="@id/friendsList"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
tools:text="N friends on Dunbar" />
<ListView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/friendsList" android:id="@+id/friendsList"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
......
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