lets use the new Conversation model at the main screen

This commit is contained in:
tibbi 2020-04-11 19:41:48 +02:00
parent 882b75324d
commit 21dd815f2a
8 changed files with 92 additions and 73 deletions

View File

@ -15,14 +15,13 @@ import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.FAQItem import com.simplemobiletools.commons.models.FAQItem
import com.simplemobiletools.smsmessenger.BuildConfig import com.simplemobiletools.smsmessenger.BuildConfig
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.adapters.ThreadsAdapter import com.simplemobiletools.smsmessenger.adapters.ConversationsAdapter
import com.simplemobiletools.smsmessenger.extensions.config import com.simplemobiletools.smsmessenger.extensions.config
import com.simplemobiletools.smsmessenger.extensions.getMessages import com.simplemobiletools.smsmessenger.extensions.getConversations
import com.simplemobiletools.smsmessenger.extensions.getThreadTitle
import com.simplemobiletools.smsmessenger.helpers.THREAD_ID import com.simplemobiletools.smsmessenger.helpers.THREAD_ID
import com.simplemobiletools.smsmessenger.helpers.THREAD_TITLE import com.simplemobiletools.smsmessenger.helpers.THREAD_TITLE
import com.simplemobiletools.smsmessenger.models.Conversation
import com.simplemobiletools.smsmessenger.models.Events import com.simplemobiletools.smsmessenger.models.Events
import com.simplemobiletools.smsmessenger.models.Message
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.Subscribe
@ -62,7 +61,7 @@ class MainActivity : SimpleActivity() {
} }
} }
messages_fab.setOnClickListener { conversations_fab.setOnClickListener {
Intent(this, NewMessageActivity::class.java).apply { Intent(this, NewMessageActivity::class.java).apply {
startActivity(this) startActivity(this)
} }
@ -72,7 +71,7 @@ class MainActivity : SimpleActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
if (storedTextColor != config.textColor) { if (storedTextColor != config.textColor) {
(messages_list.adapter as? ThreadsAdapter)?.updateTextColor(config.textColor) (conversations_list.adapter as? ConversationsAdapter)?.updateTextColor(config.textColor)
} }
updateTextColors(main_coordinator) updateTextColors(main_coordinator)
@ -135,16 +134,16 @@ class MainActivity : SimpleActivity() {
private fun initMessenger() { private fun initMessenger() {
storeStateVariables() storeStateVariables()
ensureBackgroundThread { ensureBackgroundThread {
val messages = getMessages() val conversations = getConversations()
runOnUiThread { runOnUiThread {
ThreadsAdapter(this, messages, messages_list, messages_fastscroller) { ConversationsAdapter(this, conversations, conversations_list, conversations_fastscroller) {
Intent(this, ThreadActivity::class.java).apply { Intent(this, ThreadActivity::class.java).apply {
putExtra(THREAD_ID, (it as Message).thread) putExtra(THREAD_ID, (it as Conversation).id)
putExtra(THREAD_TITLE, it.participants.getThreadTitle()) putExtra(THREAD_TITLE, it.title)
startActivity(this) startActivity(this)
} }
}.apply { }.apply {
messages_list.adapter = this conversations_list.adapter = this
} }
} }
} }

View File

@ -190,7 +190,7 @@ class ThreadActivity : SimpleActivity() {
private fun askConfirmDelete() { private fun askConfirmDelete() {
ConfirmationDialog(this, getString(R.string.delete_whole_conversation_confirmation)) { ConfirmationDialog(this, getString(R.string.delete_whole_conversation_confirmation)) {
deleteThread(threadId) deleteConversation(threadId)
refreshMessages() refreshMessages()
finish() finish()
} }

View File

@ -14,15 +14,14 @@ import com.simplemobiletools.commons.views.FastScroller
import com.simplemobiletools.commons.views.MyRecyclerView import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.activities.SimpleActivity import com.simplemobiletools.smsmessenger.activities.SimpleActivity
import com.simplemobiletools.smsmessenger.extensions.deleteThread import com.simplemobiletools.smsmessenger.extensions.deleteConversation
import com.simplemobiletools.smsmessenger.extensions.getThreadTitle
import com.simplemobiletools.smsmessenger.extensions.loadImage import com.simplemobiletools.smsmessenger.extensions.loadImage
import com.simplemobiletools.smsmessenger.helpers.refreshMessages import com.simplemobiletools.smsmessenger.helpers.refreshMessages
import com.simplemobiletools.smsmessenger.models.Message import com.simplemobiletools.smsmessenger.models.Conversation
import kotlinx.android.synthetic.main.item_thread.view.* import kotlinx.android.synthetic.main.item_conversation.view.*
class ThreadsAdapter( class ConversationsAdapter(
activity: SimpleActivity, var threads: ArrayList<Message>, activity: SimpleActivity, var conversations: ArrayList<Conversation>,
recyclerView: MyRecyclerView, recyclerView: MyRecyclerView,
fastScroller: FastScroller, fastScroller: FastScroller,
itemClick: (Any) -> Unit itemClick: (Any) -> Unit
@ -32,7 +31,7 @@ class ThreadsAdapter(
setupDragListener(true) setupDragListener(true)
} }
override fun getActionMenuId() = R.menu.cab_threads override fun getActionMenuId() = R.menu.cab_conversations
override fun prepareActionMode(menu: Menu) {} override fun prepareActionMode(menu: Menu) {}
@ -47,29 +46,29 @@ class ThreadsAdapter(
} }
} }
override fun getSelectableItemCount() = threads.size override fun getSelectableItemCount() = conversations.size
override fun getIsItemSelectable(position: Int) = true override fun getIsItemSelectable(position: Int) = true
override fun getItemSelectionKey(position: Int) = threads.getOrNull(position)?.id override fun getItemSelectionKey(position: Int) = conversations.getOrNull(position)?.id
override fun getItemKeyPosition(key: Int) = threads.indexOfFirst { it.id == key } override fun getItemKeyPosition(key: Int) = conversations.indexOfFirst { it.id == key }
override fun onActionModeCreated() {} override fun onActionModeCreated() {}
override fun onActionModeDestroyed() {} override fun onActionModeDestroyed() {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_thread, parent) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_conversation, parent)
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val message = threads[position] val conversation = conversations[position]
holder.bindView(message, true, true) { itemView, layoutPosition -> holder.bindView(conversation, true, true) { itemView, layoutPosition ->
setupView(itemView, message) setupView(itemView, conversation)
} }
bindViewHolder(holder) bindViewHolder(holder)
} }
override fun getItemCount() = threads.size override fun getItemCount() = conversations.size
private fun askConfirmDelete() { private fun askConfirmDelete() {
val itemsCnt = selectedKeys.size val itemsCnt = selectedKeys.size
@ -80,25 +79,25 @@ class ThreadsAdapter(
ConfirmationDialog(activity, question) { ConfirmationDialog(activity, question) {
ensureBackgroundThread { ensureBackgroundThread {
deleteThreads() deleteConversations()
} }
} }
} }
private fun deleteThreads() { private fun deleteConversations() {
if (selectedKeys.isEmpty()) { if (selectedKeys.isEmpty()) {
return return
} }
val threadsToRemove = threads.filter { selectedKeys.contains(it.id) } as ArrayList<Message> val conversationsToRemove = conversations.filter { selectedKeys.contains(it.id) } as ArrayList<Conversation>
val positions = getSelectedItemPositions() val positions = getSelectedItemPositions()
threadsToRemove.forEach { conversationsToRemove.forEach {
activity.deleteThread(it.thread) activity.deleteConversation(it.id)
} }
threads.removeAll(threadsToRemove) conversations.removeAll(conversationsToRemove)
activity.runOnUiThread { activity.runOnUiThread {
if (threadsToRemove.isEmpty()) { if (conversationsToRemove.isEmpty()) {
refreshMessages() refreshMessages()
finishActMode() finishActMode()
} else { } else {
@ -110,34 +109,33 @@ class ThreadsAdapter(
override fun onViewRecycled(holder: ViewHolder) { override fun onViewRecycled(holder: ViewHolder) {
super.onViewRecycled(holder) super.onViewRecycled(holder)
if (!activity.isDestroyed && !activity.isFinishing) { if (!activity.isDestroyed && !activity.isFinishing) {
Glide.with(activity).clear(holder.itemView.thread_image) Glide.with(activity).clear(holder.itemView.conversation_image)
} }
} }
private fun setupView(view: View, message: Message) { private fun setupView(view: View, conversation: Conversation) {
view.apply { view.apply {
thread_frame.isSelected = selectedKeys.contains(message.id) conversation_frame.isSelected = selectedKeys.contains(conversation.id)
thread_address.text = message.participants.getThreadTitle() conversation_address.text = conversation.title
thread_body_short.text = message.body conversation_body_short.text = conversation.snippet
thread_date.text = message.date.formatDateOrTime(context, true) conversation_date.text = conversation.date.formatDateOrTime(context, true)
if (message.read) { if (conversation.read) {
thread_address.setTypeface(null, Typeface.NORMAL) conversation_address.setTypeface(null, Typeface.NORMAL)
thread_body_short.setTypeface(null, Typeface.NORMAL) conversation_body_short.setTypeface(null, Typeface.NORMAL)
thread_body_short.alpha = 0.7f conversation_body_short.alpha = 0.7f
} else { } else {
thread_address.setTypeface(null, Typeface.BOLD) conversation_address.setTypeface(null, Typeface.BOLD)
thread_body_short.setTypeface(null, Typeface.BOLD) conversation_body_short.setTypeface(null, Typeface.BOLD)
thread_body_short.alpha = 1f conversation_body_short.alpha = 1f
} }
arrayListOf<TextView>(thread_address, thread_body_short, thread_date).forEach { arrayListOf<TextView>(conversation_address, conversation_body_short, conversation_date).forEach {
it.setTextColor(textColor) it.setTextColor(textColor)
} }
val participant = message.participants.first() context.loadImage(conversation.photoUri, conversation_image, conversation.title)
context.loadImage(participant.photoUri, thread_image, participant.name)
} }
} }
} }

View File

@ -154,8 +154,10 @@ fun Context.getConversations(): ArrayList<Conversation> {
Threads.RECIPIENT_IDS Threads.RECIPIENT_IDS
) )
val selection = "${Threads.ARCHIVED} = ?"
val selectionArgs = arrayOf("0")
val conversations = ArrayList<Conversation>() val conversations = ArrayList<Conversation>()
queryCursor(uri, projection, null, null, showErrors = true) { cursor -> queryCursor(uri, projection, selection, selectionArgs, showErrors = true) { cursor ->
val id = cursor.getIntValue(Threads._ID) val id = cursor.getIntValue(Threads._ID)
val snippet = cursor.getStringValue(Threads.SNIPPET) ?: "" val snippet = cursor.getStringValue(Threads.SNIPPET) ?: ""
var date = cursor.getLongValue(Threads.DATE) var date = cursor.getLongValue(Threads.DATE)
@ -169,7 +171,8 @@ fun Context.getConversations(): ArrayList<Conversation> {
val phoneNumbers = getThreadPhoneNumbers(recipientIds) val phoneNumbers = getThreadPhoneNumbers(recipientIds)
val names = getThreadContactNames(phoneNumbers) val names = getThreadContactNames(phoneNumbers)
val title = TextUtils.join(", ", names.toTypedArray()) val title = TextUtils.join(", ", names.toTypedArray())
val conversation = Conversation(id, snippet, date.toInt(), read, title) val photoUri = if (phoneNumbers.size == 1) getPhotoUriFromPhoneNumber(phoneNumbers.first()) else ""
val conversation = Conversation(id, snippet, date.toInt(), read, title, photoUri)
conversations.add(conversation) conversations.add(conversation)
} }
return conversations return conversations
@ -339,7 +342,6 @@ fun Context.getNameAndPhotoFromPhoneNumber(number: String): NamePhoto? {
return NamePhoto(number, null) return NamePhoto(number, null)
} }
fun Context.getNameFromPhoneNumber(number: String): String { fun Context.getNameFromPhoneNumber(number: String): String {
val uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)) val uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number))
val projection = arrayOf( val projection = arrayOf(
@ -360,6 +362,26 @@ fun Context.getNameFromPhoneNumber(number: String): String {
return number return number
} }
fun Context.getPhotoUriFromPhoneNumber(number: String): String {
val uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number))
val projection = arrayOf(
PhoneLookup.PHOTO_URI
)
try {
val cursor = contentResolver.query(uri, projection, null, null, null)
cursor.use {
if (cursor?.moveToFirst() == true) {
return cursor.getStringValue(PhoneLookup.PHOTO_URI) ?: ""
}
}
} catch (e: Exception) {
showErrorToast(e)
}
return ""
}
fun Context.getContactNames(): List<Contact> { fun Context.getContactNames(): List<Contact> {
val contacts = ArrayList<Contact>() val contacts = ArrayList<Contact>()
val uri = ContactsContract.Data.CONTENT_URI val uri = ContactsContract.Data.CONTENT_URI
@ -449,7 +471,7 @@ fun Context.insertNewSMS(address: String, subject: String, body: String, date: L
contentResolver.insert(uri, contentValues) contentResolver.insert(uri, contentValues)
} }
fun Context.deleteThread(id: Int) { fun Context.deleteConversation(id: Int) {
val uri = Sms.CONTENT_URI val uri = Sms.CONTENT_URI
val selection = "${Sms.THREAD_ID} = ?" val selection = "${Sms.THREAD_ID} = ?"
val selectionArgs = arrayOf(id.toString()) val selectionArgs = arrayOf(id.toString())

View File

@ -1,3 +1,3 @@
package com.simplemobiletools.smsmessenger.models package com.simplemobiletools.smsmessenger.models
data class Conversation(val id: Int, val snippet: String, val date: Int, val read: Boolean, val title: String) data class Conversation(val id: Int, val snippet: String, val date: Int, val read: Boolean, val title: String, val photoUri: String)

View File

@ -11,7 +11,7 @@
android:layout_height="match_parent"> android:layout_height="match_parent">
<com.simplemobiletools.commons.views.MyRecyclerView <com.simplemobiletools.commons.views.MyRecyclerView
android:id="@+id/messages_list" android:id="@+id/conversations_list"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:clipToPadding="false" android:clipToPadding="false"
@ -20,11 +20,11 @@
app:layoutManager="com.simplemobiletools.commons.views.MyLinearLayoutManager" /> app:layoutManager="com.simplemobiletools.commons.views.MyLinearLayoutManager" />
<com.simplemobiletools.commons.views.FastScroller <com.simplemobiletools.commons.views.FastScroller
android:id="@+id/messages_fastscroller" android:id="@+id/conversations_fastscroller"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_alignTop="@+id/messages_list" android:layout_alignTop="@+id/conversations_list"
android:layout_alignBottom="@+id/messages_list" android:layout_alignBottom="@+id/conversations_list"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:paddingStart="@dimen/normal_margin"> android:paddingStart="@dimen/normal_margin">
@ -34,7 +34,7 @@
</RelativeLayout> </RelativeLayout>
<com.simplemobiletools.commons.views.MyFloatingActionButton <com.simplemobiletools.commons.views.MyFloatingActionButton
android:id="@+id/messages_fab" android:id="@+id/conversations_fab"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom|end" android:layout_gravity="bottom|end"

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/thread_frame" android:id="@+id/conversation_frame"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground" android:background="?attr/selectableItemBackground"
@ -10,27 +10,27 @@
android:foreground="@drawable/selector"> android:foreground="@drawable/selector">
<RelativeLayout <RelativeLayout
android:id="@+id/thread_holder" android:id="@+id/conversation_holder"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="@dimen/activity_margin" android:paddingTop="@dimen/activity_margin"
android:paddingBottom="@dimen/activity_margin"> android:paddingBottom="@dimen/activity_margin">
<ImageView <ImageView
android:id="@+id/thread_image" android:id="@+id/conversation_image"
android:layout_width="@dimen/normal_icon_size" android:layout_width="@dimen/normal_icon_size"
android:layout_height="@dimen/normal_icon_size" android:layout_height="@dimen/normal_icon_size"
android:layout_alignTop="@+id/thread_address" android:layout_alignTop="@+id/conversation_address"
android:layout_alignBottom="@+id/thread_date" android:layout_alignBottom="@+id/conversation_date"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginStart="@dimen/normal_margin" android:layout_marginStart="@dimen/normal_margin"
android:layout_marginEnd="@dimen/normal_margin" /> android:layout_marginEnd="@dimen/normal_margin" />
<TextView <TextView
android:id="@+id/thread_address" android:id="@+id/conversation_address"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_toEndOf="@+id/thread_image" android:layout_toEndOf="@+id/conversation_image"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
android:paddingEnd="@dimen/activity_margin" android:paddingEnd="@dimen/activity_margin"
@ -38,11 +38,11 @@
tools:text="John" /> tools:text="John" />
<TextView <TextView
android:id="@+id/thread_body_short" android:id="@+id/conversation_body_short"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@+id/thread_address" android:layout_below="@+id/conversation_address"
android:layout_toEndOf="@+id/thread_image" android:layout_toEndOf="@+id/conversation_image"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
android:paddingEnd="@dimen/activity_margin" android:paddingEnd="@dimen/activity_margin"
@ -50,12 +50,12 @@
tools:text="Hey buddy!" /> tools:text="Hey buddy!" />
<TextView <TextView
android:id="@+id/thread_date" android:id="@+id/conversation_date"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@+id/thread_body_short" android:layout_below="@+id/conversation_body_short"
android:layout_marginTop="@dimen/tiny_margin" android:layout_marginTop="@dimen/tiny_margin"
android:layout_toEndOf="@+id/thread_image" android:layout_toEndOf="@+id/conversation_image"
android:alpha="0.4" android:alpha="0.4"
android:textSize="@dimen/smaller_text_size" android:textSize="@dimen/smaller_text_size"
tools:text="13:30" /> tools:text="13:30" />