mirror of
https://github.com/SimpleMobileTools/Simple-Dialer.git
synced 2025-02-12 01:20:49 +01:00
Improved RecentCallsAdapter for onScroll loading
This commit is contained in:
parent
56d0a0ca07
commit
939cba30ea
@ -260,6 +260,7 @@ class RecentCallsAdapter(
|
|||||||
if (newItems.hashCode() != recentCalls.hashCode()) {
|
if (newItems.hashCode() != recentCalls.hashCode()) {
|
||||||
recentCalls = newItems.clone() as ArrayList<RecentCall>
|
recentCalls = newItems.clone() as ArrayList<RecentCall>
|
||||||
textToHighlight = highlightText
|
textToHighlight = highlightText
|
||||||
|
recyclerView.resetItemCount()
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
finishActMode()
|
finishActMode()
|
||||||
} else if (textToHighlight != highlightText) {
|
} else if (textToHighlight != highlightText) {
|
||||||
|
@ -8,17 +8,23 @@ import com.simplemobiletools.commons.helpers.ContactsHelper
|
|||||||
import com.simplemobiletools.commons.helpers.MyContactsContentProvider
|
import com.simplemobiletools.commons.helpers.MyContactsContentProvider
|
||||||
import com.simplemobiletools.commons.helpers.PERMISSION_READ_CALL_LOG
|
import com.simplemobiletools.commons.helpers.PERMISSION_READ_CALL_LOG
|
||||||
import com.simplemobiletools.commons.helpers.SMT_PRIVATE
|
import com.simplemobiletools.commons.helpers.SMT_PRIVATE
|
||||||
|
import com.simplemobiletools.commons.models.contacts.Contact
|
||||||
|
import com.simplemobiletools.commons.views.MyRecyclerView
|
||||||
import com.simplemobiletools.dialer.R
|
import com.simplemobiletools.dialer.R
|
||||||
import com.simplemobiletools.dialer.activities.SimpleActivity
|
import com.simplemobiletools.dialer.activities.SimpleActivity
|
||||||
import com.simplemobiletools.dialer.adapters.RecentCallsAdapter
|
import com.simplemobiletools.dialer.adapters.RecentCallsAdapter
|
||||||
import com.simplemobiletools.dialer.extensions.config
|
import com.simplemobiletools.dialer.extensions.config
|
||||||
|
import com.simplemobiletools.dialer.helpers.MIN_RECENTS_THRESHOLD
|
||||||
import com.simplemobiletools.dialer.helpers.RecentsHelper
|
import com.simplemobiletools.dialer.helpers.RecentsHelper
|
||||||
import com.simplemobiletools.dialer.interfaces.RefreshItemsListener
|
import com.simplemobiletools.dialer.interfaces.RefreshItemsListener
|
||||||
import com.simplemobiletools.dialer.models.RecentCall
|
import com.simplemobiletools.dialer.models.RecentCall
|
||||||
import kotlinx.android.synthetic.main.fragment_recents.view.*
|
import kotlinx.android.synthetic.main.fragment_recents.view.recents_list
|
||||||
|
import kotlinx.android.synthetic.main.fragment_recents.view.recents_placeholder
|
||||||
|
import kotlinx.android.synthetic.main.fragment_recents.view.recents_placeholder_2
|
||||||
|
|
||||||
class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet), RefreshItemsListener {
|
class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet), RefreshItemsListener {
|
||||||
private var allRecentCalls = ArrayList<RecentCall>()
|
private var allRecentCalls = ArrayList<RecentCall>()
|
||||||
|
private var recentsAdapter: RecentCallsAdapter? = null
|
||||||
|
|
||||||
override fun setupFragment() {
|
override fun setupFragment() {
|
||||||
val placeholderResId = if (context.hasPermission(PERMISSION_READ_CALL_LOG)) {
|
val placeholderResId = if (context.hasPermission(PERMISSION_READ_CALL_LOG)) {
|
||||||
@ -40,7 +46,7 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||||||
recents_placeholder.setTextColor(textColor)
|
recents_placeholder.setTextColor(textColor)
|
||||||
recents_placeholder_2.setTextColor(properPrimaryColor)
|
recents_placeholder_2.setTextColor(properPrimaryColor)
|
||||||
|
|
||||||
(recents_list?.adapter as? RecentCallsAdapter)?.apply {
|
recentsAdapter?.apply {
|
||||||
initDrawables()
|
initDrawables()
|
||||||
updateTextColor(textColor)
|
updateTextColor(textColor)
|
||||||
}
|
}
|
||||||
@ -49,36 +55,14 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||||||
override fun refreshItems(callback: (() -> Unit)?) {
|
override fun refreshItems(callback: (() -> Unit)?) {
|
||||||
val privateCursor = context?.getMyContactsCursor(false, true)
|
val privateCursor = context?.getMyContactsCursor(false, true)
|
||||||
val groupSubsequentCalls = context?.config?.groupSubsequentCalls ?: false
|
val groupSubsequentCalls = context?.config?.groupSubsequentCalls ?: false
|
||||||
RecentsHelper(context).getRecentCalls(groupSubsequentCalls) { recents ->
|
val querySize = allRecentCalls.size.coerceAtLeast(MIN_RECENTS_THRESHOLD)
|
||||||
|
RecentsHelper(context).getRecentCalls(groupSubsequentCalls, querySize) { recents ->
|
||||||
ContactsHelper(context).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
|
ContactsHelper(context).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
|
||||||
val privateContacts = MyContactsContentProvider.getContacts(context, privateCursor)
|
val privateContacts = MyContactsContentProvider.getContacts(context, privateCursor)
|
||||||
|
|
||||||
recents.filter { it.phoneNumber == it.name }.forEach { recent ->
|
|
||||||
var wasNameFilled = false
|
|
||||||
if (privateContacts.isNotEmpty()) {
|
|
||||||
val privateContact = privateContacts.firstOrNull { it.doesContainPhoneNumber(recent.phoneNumber) }
|
|
||||||
if (privateContact != null) {
|
|
||||||
recent.name = privateContact.getNameToDisplay()
|
|
||||||
wasNameFilled = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wasNameFilled) {
|
|
||||||
val contact = contacts.filter { it.phoneNumbers.isNotEmpty() }.firstOrNull { it.phoneNumbers.first().normalizedNumber == recent.phoneNumber }
|
|
||||||
if (contact != null) {
|
|
||||||
recent.name = contact.getNameToDisplay()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
allRecentCalls = recents
|
allRecentCalls = recents
|
||||||
|
.setNamesIfEmpty(contacts, privateContacts)
|
||||||
// hide private contacts from recent calls
|
.hidePrivateContacts(privateContacts, SMT_PRIVATE in context.baseConfig.ignoredContactSources)
|
||||||
if (SMT_PRIVATE in context.baseConfig.ignoredContactSources) {
|
|
||||||
allRecentCalls = recents.filterNot { recent ->
|
|
||||||
val privateNumbers = privateContacts.flatMap { it.phoneNumbers }.map { it.value }
|
|
||||||
recent.phoneNumber in privateNumbers
|
|
||||||
} as ArrayList
|
|
||||||
}
|
|
||||||
|
|
||||||
activity?.runOnUiThread {
|
activity?.runOnUiThread {
|
||||||
gotRecents(allRecentCalls)
|
gotRecents(allRecentCalls)
|
||||||
@ -99,7 +83,7 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||||||
|
|
||||||
val currAdapter = recents_list.adapter
|
val currAdapter = recents_list.adapter
|
||||||
if (currAdapter == null) {
|
if (currAdapter == null) {
|
||||||
RecentCallsAdapter(activity as SimpleActivity, recents, recents_list, this, true) {
|
recentsAdapter = RecentCallsAdapter(activity as SimpleActivity, recents, recents_list, this, true) {
|
||||||
val recentCall = it as RecentCall
|
val recentCall = it as RecentCall
|
||||||
if (context.config.showCallConfirmation) {
|
if (context.config.showCallConfirmation) {
|
||||||
CallConfirmationDialog(activity as SimpleActivity, recentCall.name) {
|
CallConfirmationDialog(activity as SimpleActivity, recentCall.name) {
|
||||||
@ -108,15 +92,43 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||||||
} else {
|
} else {
|
||||||
activity?.launchCallIntent(recentCall.phoneNumber)
|
activity?.launchCallIntent(recentCall.phoneNumber)
|
||||||
}
|
}
|
||||||
}.apply {
|
|
||||||
recents_list.adapter = this
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
recents_list.adapter = recentsAdapter
|
||||||
|
|
||||||
if (context.areSystemAnimationsEnabled) {
|
if (context.areSystemAnimationsEnabled) {
|
||||||
recents_list.scheduleLayoutAnimation()
|
recents_list.scheduleLayoutAnimation()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
recents_list.endlessScrollListener = object : MyRecyclerView.EndlessScrollListener {
|
||||||
|
override fun updateTop() {}
|
||||||
|
|
||||||
|
override fun updateBottom() {
|
||||||
|
getMoreRecentCalls()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
(currAdapter as RecentCallsAdapter).updateItems(recents)
|
recentsAdapter?.updateItems(recents)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getMoreRecentCalls() {
|
||||||
|
val privateCursor = context?.getMyContactsCursor(false, true)
|
||||||
|
val groupSubsequentCalls = context?.config?.groupSubsequentCalls ?: false
|
||||||
|
val querySize = allRecentCalls.size.plus(MIN_RECENTS_THRESHOLD)
|
||||||
|
RecentsHelper(context).getRecentCalls(groupSubsequentCalls, querySize) { recents ->
|
||||||
|
ContactsHelper(context).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
|
||||||
|
val privateContacts = MyContactsContentProvider.getContacts(context, privateCursor)
|
||||||
|
|
||||||
|
allRecentCalls = recents
|
||||||
|
.setNamesIfEmpty(contacts, privateContacts)
|
||||||
|
.hidePrivateContacts(privateContacts, SMT_PRIVATE in context.baseConfig.ignoredContactSources)
|
||||||
|
|
||||||
|
activity?.runOnUiThread {
|
||||||
|
gotRecents(allRecentCalls)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,7 +151,7 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||||||
|
|
||||||
override fun onSearchClosed() {
|
override fun onSearchClosed() {
|
||||||
recents_placeholder.beVisibleIf(allRecentCalls.isEmpty())
|
recents_placeholder.beVisibleIf(allRecentCalls.isEmpty())
|
||||||
(recents_list.adapter as? RecentCallsAdapter)?.updateItems(allRecentCalls)
|
recentsAdapter?.updateItems(allRecentCalls)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSearchQueryChanged(text: String) {
|
override fun onSearchQueryChanged(text: String) {
|
||||||
@ -150,6 +162,39 @@ class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
|
|||||||
}.toMutableList() as ArrayList<RecentCall>
|
}.toMutableList() as ArrayList<RecentCall>
|
||||||
|
|
||||||
recents_placeholder.beVisibleIf(recentCalls.isEmpty())
|
recents_placeholder.beVisibleIf(recentCalls.isEmpty())
|
||||||
(recents_list.adapter as? RecentCallsAdapter)?.updateItems(recentCalls, text)
|
recentsAdapter?.updateItems(recentCalls, text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hide private contacts from recent calls
|
||||||
|
private fun List<RecentCall>.hidePrivateContacts(privateContacts: ArrayList<Contact>, shouldHide: Boolean): ArrayList<RecentCall> {
|
||||||
|
return if (shouldHide) {
|
||||||
|
filterNot { recent ->
|
||||||
|
val privateNumbers = privateContacts.flatMap { it.phoneNumbers }.map { it.value }
|
||||||
|
recent.phoneNumber in privateNumbers
|
||||||
|
} as ArrayList
|
||||||
|
} else {
|
||||||
|
this as ArrayList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ArrayList<RecentCall>.setNamesIfEmpty(contacts: ArrayList<Contact>, privateContacts: ArrayList<Contact>): ArrayList<RecentCall> {
|
||||||
|
filter { it.phoneNumber == it.name }.forEach { recent ->
|
||||||
|
var wasNameFilled = false
|
||||||
|
if (privateContacts.isNotEmpty()) {
|
||||||
|
val privateContact = privateContacts.firstOrNull { it.doesContainPhoneNumber(recent.phoneNumber) }
|
||||||
|
if (privateContact != null) {
|
||||||
|
recent.name = privateContact.getNameToDisplay()
|
||||||
|
wasNameFilled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wasNameFilled) {
|
||||||
|
val contact = contacts.filter { it.phoneNumbers.isNotEmpty() }.firstOrNull { it.phoneNumbers.first().normalizedNumber == recent.phoneNumber }
|
||||||
|
if (contact != null) {
|
||||||
|
recent.name = contact.getNameToDisplay()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
@ -28,3 +28,5 @@ const val ACCEPT_CALL = PATH + "accept_call"
|
|||||||
const val DECLINE_CALL = PATH + "decline_call"
|
const val DECLINE_CALL = PATH + "decline_call"
|
||||||
|
|
||||||
const val DIALPAD_TONE_LENGTH_MS = 150L // The length of DTMF tones in milliseconds
|
const val DIALPAD_TONE_LENGTH_MS = 150L // The length of DTMF tones in milliseconds
|
||||||
|
|
||||||
|
const val MIN_RECENTS_THRESHOLD = 30
|
||||||
|
@ -13,10 +13,10 @@ import com.simplemobiletools.dialer.models.RecentCall
|
|||||||
|
|
||||||
class RecentsHelper(private val context: Context) {
|
class RecentsHelper(private val context: Context) {
|
||||||
private val COMPARABLE_PHONE_NUMBER_LENGTH = 9
|
private val COMPARABLE_PHONE_NUMBER_LENGTH = 9
|
||||||
private val QUERY_LIMIT = "200"
|
private val QUERY_LIMIT = 200
|
||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
fun getRecentCalls(groupSubsequentCalls: Boolean, callback: (ArrayList<RecentCall>) -> Unit) {
|
fun getRecentCalls(groupSubsequentCalls: Boolean, maxSize: Int = QUERY_LIMIT, callback: (ArrayList<RecentCall>) -> Unit) {
|
||||||
val privateCursor = context.getMyContactsCursor(false, true)
|
val privateCursor = context.getMyContactsCursor(false, true)
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
if (!context.hasPermission(PERMISSION_READ_CALL_LOG)) {
|
if (!context.hasPermission(PERMISSION_READ_CALL_LOG)) {
|
||||||
@ -30,13 +30,13 @@ class RecentsHelper(private val context: Context) {
|
|||||||
contacts.addAll(privateContacts)
|
contacts.addAll(privateContacts)
|
||||||
}
|
}
|
||||||
|
|
||||||
getRecents(contacts, groupSubsequentCalls, callback)
|
getRecents(contacts, groupSubsequentCalls, maxSize, callback = callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
private fun getRecents(contacts: ArrayList<Contact>, groupSubsequentCalls: Boolean, callback: (ArrayList<RecentCall>) -> Unit) {
|
private fun getRecents(contacts: ArrayList<Contact>, groupSubsequentCalls: Boolean, maxSize: Int, callback: (ArrayList<RecentCall>) -> Unit) {
|
||||||
|
|
||||||
var recentCalls = ArrayList<RecentCall>()
|
var recentCalls = ArrayList<RecentCall>()
|
||||||
var previousRecentCallFrom = ""
|
var previousRecentCallFrom = ""
|
||||||
@ -64,7 +64,7 @@ class RecentsHelper(private val context: Context) {
|
|||||||
val cursor = if (isNougatPlus()) {
|
val cursor = if (isNougatPlus()) {
|
||||||
// https://issuetracker.google.com/issues/175198972?pli=1#comment6
|
// https://issuetracker.google.com/issues/175198972?pli=1#comment6
|
||||||
val limitedUri = uri.buildUpon()
|
val limitedUri = uri.buildUpon()
|
||||||
.appendQueryParameter(Calls.LIMIT_PARAM_KEY, QUERY_LIMIT)
|
.appendQueryParameter(Calls.LIMIT_PARAM_KEY, QUERY_LIMIT.toString())
|
||||||
.build()
|
.build()
|
||||||
val sortOrder = "${Calls._ID} DESC"
|
val sortOrder = "${Calls._ID} DESC"
|
||||||
context.contentResolver.query(limitedUri, projection, null, null, sortOrder)
|
context.contentResolver.query(limitedUri, projection, null, null, sortOrder)
|
||||||
@ -163,7 +163,7 @@ class RecentsHelper(private val context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
previousRecentCallFrom = "$number$name$simID"
|
previousRecentCallFrom = "$number$name$simID"
|
||||||
} while (cursor.moveToNext())
|
} while (cursor.moveToNext() && recentCalls.size < maxSize)
|
||||||
}
|
}
|
||||||
cursor?.close()
|
cursor?.close()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user