mirror of
https://github.com/SimpleMobileTools/Simple-Contacts.git
synced 2025-06-05 21:59:27 +02:00
imports contacts helper & extensions
This commit is contained in:
@@ -5,6 +5,7 @@ import org.jetbrains.kotlin.konan.properties.Properties
|
||||
plugins {
|
||||
alias(libs.plugins.android)
|
||||
alias(libs.plugins.kotlinAndroid)
|
||||
alias(libs.plugins.kotlinSerialization)
|
||||
alias(libs.plugins.ksp)
|
||||
}
|
||||
|
||||
@@ -88,6 +89,7 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
implementation(libs.simple.tools.commons)
|
||||
implementation(libs.androidx.swiperefreshlayout)
|
||||
implementation(libs.autofittextview)
|
||||
|
@@ -24,6 +24,7 @@ import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
||||
import com.simplemobiletools.commons.dialogs.FilePickerDialog
|
||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
//import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.models.FAQItem
|
||||
import com.simplemobiletools.commons.models.PhoneNumber
|
||||
@@ -38,11 +39,16 @@ import com.simplemobiletools.contacts.pro.dialogs.ChangeSortingDialog
|
||||
import com.simplemobiletools.contacts.pro.dialogs.ExportContactsDialog
|
||||
import com.simplemobiletools.contacts.pro.dialogs.FilterContactSourcesDialog
|
||||
import com.simplemobiletools.contacts.pro.dialogs.ImportContactsDialog
|
||||
import com.simplemobiletools.contacts.pro.extensions.config
|
||||
import com.simplemobiletools.contacts.pro.extensions.handleGenericContactClick
|
||||
import com.simplemobiletools.contacts.pro.extensions.*
|
||||
import com.simplemobiletools.contacts.pro.extensions.getTempFile
|
||||
import com.simplemobiletools.contacts.pro.extensions.isPackageInstalled
|
||||
import com.simplemobiletools.contacts.pro.extensions.showErrorToast
|
||||
import com.simplemobiletools.contacts.pro.extensions.toast
|
||||
import com.simplemobiletools.contacts.pro.extensions.updateBottomTabItemColors
|
||||
import com.simplemobiletools.contacts.pro.fragments.FavoritesFragment
|
||||
import com.simplemobiletools.contacts.pro.fragments.MyViewPagerFragment
|
||||
import com.simplemobiletools.contacts.pro.helpers.ALL_TABS_MASK
|
||||
import com.simplemobiletools.contacts.pro.helpers.ContactsHelper
|
||||
import com.simplemobiletools.contacts.pro.helpers.VcfExporter
|
||||
import com.simplemobiletools.contacts.pro.helpers.tabsList
|
||||
import com.simplemobiletools.contacts.pro.interfaces.RefreshContactsListener
|
||||
@@ -624,44 +630,48 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
binding.viewPager.currentItem = getDefaultTab()
|
||||
}
|
||||
|
||||
val initToLoad = System.currentTimeMillis() - timeInMs
|
||||
ContactsHelper(this).getContacts { contacts ->
|
||||
val diff = System.currentTimeMillis() - timeInMs
|
||||
val msg = "loaded ${contacts.size} in $diff ms (init: $initToLoad + load: ${diff - initToLoad})";
|
||||
Log.e("TAGG", msg)
|
||||
toast(msg)
|
||||
isGettingContacts = false
|
||||
if (isDestroyed || isFinishing) {
|
||||
return@getContacts
|
||||
}
|
||||
|
||||
if (refreshTabsMask and TAB_CONTACTS != 0) {
|
||||
findViewById<MyViewPagerFragment<*>>(R.id.contacts_fragment)?.apply {
|
||||
skipHashComparing = true
|
||||
refreshContacts(contacts)
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
val initToLoad = System.currentTimeMillis() - timeInMs
|
||||
ContactsHelper(this).getContacts { contacts ->
|
||||
val diff = System.currentTimeMillis() - timeInMs
|
||||
val msg = "loaded ${contacts.size} in $diff ms (init: $initToLoad + load: ${diff - initToLoad})";
|
||||
Log.e("TAGG", msg)
|
||||
toast(msg)
|
||||
isGettingContacts = false
|
||||
if (isDestroyed || isFinishing) {
|
||||
return@getContacts
|
||||
}
|
||||
}
|
||||
|
||||
if (refreshTabsMask and TAB_FAVORITES != 0) {
|
||||
findViewById<MyViewPagerFragment<*>>(R.id.favorites_fragment)?.apply {
|
||||
skipHashComparing = true
|
||||
refreshContacts(contacts)
|
||||
}
|
||||
}
|
||||
|
||||
if (refreshTabsMask and TAB_GROUPS != 0) {
|
||||
findViewById<MyViewPagerFragment<*>>(R.id.groups_fragment)?.apply {
|
||||
if (refreshTabsMask == TAB_GROUPS) {
|
||||
if (refreshTabsMask and TAB_CONTACTS != 0) {
|
||||
findViewById<MyViewPagerFragment<*>>(R.id.contacts_fragment)?.apply {
|
||||
skipHashComparing = true
|
||||
refreshContacts(contacts)
|
||||
}
|
||||
refreshContacts(contacts)
|
||||
}
|
||||
|
||||
if (refreshTabsMask and TAB_FAVORITES != 0) {
|
||||
findViewById<MyViewPagerFragment<*>>(R.id.favorites_fragment)?.apply {
|
||||
skipHashComparing = true
|
||||
refreshContacts(contacts)
|
||||
}
|
||||
}
|
||||
|
||||
if (refreshTabsMask and TAB_GROUPS != 0) {
|
||||
findViewById<MyViewPagerFragment<*>>(R.id.groups_fragment)?.apply {
|
||||
if (refreshTabsMask == TAB_GROUPS) {
|
||||
skipHashComparing = true
|
||||
}
|
||||
refreshContacts(contacts)
|
||||
}
|
||||
}
|
||||
|
||||
if (binding.mainMenu.isSearchOpen) {
|
||||
getCurrentFragment()?.onSearchQueryChanged(binding.mainMenu.getCurrentQuery())
|
||||
}
|
||||
}
|
||||
|
||||
if (binding.mainMenu.isSearchOpen) {
|
||||
getCurrentFragment()?.onSearchQueryChanged(binding.mainMenu.getCurrentQuery())
|
||||
}
|
||||
}
|
||||
}, 3000)
|
||||
}
|
||||
|
||||
override fun contactClicked(contact: Contact) {
|
||||
|
@@ -20,6 +20,7 @@ import com.simplemobiletools.commons.dialogs.CallConfirmationDialog
|
||||
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
||||
import com.simplemobiletools.commons.dialogs.SelectAlarmSoundDialog
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.contacts.pro.helpers.*
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.models.PhoneNumber
|
||||
import com.simplemobiletools.commons.models.contacts.*
|
||||
@@ -32,6 +33,7 @@ import com.simplemobiletools.contacts.pro.extensions.editContact
|
||||
import com.simplemobiletools.contacts.pro.extensions.getPackageDrawable
|
||||
import com.simplemobiletools.contacts.pro.extensions.startCallIntent
|
||||
import com.simplemobiletools.contacts.pro.helpers.*
|
||||
import com.simplemobiletools.contacts.pro.helpers.ContactsHelper
|
||||
|
||||
class ViewContactActivity : ContactActivity() {
|
||||
private var isViewIntent = false
|
||||
|
@@ -0,0 +1,400 @@
|
||||
package com.simplemobiletools.contacts.pro.extensions
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.provider.ContactsContract
|
||||
import android.telephony.PhoneNumberUtils
|
||||
import com.simplemobiletools.commons.R
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.databases.ContactsDatabase
|
||||
import com.simplemobiletools.commons.dialogs.CallConfirmationDialog
|
||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||
import com.simplemobiletools.commons.extensions.getIntValue
|
||||
import com.simplemobiletools.commons.extensions.getLongValue
|
||||
import com.simplemobiletools.commons.extensions.getStringValue
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.interfaces.ContactsDao
|
||||
import com.simplemobiletools.commons.interfaces.GroupsDao
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import com.simplemobiletools.commons.models.contacts.Contact
|
||||
import com.simplemobiletools.commons.models.contacts.ContactSource
|
||||
import com.simplemobiletools.commons.models.contacts.Organization
|
||||
import com.simplemobiletools.commons.models.contacts.SocialAction
|
||||
import com.simplemobiletools.contacts.pro.helpers.ContactsHelper
|
||||
import java.io.File
|
||||
|
||||
val Context.contactsDB: ContactsDao get() = ContactsDatabase.getInstance(applicationContext).ContactsDao()
|
||||
|
||||
val Context.groupsDB: GroupsDao get() = ContactsDatabase.getInstance(applicationContext).GroupsDao()
|
||||
|
||||
fun Context.getEmptyContact(): Contact {
|
||||
val originalContactSource = if (hasContactPermissions()) baseConfig.lastUsedContactSource else SMT_PRIVATE
|
||||
val organization = Organization("", "")
|
||||
return Contact(
|
||||
0, "", "", "", "", "", "", "", ArrayList(), ArrayList(), ArrayList(), ArrayList(), originalContactSource, 0, 0, "",
|
||||
null, "", ArrayList(), organization, ArrayList(), ArrayList(), DEFAULT_MIMETYPE, null
|
||||
)
|
||||
}
|
||||
|
||||
fun Context.sendAddressIntent(address: String) {
|
||||
val location = Uri.encode(address)
|
||||
val uri = Uri.parse("geo:0,0?q=$location")
|
||||
|
||||
Intent(Intent.ACTION_VIEW, uri).apply {
|
||||
launchActivityIntent(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.openWebsiteIntent(url: String) {
|
||||
val website = if (url.startsWith("http")) {
|
||||
url
|
||||
} else {
|
||||
"https://$url"
|
||||
}
|
||||
|
||||
Intent(Intent.ACTION_VIEW).apply {
|
||||
data = Uri.parse(website)
|
||||
launchActivityIntent(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.getLookupUriRawId(dataUri: Uri): Int {
|
||||
val lookupKey = getLookupKeyFromUri(dataUri)
|
||||
if (lookupKey != null) {
|
||||
val uri = lookupContactUri(lookupKey, this)
|
||||
if (uri != null) {
|
||||
return getContactUriRawId(uri)
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
fun Context.getContactUriRawId(uri: Uri): Int {
|
||||
val projection = arrayOf(ContactsContract.Contacts.NAME_RAW_CONTACT_ID)
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = contentResolver.query(uri, projection, null, null, null)
|
||||
if (cursor!!.moveToFirst()) {
|
||||
return cursor.getIntValue(ContactsContract.Contacts.NAME_RAW_CONTACT_ID)
|
||||
}
|
||||
} catch (ignored: Exception) {
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// from https://android.googlesource.com/platform/packages/apps/Dialer/+/68038172793ee0e2ab3e2e56ddfbeb82879d1f58/java/com/android/contacts/common/util/UriUtils.java
|
||||
fun getLookupKeyFromUri(lookupUri: Uri): String? {
|
||||
return if (!isEncodedContactUri(lookupUri)) {
|
||||
val segments = lookupUri.pathSegments
|
||||
if (segments.size < 3) null else Uri.encode(segments[2])
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun isEncodedContactUri(uri: Uri?): Boolean {
|
||||
if (uri == null) {
|
||||
return false
|
||||
}
|
||||
val lastPathSegment = uri.lastPathSegment ?: return false
|
||||
return lastPathSegment == "encoded"
|
||||
}
|
||||
|
||||
fun lookupContactUri(lookup: String, context: Context): Uri? {
|
||||
val lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookup)
|
||||
return try {
|
||||
ContactsContract.Contacts.lookupContact(context.contentResolver, lookupUri)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.getCachePhoto(): File {
|
||||
val imagesFolder = File(cacheDir, "my_cache")
|
||||
if (!imagesFolder.exists()) {
|
||||
imagesFolder.mkdirs()
|
||||
}
|
||||
|
||||
val file = File(imagesFolder, "Photo_${System.currentTimeMillis()}.jpg")
|
||||
file.createNewFile()
|
||||
return file
|
||||
}
|
||||
|
||||
fun Context.getPhotoThumbnailSize(): Int {
|
||||
val uri = ContactsContract.DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI
|
||||
val projection = arrayOf(ContactsContract.DisplayPhoto.THUMBNAIL_MAX_DIM)
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = contentResolver.query(uri, projection, null, null, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
return cursor.getIntValue(ContactsContract.DisplayPhoto.THUMBNAIL_MAX_DIM)
|
||||
}
|
||||
} catch (ignored: Exception) {
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
fun Context.hasContactPermissions() = hasPermission(PERMISSION_READ_CONTACTS) && hasPermission(PERMISSION_WRITE_CONTACTS)
|
||||
|
||||
fun Context.getPublicContactSource(source: String, callback: (String) -> Unit) {
|
||||
when (source) {
|
||||
SMT_PRIVATE -> callback(getString(R.string.phone_storage_hidden))
|
||||
else -> {
|
||||
ContactsHelper(this).getContactSources {
|
||||
var newSource = source
|
||||
for (contactSource in it) {
|
||||
if (contactSource.name == source && contactSource.type == TELEGRAM_PACKAGE) {
|
||||
newSource = getString(R.string.telegram)
|
||||
break
|
||||
} else if (contactSource.name == source && contactSource.type == VIBER_PACKAGE) {
|
||||
newSource = getString(R.string.viber)
|
||||
break
|
||||
}
|
||||
}
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
callback(newSource)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.getPublicContactSourceSync(source: String, contactSources: ArrayList<ContactSource>): String {
|
||||
return when (source) {
|
||||
SMT_PRIVATE -> getString(R.string.phone_storage_hidden)
|
||||
else -> {
|
||||
var newSource = source
|
||||
for (contactSource in contactSources) {
|
||||
if (contactSource.name == source && contactSource.type == TELEGRAM_PACKAGE) {
|
||||
newSource = getString(R.string.telegram)
|
||||
break
|
||||
} else if (contactSource.name == source && contactSource.type == VIBER_PACKAGE) {
|
||||
newSource = getString(R.string.viber)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return newSource
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.sendSMSToContacts(contacts: ArrayList<Contact>) {
|
||||
val numbers = StringBuilder()
|
||||
contacts.forEach {
|
||||
val number = it.phoneNumbers.firstOrNull { it.type == ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE }
|
||||
?: it.phoneNumbers.firstOrNull()
|
||||
if (number != null) {
|
||||
numbers.append("${Uri.encode(number.value)};")
|
||||
}
|
||||
}
|
||||
|
||||
val uriString = "smsto:${numbers.toString().trimEnd(';')}"
|
||||
Intent(Intent.ACTION_SENDTO, Uri.parse(uriString)).apply {
|
||||
launchActivityIntent(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.sendEmailToContacts(contacts: ArrayList<Contact>) {
|
||||
val emails = ArrayList<String>()
|
||||
contacts.forEach {
|
||||
it.emails.forEach {
|
||||
if (it.value.isNotEmpty()) {
|
||||
emails.add(it.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Intent(Intent.ACTION_SEND_MULTIPLE).apply {
|
||||
type = "message/rfc822"
|
||||
putExtra(Intent.EXTRA_EMAIL, emails.toTypedArray())
|
||||
launchActivityIntent(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.getTempFile(filename: String = DEFAULT_FILE_NAME): File? {
|
||||
val folder = File(cacheDir, "contacts")
|
||||
if (!folder.exists()) {
|
||||
if (!folder.mkdir()) {
|
||||
toast(R.string.unknown_error_occurred)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return File(folder, filename)
|
||||
}
|
||||
|
||||
fun Context.addContactsToGroup(contacts: ArrayList<Contact>, groupId: Long) {
|
||||
val publicContacts = contacts.filter { !it.isPrivate() }.toMutableList() as ArrayList<Contact>
|
||||
val privateContacts = contacts.filter { it.isPrivate() }.toMutableList() as ArrayList<Contact>
|
||||
if (publicContacts.isNotEmpty()) {
|
||||
ContactsHelper(this).addContactsToGroup(publicContacts, groupId)
|
||||
}
|
||||
|
||||
if (privateContacts.isNotEmpty()) {
|
||||
LocalContactsHelper(this).addContactsToGroup(privateContacts, groupId)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.removeContactsFromGroup(contacts: ArrayList<Contact>, groupId: Long) {
|
||||
val publicContacts = contacts.filter { !it.isPrivate() }.toMutableList() as ArrayList<Contact>
|
||||
val privateContacts = contacts.filter { it.isPrivate() }.toMutableList() as ArrayList<Contact>
|
||||
if (publicContacts.isNotEmpty() && hasContactPermissions()) {
|
||||
ContactsHelper(this).removeContactsFromGroup(publicContacts, groupId)
|
||||
}
|
||||
|
||||
if (privateContacts.isNotEmpty()) {
|
||||
LocalContactsHelper(this).removeContactsFromGroup(privateContacts, groupId)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.getContactPublicUri(contact: Contact): Uri {
|
||||
val lookupKey = if (contact.isPrivate()) {
|
||||
"local_${contact.id}"
|
||||
} else {
|
||||
SimpleContactsHelper(this).getContactLookupKey(contact.id.toString())
|
||||
}
|
||||
return Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey)
|
||||
}
|
||||
|
||||
fun Context.getVisibleContactSources(): ArrayList<String> {
|
||||
val sources = getAllContactSources()
|
||||
val ignoredContactSources = baseConfig.ignoredContactSources
|
||||
return ArrayList(sources).filter { !ignoredContactSources.contains(it.getFullIdentifier()) }
|
||||
.map { it.name }.toMutableList() as ArrayList<String>
|
||||
}
|
||||
|
||||
fun Context.getAllContactSources(): ArrayList<ContactSource> {
|
||||
val sources = ContactsHelper(this).getDeviceContactSources()
|
||||
sources.add(getPrivateContactSource())
|
||||
return sources.toMutableList() as ArrayList<ContactSource>
|
||||
}
|
||||
|
||||
fun Context.getPrivateContactSource() = ContactSource(SMT_PRIVATE, SMT_PRIVATE, getString(R.string.phone_storage_hidden))
|
||||
|
||||
fun Context.getSocialActions(id: Int): ArrayList<SocialAction> {
|
||||
val uri = ContactsContract.Data.CONTENT_URI
|
||||
val projection = arrayOf(
|
||||
ContactsContract.Data._ID,
|
||||
ContactsContract.Data.DATA3,
|
||||
ContactsContract.Data.MIMETYPE,
|
||||
ContactsContract.Data.ACCOUNT_TYPE_AND_DATA_SET
|
||||
)
|
||||
|
||||
val socialActions = ArrayList<SocialAction>()
|
||||
var curActionId = 0
|
||||
val selection = "${ContactsContract.Data.RAW_CONTACT_ID} = ?"
|
||||
val selectionArgs = arrayOf(id.toString())
|
||||
queryCursor(uri, projection, selection, selectionArgs, null, true) { cursor ->
|
||||
val mimetype = cursor.getStringValue(ContactsContract.Data.MIMETYPE)
|
||||
val type = when (mimetype) {
|
||||
// WhatsApp
|
||||
"vnd.android.cursor.item/vnd.com.whatsapp.profile" -> SOCIAL_MESSAGE
|
||||
"vnd.android.cursor.item/vnd.com.whatsapp.voip.call" -> SOCIAL_VOICE_CALL
|
||||
"vnd.android.cursor.item/vnd.com.whatsapp.video.call" -> SOCIAL_VIDEO_CALL
|
||||
|
||||
// Viber
|
||||
"vnd.android.cursor.item/vnd.com.viber.voip.viber_number_call" -> SOCIAL_VOICE_CALL
|
||||
"vnd.android.cursor.item/vnd.com.viber.voip.viber_out_call_viber" -> SOCIAL_VOICE_CALL
|
||||
"vnd.android.cursor.item/vnd.com.viber.voip.viber_out_call_none_viber" -> SOCIAL_VOICE_CALL
|
||||
"vnd.android.cursor.item/vnd.com.viber.voip.viber_number_message" -> SOCIAL_MESSAGE
|
||||
|
||||
// Signal
|
||||
"vnd.android.cursor.item/vnd.org.thoughtcrime.securesms.contact" -> SOCIAL_MESSAGE
|
||||
"vnd.android.cursor.item/vnd.org.thoughtcrime.securesms.call" -> SOCIAL_VOICE_CALL
|
||||
|
||||
// Telegram
|
||||
"vnd.android.cursor.item/vnd.org.telegram.messenger.android.call" -> SOCIAL_VOICE_CALL
|
||||
"vnd.android.cursor.item/vnd.org.telegram.messenger.android.call.video" -> SOCIAL_VIDEO_CALL
|
||||
"vnd.android.cursor.item/vnd.org.telegram.messenger.android.profile" -> SOCIAL_MESSAGE
|
||||
|
||||
// Threema
|
||||
"vnd.android.cursor.item/vnd.ch.threema.app.profile" -> SOCIAL_MESSAGE
|
||||
"vnd.android.cursor.item/vnd.ch.threema.app.call" -> SOCIAL_VOICE_CALL
|
||||
else -> return@queryCursor
|
||||
}
|
||||
|
||||
val label = cursor.getStringValue(ContactsContract.Data.DATA3)
|
||||
val realID = cursor.getLongValue(ContactsContract.Data._ID)
|
||||
val packageName = cursor.getStringValue(ContactsContract.Data.ACCOUNT_TYPE_AND_DATA_SET)
|
||||
val socialAction = SocialAction(curActionId++, type, label, mimetype, realID, packageName)
|
||||
socialActions.add(socialAction)
|
||||
}
|
||||
return socialActions
|
||||
}
|
||||
|
||||
fun BaseSimpleActivity.initiateCall(contact: Contact, onStartCallIntent: (phoneNumber: String) -> Unit) {
|
||||
val numbers = contact.phoneNumbers
|
||||
if (numbers.size == 1) {
|
||||
onStartCallIntent(numbers.first().value)
|
||||
} else if (numbers.size > 1) {
|
||||
val primaryNumber = contact.phoneNumbers.find { it.isPrimary }
|
||||
if (primaryNumber != null) {
|
||||
onStartCallIntent(primaryNumber.value)
|
||||
} else {
|
||||
val items = ArrayList<RadioItem>()
|
||||
numbers.forEachIndexed { index, phoneNumber ->
|
||||
items.add(RadioItem(index, "${phoneNumber.value} (${getPhoneNumberTypeText(phoneNumber.type, phoneNumber.label)})", phoneNumber.value))
|
||||
}
|
||||
|
||||
RadioGroupDialog(this, items) {
|
||||
onStartCallIntent(it as String)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun BaseSimpleActivity.tryInitiateCall(contact: Contact, onStartCallIntent: (phoneNumber: String) -> Unit) {
|
||||
if (baseConfig.showCallConfirmation) {
|
||||
CallConfirmationDialog(this, contact.getNameToDisplay()) {
|
||||
initiateCall(contact, onStartCallIntent)
|
||||
}
|
||||
} else {
|
||||
initiateCall(contact, onStartCallIntent)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.isContactBlocked(contact: Contact, callback: (Boolean) -> Unit) {
|
||||
val phoneNumbers = contact.phoneNumbers.map { PhoneNumberUtils.stripSeparators(it.value) }
|
||||
getBlockedNumbersWithContact { blockedNumbersWithContact ->
|
||||
val blockedNumbers = blockedNumbersWithContact.map { it.number }
|
||||
val allNumbersBlocked = phoneNumbers.all { it in blockedNumbers }
|
||||
callback(allNumbersBlocked)
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
fun Context.blockContact(contact: Contact): Boolean {
|
||||
var contactBlocked = true
|
||||
ensureBackgroundThread {
|
||||
contact.phoneNumbers.forEach {
|
||||
val numberBlocked = addBlockedNumber(PhoneNumberUtils.stripSeparators(it.value))
|
||||
contactBlocked = contactBlocked && numberBlocked
|
||||
}
|
||||
}
|
||||
|
||||
return contactBlocked
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
fun Context.unblockContact(contact: Contact): Boolean {
|
||||
var contactUnblocked = true
|
||||
ensureBackgroundThread {
|
||||
contact.phoneNumbers.forEach {
|
||||
val numberUnblocked = deleteBlockedNumber(PhoneNumberUtils.stripSeparators(it.value))
|
||||
contactUnblocked = contactUnblocked && numberUnblocked
|
||||
}
|
||||
}
|
||||
|
||||
return contactUnblocked
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -2,4 +2,6 @@ plugins {
|
||||
alias(libs.plugins.android).apply(false)
|
||||
alias(libs.plugins.kotlinAndroid).apply(false)
|
||||
alias(libs.plugins.ksp).apply(false)
|
||||
alias(libs.plugins.kotlinSerialization).apply(false)
|
||||
|
||||
}
|
||||
|
@@ -3,6 +3,8 @@
|
||||
kotlin = "1.9.0"
|
||||
#KSP
|
||||
ksp = "1.9.0-1.0.12"
|
||||
kotlinxSerializationJson = "1.5.1"
|
||||
|
||||
#AndroidX
|
||||
androidx-swiperefreshlayout = "1.1.0"
|
||||
#AutoFitTextView
|
||||
@@ -30,6 +32,8 @@ app-version-versionName = "6.22.7"
|
||||
[libraries]
|
||||
#AndroidX
|
||||
androidx-swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version.ref = "androidx-swiperefreshlayout" }
|
||||
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
|
||||
|
||||
#AutoFitTextView
|
||||
autofittextview = { module = "me.grantland:autofittextview", version.ref = "autofittextview" }
|
||||
#EzVcard
|
||||
@@ -51,3 +55,4 @@ room = [
|
||||
android = { id = "com.android.application", version.ref = "gradlePlugins-agp" }
|
||||
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
||||
kotlinSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
|
||||
|
Reference in New Issue
Block a user