@ -45,7 +45,7 @@ ext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.simplemobiletools:commons:3.19.21'
|
implementation 'com.simplemobiletools:commons:3.20.6'
|
||||||
implementation 'joda-time:joda-time:2.9.9'
|
implementation 'joda-time:joda-time:2.9.9'
|
||||||
implementation 'com.facebook.stetho:stetho:1.5.0'
|
implementation 'com.facebook.stetho:stetho:1.5.0'
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
<uses-permission android:name="android.permission.READ_CONTACTS"/>
|
<uses-permission android:name="android.permission.READ_CONTACTS"/>
|
||||||
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
|
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
|
||||||
|
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.USE_FINGERPRINT"
|
android:name="android.permission.USE_FINGERPRINT"
|
||||||
@ -26,8 +28,6 @@
|
|||||||
android:name=".activities.SplashActivity"
|
android:name=".activities.SplashActivity"
|
||||||
android:theme="@style/SplashTheme">
|
android:theme="@style/SplashTheme">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
@ -190,5 +190,30 @@
|
|||||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
android:resource="@xml/provider_paths"/>
|
android:resource="@xml/provider_paths"/>
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
|
<!-- Do not append ".Orange" to the default alias "name", it would remove the old homescreen launcher of users at upgrade -->
|
||||||
|
<activity-alias
|
||||||
|
android:name=".activities.SplashActivity"
|
||||||
|
android:enabled="true"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher"
|
||||||
|
android:targetActivity=".activities.SplashActivity">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
</intent-filter>
|
||||||
|
</activity-alias>
|
||||||
|
|
||||||
|
<activity-alias
|
||||||
|
android:name=".activities.SplashActivity.Red"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_red"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_red"
|
||||||
|
android:targetActivity=".activities.SplashActivity">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
</intent-filter>
|
||||||
|
</activity-alias>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -87,6 +87,7 @@ class EditContactActivity : ContactActivity() {
|
|||||||
if (wasActivityInitialized) {
|
if (wasActivityInitialized) {
|
||||||
menu.findItem(R.id.delete).isVisible = contact?.id != 0
|
menu.findItem(R.id.delete).isVisible = contact?.id != 0
|
||||||
menu.findItem(R.id.share).isVisible = contact?.id != 0
|
menu.findItem(R.id.share).isVisible = contact?.id != 0
|
||||||
|
menu.findItem(R.id.open_with).isVisible = contact?.id != 0 && contact?.source != SMT_PRIVATE
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -94,8 +95,9 @@ class EditContactActivity : ContactActivity() {
|
|||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.save -> saveContact()
|
R.id.save -> saveContact()
|
||||||
R.id.delete -> deleteContact()
|
|
||||||
R.id.share -> shareContact()
|
R.id.share -> shareContact()
|
||||||
|
R.id.open_with -> openWith()
|
||||||
|
R.id.delete -> deleteContact()
|
||||||
else -> return super.onOptionsItemSelected(item)
|
else -> return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -224,6 +226,14 @@ class EditContactActivity : ContactActivity() {
|
|||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun openWith() {
|
||||||
|
Intent().apply {
|
||||||
|
action = Intent.ACTION_EDIT
|
||||||
|
data = getContactPublicUri(contact!!)
|
||||||
|
startActivity(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun startCropPhotoIntent(uri: Uri?) {
|
private fun startCropPhotoIntent(uri: Uri?) {
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
toast(R.string.unknown_error_occurred)
|
toast(R.string.unknown_error_occurred)
|
||||||
|
@ -234,16 +234,6 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
|||||||
|
|
||||||
private fun storeLocalAccountData() {
|
private fun storeLocalAccountData() {
|
||||||
if (config.localAccountType == "-1") {
|
if (config.localAccountType == "-1") {
|
||||||
// some manufacturer contact account types from https://stackoverflow.com/a/44802016/1967672
|
|
||||||
val localAccountTypes = arrayListOf("vnd.sec.contact.phone",
|
|
||||||
"com.htc.android.pcsc",
|
|
||||||
"com.sonyericsson.localcontacts",
|
|
||||||
"com.lge.sync",
|
|
||||||
"com.lge.phone",
|
|
||||||
"vnd.tmobileus.contact.phone",
|
|
||||||
"com.android.huawei.phone",
|
|
||||||
"Local Phone Account")
|
|
||||||
|
|
||||||
ContactsHelper(this).getContactSources {
|
ContactsHelper(this).getContactSources {
|
||||||
var localAccountType = ""
|
var localAccountType = ""
|
||||||
var localAccountName = ""
|
var localAccountName = ""
|
||||||
|
@ -17,6 +17,7 @@ import com.simplemobiletools.contacts.adapters.SelectContactsAdapter
|
|||||||
import com.simplemobiletools.contacts.dialogs.ChangeSortingDialog
|
import com.simplemobiletools.contacts.dialogs.ChangeSortingDialog
|
||||||
import com.simplemobiletools.contacts.dialogs.FilterContactSourcesDialog
|
import com.simplemobiletools.contacts.dialogs.FilterContactSourcesDialog
|
||||||
import com.simplemobiletools.contacts.extensions.config
|
import com.simplemobiletools.contacts.extensions.config
|
||||||
|
import com.simplemobiletools.contacts.extensions.getContactPublicUri
|
||||||
import com.simplemobiletools.contacts.helpers.ContactsHelper
|
import com.simplemobiletools.contacts.helpers.ContactsHelper
|
||||||
import com.simplemobiletools.contacts.helpers.SMT_PRIVATE
|
import com.simplemobiletools.contacts.helpers.SMT_PRIVATE
|
||||||
import com.simplemobiletools.contacts.models.Contact
|
import com.simplemobiletools.contacts.models.Contact
|
||||||
@ -98,9 +99,7 @@ class SelectContactActivity : SimpleActivity() {
|
|||||||
} as ArrayList<Contact>
|
} as ArrayList<Contact>
|
||||||
|
|
||||||
val contactSources = config.displayContactSources
|
val contactSources = config.displayContactSources
|
||||||
if (!config.showAllContacts()) {
|
|
||||||
contacts = contacts.filter { contactSources.contains(it.source) } as ArrayList<Contact>
|
contacts = contacts.filter { contactSources.contains(it.source) } as ArrayList<Contact>
|
||||||
}
|
|
||||||
|
|
||||||
Contact.sorting = config.sorting
|
Contact.sorting = config.sorting
|
||||||
Contact.startWithSurname = config.startNameWithSurname
|
Contact.startWithSurname = config.startNameWithSurname
|
||||||
@ -135,8 +134,7 @@ class SelectContactActivity : SimpleActivity() {
|
|||||||
Uri.withAppendedPath(ContactsContract.Data.CONTENT_URI, contactId)
|
Uri.withAppendedPath(ContactsContract.Data.CONTENT_URI, contactId)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val lookupKey = ContactsHelper(this).getContactLookupKey(contact.id.toString())
|
getContactPublicUri(contact)
|
||||||
Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
package com.simplemobiletools.contacts.activities
|
package com.simplemobiletools.contacts.activities
|
||||||
|
|
||||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||||
|
import com.simplemobiletools.contacts.R
|
||||||
|
|
||||||
open class SimpleActivity : BaseSimpleActivity()
|
open class SimpleActivity : BaseSimpleActivity() {
|
||||||
|
override fun getAppIconIDs() = arrayListOf(
|
||||||
|
R.mipmap.ic_launcher_red,
|
||||||
|
R.mipmap.ic_launcher
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun getAppLauncherName() = getString(R.string.app_launcher_name)
|
||||||
|
}
|
||||||
|
@ -49,13 +49,18 @@ class ViewContactActivity : ContactActivity() {
|
|||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
menuInflater.inflate(R.menu.menu_view_contact, menu)
|
menuInflater.inflate(R.menu.menu_view_contact, menu)
|
||||||
|
menu.apply {
|
||||||
|
findItem(R.id.open_with).isVisible = contact?.source != SMT_PRIVATE
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.edit -> editContact(contact!!)
|
R.id.edit -> editContact(contact!!)
|
||||||
R.id.share -> shareContact()
|
R.id.share -> shareContact()
|
||||||
|
R.id.open_with -> openWith()
|
||||||
R.id.delete -> deleteContact()
|
R.id.delete -> deleteContact()
|
||||||
else -> return super.onOptionsItemSelected(item)
|
else -> return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
@ -151,6 +156,14 @@ class ViewContactActivity : ContactActivity() {
|
|||||||
setupContactSource()
|
setupContactSource()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun openWith() {
|
||||||
|
Intent().apply {
|
||||||
|
action = ContactsContract.QuickContact.ACTION_QUICK_CONTACT
|
||||||
|
data = getContactPublicUri(contact!!)
|
||||||
|
startActivity(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupFavorite() {
|
private fun setupFavorite() {
|
||||||
contact_toggle_favorite.apply {
|
contact_toggle_favorite.apply {
|
||||||
beVisible()
|
beVisible()
|
||||||
|
@ -21,7 +21,7 @@ class FilterContactSourcesAdapter(val activity: SimpleActivity, private val cont
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
contactSources.forEachIndexed { index, contactSource ->
|
contactSources.forEachIndexed { index, contactSource ->
|
||||||
if (activity.config.showAllContacts() || displayContactSources.contains(contactSource.name)) {
|
if (displayContactSources.contains(contactSource.name)) {
|
||||||
selectedPositions.add(index)
|
selectedPositions.add(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,9 +19,7 @@ class SelectContactsDialog(val activity: SimpleActivity, initialContacts: ArrayL
|
|||||||
var allContacts = initialContacts
|
var allContacts = initialContacts
|
||||||
if (selectContacts == null) {
|
if (selectContacts == null) {
|
||||||
val contactSources = activity.config.displayContactSources
|
val contactSources = activity.config.displayContactSources
|
||||||
if (!activity.config.showAllContacts()) {
|
|
||||||
allContacts = allContacts.filter { contactSources.contains(it.source) } as ArrayList<Contact>
|
allContacts = allContacts.filter { contactSources.contains(it.source) } as ArrayList<Contact>
|
||||||
}
|
|
||||||
|
|
||||||
initiallySelectedContacts = allContacts.filter { it.starred == 1 } as ArrayList<Contact>
|
initiallySelectedContacts = allContacts.filter { it.starred == 1 } as ArrayList<Contact>
|
||||||
} else {
|
} else {
|
||||||
|
@ -2,6 +2,7 @@ package com.simplemobiletools.contacts.extensions
|
|||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.provider.ContactsContract
|
||||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||||
import com.simplemobiletools.commons.extensions.sharePathIntent
|
import com.simplemobiletools.commons.extensions.sharePathIntent
|
||||||
@ -175,3 +176,8 @@ fun BaseSimpleActivity.removeContactsFromGroup(contacts: ArrayList<Contact>, gro
|
|||||||
dbHelper.removeContactsFromGroup(contacts, groupId)
|
dbHelper.removeContactsFromGroup(contacts, groupId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun BaseSimpleActivity.getContactPublicUri(contact: Contact): Uri {
|
||||||
|
val lookupKey = ContactsHelper(this).getContactLookupKey(contact.id.toString())
|
||||||
|
return Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey)
|
||||||
|
}
|
||||||
|
@ -99,15 +99,11 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
|
|||||||
contacts.sort()
|
contacts.sort()
|
||||||
allContacts = contacts
|
allContacts = contacts
|
||||||
|
|
||||||
val filtered = if (this is GroupsFragment) {
|
val filtered = when {
|
||||||
contacts
|
this is GroupsFragment -> contacts
|
||||||
} else if (this is FavoritesFragment) {
|
this is FavoritesFragment -> contacts.filter { it.starred == 1 } as ArrayList<Contact>
|
||||||
contacts.filter { it.starred == 1 } as ArrayList<Contact>
|
else -> {
|
||||||
} else {
|
|
||||||
val contactSources = config.displayContactSources
|
val contactSources = config.displayContactSources
|
||||||
if (config.showAllContacts()) {
|
|
||||||
contacts
|
|
||||||
} else {
|
|
||||||
contacts.filter { contactSources.contains(it.source) } as ArrayList<Contact>
|
contacts.filter { contactSources.contains(it.source) } as ArrayList<Contact>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,6 @@ class Config(context: Context) : BaseConfig(context) {
|
|||||||
get() = prefs.getStringSet(DISPLAY_CONTACT_SOURCES, hashSetOf("-1"))
|
get() = prefs.getStringSet(DISPLAY_CONTACT_SOURCES, hashSetOf("-1"))
|
||||||
set(displayContactSources) = prefs.edit().remove(DISPLAY_CONTACT_SOURCES).putStringSet(DISPLAY_CONTACT_SOURCES, displayContactSources).apply()
|
set(displayContactSources) = prefs.edit().remove(DISPLAY_CONTACT_SOURCES).putStringSet(DISPLAY_CONTACT_SOURCES, displayContactSources).apply()
|
||||||
|
|
||||||
fun showAllContacts() = displayContactSources.size == 1 && displayContactSources.first() == "-1"
|
|
||||||
|
|
||||||
var showContactThumbnails: Boolean
|
var showContactThumbnails: Boolean
|
||||||
get() = prefs.getBoolean(SHOW_CONTACT_THUMBNAILS, true)
|
get() = prefs.getBoolean(SHOW_CONTACT_THUMBNAILS, true)
|
||||||
set(showContactThumbnails) = prefs.edit().putBoolean(SHOW_CONTACT_THUMBNAILS, showContactThumbnails).apply()
|
set(showContactThumbnails) = prefs.edit().putBoolean(SHOW_CONTACT_THUMBNAILS, showContactThumbnails).apply()
|
||||||
|
@ -93,3 +93,14 @@ const val DEFAULT_ADDRESS_TYPE = CommonDataKinds.StructuredPostal.TYPE_HOME
|
|||||||
const val DEFAULT_EVENT_TYPE = CommonDataKinds.Event.TYPE_BIRTHDAY
|
const val DEFAULT_EVENT_TYPE = CommonDataKinds.Event.TYPE_BIRTHDAY
|
||||||
const val DEFAULT_ORGANIZATION_TYPE = CommonDataKinds.Organization.TYPE_WORK
|
const val DEFAULT_ORGANIZATION_TYPE = CommonDataKinds.Organization.TYPE_WORK
|
||||||
const val DEFAULT_WEBSITE_TYPE = CommonDataKinds.Website.TYPE_HOMEPAGE
|
const val DEFAULT_WEBSITE_TYPE = CommonDataKinds.Website.TYPE_HOMEPAGE
|
||||||
|
|
||||||
|
// some manufacturer contact account types from https://stackoverflow.com/a/44802016/1967672
|
||||||
|
val localAccountTypes = arrayListOf("vnd.sec.contact.phone",
|
||||||
|
"com.htc.android.pcsc",
|
||||||
|
"com.sonyericsson.localcontacts",
|
||||||
|
"com.lge.sync",
|
||||||
|
"com.lge.phone",
|
||||||
|
"vnd.tmobileus.contact.phone",
|
||||||
|
"com.android.huawei.phone",
|
||||||
|
"Local Phone Account"
|
||||||
|
)
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package com.simplemobiletools.contacts.helpers
|
package com.simplemobiletools.contacts.helpers
|
||||||
|
|
||||||
import android.content.ContentProviderOperation
|
import android.accounts.AccountManager
|
||||||
import android.content.ContentProviderResult
|
import android.content.*
|
||||||
import android.content.ContentUris
|
|
||||||
import android.content.ContentValues
|
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
@ -37,7 +35,9 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
val contactsSize = contacts.size()
|
val contactsSize = contacts.size()
|
||||||
var resultContacts = ArrayList<Contact>(contactsSize)
|
var resultContacts = ArrayList<Contact>(contactsSize)
|
||||||
(0 until contactsSize).mapTo(resultContacts) { contacts.valueAt(it) }
|
(0 until contactsSize).mapTo(resultContacts) { contacts.valueAt(it) }
|
||||||
resultContacts = resultContacts.distinctBy { it.contactId } as ArrayList<Contact>
|
resultContacts = resultContacts.distinctBy {
|
||||||
|
it.getHashToCompare()
|
||||||
|
} as ArrayList<Contact>
|
||||||
|
|
||||||
// groups are obtained with contactID, not rawID, so assign them to proper contacts like this
|
// groups are obtained with contactID, not rawID, so assign them to proper contacts like this
|
||||||
val groups = getContactGroups(getStoredGroups())
|
val groups = getContactGroups(getStoredGroups())
|
||||||
@ -90,6 +90,7 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
val websites = ArrayList<String>()
|
val websites = ArrayList<String>()
|
||||||
val contact = Contact(id, prefix, firstName, middleName, surname, suffix, photoUri, number, emails, addresses, events,
|
val contact = Contact(id, prefix, firstName, middleName, surname, suffix, photoUri, number, emails, addresses, events,
|
||||||
accountName, starred, contactId, thumbnailUri, null, notes, groups, organization, websites)
|
accountName, starred, contactId, thumbnailUri, null, notes, groups, organization, websites)
|
||||||
|
|
||||||
contacts.put(id, contact)
|
contacts.put(id, contact)
|
||||||
} while (cursor.moveToNext())
|
} while (cursor.moveToNext())
|
||||||
}
|
}
|
||||||
@ -621,64 +622,34 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
|
|
||||||
fun getContactSources(callback: (ArrayList<ContactSource>) -> Unit) {
|
fun getContactSources(callback: (ArrayList<ContactSource>) -> Unit) {
|
||||||
Thread {
|
Thread {
|
||||||
val sources = LinkedHashSet<ContactSource>()
|
val sources = getDeviceContactSources()
|
||||||
getDeviceContactSources(sources)
|
|
||||||
sources.add(ContactSource(activity.getString(R.string.phone_storage_hidden), SMT_PRIVATE))
|
sources.add(ContactSource(activity.getString(R.string.phone_storage_hidden), SMT_PRIVATE))
|
||||||
callback(ArrayList(sources))
|
callback(ArrayList(sources))
|
||||||
}.start()
|
}.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getDeviceContactSources(sources: LinkedHashSet<ContactSource>) {
|
private fun getDeviceContactSources(): LinkedHashSet<ContactSource> {
|
||||||
|
val sources = LinkedHashSet<ContactSource>()
|
||||||
if (!activity.hasContactPermissions()) {
|
if (!activity.hasContactPermissions()) {
|
||||||
return
|
return sources
|
||||||
}
|
}
|
||||||
|
|
||||||
val uri = ContactsContract.RawContacts.CONTENT_URI
|
val accountManager = AccountManager.get(activity)
|
||||||
val projection = arrayOf(ContactsContract.RawContacts.ACCOUNT_NAME, ContactsContract.RawContacts.ACCOUNT_TYPE)
|
accountManager.accounts.filter { it.name.contains("@") || localAccountTypes.contains(it.type) }.forEach {
|
||||||
|
if (ContentResolver.getIsSyncable(it, ContactsContract.AUTHORITY) == 1) {
|
||||||
var cursor: Cursor? = null
|
val contactSource = ContactSource(it.name, it.type)
|
||||||
try {
|
|
||||||
cursor = activity.contentResolver.query(uri, projection, null, null, null)
|
|
||||||
if (cursor?.moveToFirst() == true) {
|
|
||||||
do {
|
|
||||||
val name = cursor.getStringValue(ContactsContract.RawContacts.ACCOUNT_NAME) ?: continue
|
|
||||||
val type = cursor.getStringValue(ContactsContract.RawContacts.ACCOUNT_TYPE) ?: continue
|
|
||||||
val contactSource = ContactSource(name, type)
|
|
||||||
sources.add(contactSource)
|
sources.add(contactSource)
|
||||||
} while (cursor.moveToNext())
|
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
|
||||||
activity.showErrorToast(e)
|
|
||||||
} finally {
|
|
||||||
cursor?.close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sources.isEmpty() && activity.config.localAccountName.isEmpty() && activity.config.localAccountType.isEmpty()) {
|
if (sources.isEmpty() && activity.config.localAccountName.isEmpty() && activity.config.localAccountType.isEmpty()) {
|
||||||
sources.add(ContactSource("", ""))
|
sources.add(ContactSource("", ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return sources
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getContactSourceType(accountName: String): String {
|
private fun getContactSourceType(accountName: String) = getDeviceContactSources().firstOrNull { it.name == accountName }?.type ?: ""
|
||||||
if (accountName.isEmpty()) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
val uri = ContactsContract.RawContacts.CONTENT_URI
|
|
||||||
val projection = arrayOf(ContactsContract.RawContacts.ACCOUNT_TYPE)
|
|
||||||
val selection = "${ContactsContract.RawContacts.ACCOUNT_NAME} = ?"
|
|
||||||
val selectionArgs = arrayOf(accountName)
|
|
||||||
|
|
||||||
var cursor: Cursor? = null
|
|
||||||
try {
|
|
||||||
cursor = activity.contentResolver.query(uri, projection, selection, selectionArgs, null)
|
|
||||||
if (cursor?.moveToFirst() == true) {
|
|
||||||
return cursor.getStringValue(ContactsContract.RawContacts.ACCOUNT_TYPE)
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
cursor?.close()
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getContactProjection() = arrayOf(
|
private fun getContactProjection() = arrayOf(
|
||||||
ContactsContract.Data.CONTACT_ID,
|
ContactsContract.Data.CONTACT_ID,
|
||||||
@ -1060,6 +1031,7 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// organization
|
// organization
|
||||||
|
if (!contact.organization.isEmpty()) {
|
||||||
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply {
|
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply {
|
||||||
withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
|
withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
|
||||||
withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Organization.CONTENT_ITEM_TYPE)
|
withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Organization.CONTENT_ITEM_TYPE)
|
||||||
@ -1069,6 +1041,7 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
withValue(CommonDataKinds.Organization.TYPE, DEFAULT_ORGANIZATION_TYPE)
|
withValue(CommonDataKinds.Organization.TYPE, DEFAULT_ORGANIZATION_TYPE)
|
||||||
operations.add(build())
|
operations.add(build())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// websites
|
// websites
|
||||||
contact.websites.forEach {
|
contact.websites.forEach {
|
||||||
@ -1246,16 +1219,14 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
activity.dbHelper.deleteContacts(localContacts)
|
activity.dbHelper.deleteContacts(localContacts)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val contactIDs = HashSet<String>()
|
|
||||||
val operations = ArrayList<ContentProviderOperation>()
|
val operations = ArrayList<ContentProviderOperation>()
|
||||||
val selection = "${ContactsContract.Data.CONTACT_ID} = ?"
|
val selection = "${ContactsContract.Data.CONTACT_ID} = ?"
|
||||||
contacts.filter { it.source != SMT_PRIVATE }.forEach {
|
contacts.filter { it.source != SMT_PRIVATE }.forEach {
|
||||||
ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI).apply {
|
ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI).apply {
|
||||||
val selectionArgs = arrayOf(it.contactId.toString())
|
val selectionArgs = arrayOf(it.contactId.toString())
|
||||||
withSelection(selection, selectionArgs)
|
withSelection(selection, selectionArgs)
|
||||||
operations.add(this.build())
|
operations.add(build())
|
||||||
}
|
}
|
||||||
contactIDs.add(it.id.toString())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
activity.contentResolver.applyBatch(ContactsContract.AUTHORITY, operations)
|
activity.contentResolver.applyBatch(ContactsContract.AUTHORITY, operations)
|
||||||
|
@ -119,6 +119,10 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
|
|||||||
fun deleteContact(id: Int) = deleteContacts(arrayOf(id.toString()))
|
fun deleteContact(id: Int) = deleteContacts(arrayOf(id.toString()))
|
||||||
|
|
||||||
fun deleteContacts(ids: Array<String>) {
|
fun deleteContacts(ids: Array<String>) {
|
||||||
|
if (ids.isEmpty()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val args = TextUtils.join(", ", ids)
|
val args = TextUtils.join(", ", ids)
|
||||||
val selection = "$CONTACTS_TABLE_NAME.$COL_ID IN ($args)"
|
val selection = "$CONTACTS_TABLE_NAME.$COL_ID IN ($args)"
|
||||||
mDb.delete(CONTACTS_TABLE_NAME, selection, null)
|
mDb.delete(CONTACTS_TABLE_NAME, selection, null)
|
||||||
|
@ -12,6 +12,7 @@ data class Contact(val id: Int, var prefix: String, var firstName: String, var m
|
|||||||
companion object {
|
companion object {
|
||||||
var sorting = 0
|
var sorting = 0
|
||||||
var startWithSurname = false
|
var startWithSurname = false
|
||||||
|
val pattern = "\\D+".toRegex()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun compareTo(other: Contact): Int {
|
override fun compareTo(other: Contact): Int {
|
||||||
@ -81,4 +82,10 @@ data class Contact(val id: Int, var prefix: String, var firstName: String, var m
|
|||||||
fullName
|
fullName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getHashToCompare(): Int {
|
||||||
|
val newPhoneNumbers = ArrayList<PhoneNumber>()
|
||||||
|
phoneNumbers.mapTo(newPhoneNumbers, { PhoneNumber(it.value.replace(pattern, ""), 0) })
|
||||||
|
return copy(id = 0, phoneNumbers = newPhoneNumbers).hashCode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -341,7 +341,7 @@
|
|||||||
android:layout_marginTop="@dimen/normal_margin"
|
android:layout_marginTop="@dimen/normal_margin"
|
||||||
android:layout_toRightOf="@+id/contact_notes_image"
|
android:layout_toRightOf="@+id/contact_notes_image"
|
||||||
android:hint="@string/notes"
|
android:hint="@string/notes"
|
||||||
android:inputType="textCapWords|textMultiLine"
|
android:inputType="textCapSentences|textMultiLine"
|
||||||
android:textCursorDrawable="@null"
|
android:textCursorDrawable="@null"
|
||||||
android:textSize="@dimen/bigger_text_size"/>
|
android:textSize="@dimen/bigger_text_size"/>
|
||||||
|
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
android:icon="@drawable/ic_share"
|
android:icon="@drawable/ic_share"
|
||||||
android:title="@string/share"
|
android:title="@string/share"
|
||||||
app:showAsAction="ifRoom"/>
|
app:showAsAction="ifRoom"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/open_with"
|
||||||
|
android:title="@string/open_with"
|
||||||
|
app:showAsAction="never"/>
|
||||||
<item
|
<item
|
||||||
android:id="@+id/delete"
|
android:id="@+id/delete"
|
||||||
android:icon="@drawable/ic_delete"
|
android:icon="@drawable/ic_delete"
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
android:icon="@drawable/ic_share"
|
android:icon="@drawable/ic_share"
|
||||||
android:title="@string/share"
|
android:title="@string/share"
|
||||||
app:showAsAction="ifRoom"/>
|
app:showAsAction="ifRoom"/>
|
||||||
|
<item
|
||||||
|
android:id="@+id/open_with"
|
||||||
|
android:title="@string/open_with"
|
||||||
|
app:showAsAction="never"/>
|
||||||
<item
|
<item
|
||||||
android:id="@+id/delete"
|
android:id="@+id/delete"
|
||||||
android:icon="@drawable/ic_delete"
|
android:icon="@drawable/ic_delete"
|
||||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.7 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_red.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 3.4 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_red.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 6.0 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_red.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 6.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_red.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
@ -9,10 +9,10 @@
|
|||||||
<string name="company">Organização</string>
|
<string name="company">Organização</string>
|
||||||
<string name="job_position">Cargo</string>
|
<string name="job_position">Cargo</string>
|
||||||
<string name="website">Site</string>
|
<string name="website">Site</string>
|
||||||
<string name="send_sms_to_contacts">Send SMS to contacts</string>
|
<string name="send_sms_to_contacts">Enviar SMS aos contactos</string>
|
||||||
<string name="send_email_to_contacts">Send email to contacts</string>
|
<string name="send_email_to_contacts">Enviar e-mail aos contactos</string>
|
||||||
<string name="send_sms_to_group">Send SMS to group</string>
|
<string name="send_sms_to_group">Enviar SMS para o grupo</string>
|
||||||
<string name="send_email_to_group">Send email to group</string>
|
<string name="send_email_to_group">Enviar e-mail para o grupo</string>
|
||||||
|
|
||||||
<string name="new_contact">Novo contacto</string>
|
<string name="new_contact">Novo contacto</string>
|
||||||
<string name="edit_contact">Editar contacto</string>
|
<string name="edit_contact">Editar contacto</string>
|
||||||
@ -73,7 +73,7 @@
|
|||||||
<string name="add_favorites">Adicionar favoritos</string>
|
<string name="add_favorites">Adicionar favoritos</string>
|
||||||
<string name="add_to_favorites">Adicionar aos favoritos</string>
|
<string name="add_to_favorites">Adicionar aos favoritos</string>
|
||||||
<string name="remove_from_favorites">Remover dos favoritos</string>
|
<string name="remove_from_favorites">Remover dos favoritos</string>
|
||||||
<string name="must_be_at_edit">You must be at the Edit screen to modify a contact</string>
|
<string name="must_be_at_edit">Tem que estar no ecrã de edição para alterar um contacto</string>
|
||||||
|
|
||||||
<!-- Search -->
|
<!-- Search -->
|
||||||
<string name="search_contacts">Pesquisar contactos</string>
|
<string name="search_contacts">Pesquisar contactos</string>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.2.40'
|
ext.kotlin_version = '1.2.41'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
|