15
CHANGELOG.md
@ -1,6 +1,21 @@
|
|||||||
Changelog
|
Changelog
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
Version 4.0.1 *(2018-05-09)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Fixed a glitch happening at updating from old app version to 4.x
|
||||||
|
|
||||||
|
Version 4.0.0 *(2018-05-09)*
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* Allow changing app icon color
|
||||||
|
* Add a toggle for trying to filter out duplicate contacts, enabled by default
|
||||||
|
* Fix some contacts not being visible
|
||||||
|
* Allow opening contacts with third party apps
|
||||||
|
* Couple misc fixes related to contacts syncing via CardDAV
|
||||||
|
* Allow moving contacts in a different contact source at the Edit screen
|
||||||
|
|
||||||
Version 3.5.3 *(2018-04-18)*
|
Version 3.5.3 *(2018-04-18)*
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ android {
|
|||||||
applicationId "com.simplemobiletools.contacts"
|
applicationId "com.simplemobiletools.contacts"
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 27
|
targetSdkVersion 27
|
||||||
versionCode 19
|
versionCode 21
|
||||||
versionName "3.5.3"
|
versionName "4.0.1"
|
||||||
setProperty("archivesBaseName", "contacts")
|
setProperty("archivesBaseName", "contacts")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ ext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.simplemobiletools:commons:3.20.6'
|
implementation 'com.simplemobiletools:commons:4.0.0'
|
||||||
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'
|
||||||
|
|
||||||
|
@ -210,6 +210,228 @@
|
|||||||
android:icon="@mipmap/ic_launcher_red"
|
android:icon="@mipmap/ic_launcher_red"
|
||||||
android:roundIcon="@mipmap/ic_launcher_red"
|
android:roundIcon="@mipmap/ic_launcher_red"
|
||||||
android:targetActivity=".activities.SplashActivity">
|
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.Pink"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_pink"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_pink"
|
||||||
|
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.Purple"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_purple"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_purple"
|
||||||
|
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.Deep_purple"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_deep_purple"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_deep_purple"
|
||||||
|
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.Indigo"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_indigo"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_indigo"
|
||||||
|
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.Blue"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_blue"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_blue"
|
||||||
|
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.Light_blue"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_light_blue"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_light_blue"
|
||||||
|
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.Cyan"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_cyan"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_cyan"
|
||||||
|
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.Teal"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_teal"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_teal"
|
||||||
|
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.Green"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_green"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_green"
|
||||||
|
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.Light_green"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_light_green"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_light_green"
|
||||||
|
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.Lime"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_lime"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_lime"
|
||||||
|
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.Yellow"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_yellow"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_yellow"
|
||||||
|
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.Amber"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_amber"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_amber"
|
||||||
|
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.Deep_orange"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_deep_orange"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_deep_orange"
|
||||||
|
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.Brown"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_brown"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_brown"
|
||||||
|
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.Blue_grey"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_blue_grey"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_blue_grey"
|
||||||
|
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.Grey_black"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_launcher_grey_black"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_grey_black"
|
||||||
|
android:targetActivity=".activities.SplashActivity">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
@ -52,6 +52,7 @@ class EditContactActivity : ContactActivity() {
|
|||||||
private var lastPhotoIntentUri: Uri? = null
|
private var lastPhotoIntentUri: Uri? = null
|
||||||
private var isSaving = false
|
private var isSaving = false
|
||||||
private var isThirdPartyIntent = false
|
private var isThirdPartyIntent = false
|
||||||
|
private var originalContactSource = ""
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@ -212,6 +213,7 @@ class EditContactActivity : ContactActivity() {
|
|||||||
contact_events_add_new.setOnClickListener { addNewEventField() }
|
contact_events_add_new.setOnClickListener { addNewEventField() }
|
||||||
contact_websites_add_new.setOnClickListener { addNewWebsiteField() }
|
contact_websites_add_new.setOnClickListener { addNewWebsiteField() }
|
||||||
contact_groups_add_new.setOnClickListener { showSelectGroupsDialog() }
|
contact_groups_add_new.setOnClickListener { showSelectGroupsDialog() }
|
||||||
|
contact_source.setOnClickListener { showSelectContactSourceDialog() }
|
||||||
|
|
||||||
setupFieldVisibility()
|
setupFieldVisibility()
|
||||||
|
|
||||||
@ -504,21 +506,16 @@ class EditContactActivity : ContactActivity() {
|
|||||||
|
|
||||||
private fun setupContactSource() {
|
private fun setupContactSource() {
|
||||||
contact_source.text = getPublicContactSource(contact!!.source)
|
contact_source.text = getPublicContactSource(contact!!.source)
|
||||||
|
originalContactSource = contact!!.source
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupNewContact() {
|
private fun setupNewContact() {
|
||||||
supportActionBar?.title = resources.getString(R.string.new_contact)
|
supportActionBar?.title = resources.getString(R.string.new_contact)
|
||||||
val contactSource = if (hasContactPermissions()) config.lastUsedContactSource else SMT_PRIVATE
|
originalContactSource = if (hasContactPermissions()) config.lastUsedContactSource else SMT_PRIVATE
|
||||||
val organization = Organization("", "")
|
val organization = Organization("", "")
|
||||||
contact = Contact(0, "", "", "", "", "", "", ArrayList(), ArrayList(), ArrayList(), ArrayList(), contactSource, 0, 0, "", null, "",
|
contact = Contact(0, "", "", "", "", "", "", ArrayList(), ArrayList(), ArrayList(), ArrayList(), originalContactSource, 0, 0, "", null, "",
|
||||||
ArrayList(), organization, ArrayList())
|
ArrayList(), organization, ArrayList())
|
||||||
contact_source.text = getPublicContactSource(contact!!.source)
|
contact_source.text = getPublicContactSource(contact!!.source)
|
||||||
contact_source.setOnClickListener {
|
|
||||||
showContactSourcePicker(contact!!.source) {
|
|
||||||
contact!!.source = if (it == getString(R.string.phone_storage_hidden)) SMT_PRIVATE else it
|
|
||||||
contact_source.text = getPublicContactSource(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupTypePickers() {
|
private fun setupTypePickers() {
|
||||||
@ -708,6 +705,13 @@ class EditContactActivity : ContactActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showSelectContactSourceDialog() {
|
||||||
|
showContactSourcePicker(contact!!.source) {
|
||||||
|
contact!!.source = if (it == getString(R.string.phone_storage_hidden)) SMT_PRIVATE else it
|
||||||
|
contact_source.text = getPublicContactSource(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun saveContact() {
|
private fun saveContact() {
|
||||||
if (isSaving || contact == null) {
|
if (isSaving || contact == null) {
|
||||||
return
|
return
|
||||||
@ -726,7 +730,6 @@ class EditContactActivity : ContactActivity() {
|
|||||||
emails = getFilledEmails()
|
emails = getFilledEmails()
|
||||||
addresses = getFilledAddresses()
|
addresses = getFilledAddresses()
|
||||||
events = getFilledEvents()
|
events = getFilledEvents()
|
||||||
source = contact!!.source
|
|
||||||
starred = if (isContactStarred()) 1 else 0
|
starred = if (isContactStarred()) 1 else 0
|
||||||
notes = contact_notes.value
|
notes = contact_notes.value
|
||||||
websites = getFilledWebsites()
|
websites = getFilledWebsites()
|
||||||
@ -737,12 +740,14 @@ class EditContactActivity : ContactActivity() {
|
|||||||
|
|
||||||
Thread {
|
Thread {
|
||||||
config.lastUsedContactSource = source
|
config.lastUsedContactSource = source
|
||||||
if (id == 0) {
|
when {
|
||||||
insertNewContact()
|
id == 0 -> insertNewContact(false)
|
||||||
} else {
|
originalContactSource != source -> insertNewContact(true)
|
||||||
|
else -> {
|
||||||
val photoUpdateStatus = getPhotoUpdateStatus(oldPhotoUri, photoUri)
|
val photoUpdateStatus = getPhotoUpdateStatus(oldPhotoUri, photoUri)
|
||||||
updateContact(photoUpdateStatus)
|
updateContact(photoUpdateStatus)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}.start()
|
}.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -821,10 +826,17 @@ class EditContactActivity : ContactActivity() {
|
|||||||
return websites
|
return websites
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun insertNewContact() {
|
private fun insertNewContact(deleteCurrentContact: Boolean) {
|
||||||
isSaving = true
|
isSaving = true
|
||||||
|
if (!deleteCurrentContact) {
|
||||||
toast(R.string.inserting)
|
toast(R.string.inserting)
|
||||||
|
}
|
||||||
|
|
||||||
if (ContactsHelper(this@EditContactActivity).insertContact(contact!!)) {
|
if (ContactsHelper(this@EditContactActivity).insertContact(contact!!)) {
|
||||||
|
if (deleteCurrentContact) {
|
||||||
|
contact!!.source = originalContactSource
|
||||||
|
ContactsHelper(this).deleteContact(contact!!)
|
||||||
|
}
|
||||||
finish()
|
finish()
|
||||||
} else {
|
} else {
|
||||||
toast(R.string.unknown_error_occurred)
|
toast(R.string.unknown_error_occurred)
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
package com.simplemobiletools.contacts.activities
|
package com.simplemobiletools.contacts.activities
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.app.SearchManager
|
import android.app.SearchManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.support.v4.app.ActivityCompat
|
||||||
|
import android.support.v4.content.ContextCompat
|
||||||
import android.support.v4.view.MenuItemCompat
|
import android.support.v4.view.MenuItemCompat
|
||||||
import android.support.v4.view.ViewPager
|
import android.support.v4.view.ViewPager
|
||||||
import android.support.v7.widget.SearchView
|
import android.support.v7.widget.SearchView
|
||||||
@ -48,11 +52,12 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
|||||||
private var storedShowContactThumbnails = false
|
private var storedShowContactThumbnails = false
|
||||||
private var storedShowPhoneNumbers = false
|
private var storedShowPhoneNumbers = false
|
||||||
private var storedStartNameWithSurname = false
|
private var storedStartNameWithSurname = false
|
||||||
|
private var storedFilterDuplicates = true
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
appLaunched()
|
appLaunched(BuildConfig.APPLICATION_ID)
|
||||||
setupTabColors()
|
setupTabColors()
|
||||||
|
|
||||||
// just get a reference to the database to make sure it is created properly
|
// just get a reference to the database to make sure it is created properly
|
||||||
@ -62,6 +67,12 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
|||||||
werePermissionsHandled = true
|
werePermissionsHandled = true
|
||||||
if (it) {
|
if (it) {
|
||||||
handlePermission(PERMISSION_WRITE_CONTACTS) {
|
handlePermission(PERMISSION_WRITE_CONTACTS) {
|
||||||
|
// workaround for upgrading from version 3.x to 4.x as we added a new permission from an already granted permissions group
|
||||||
|
val hasGetAccountsPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.GET_ACCOUNTS) == PackageManager.PERMISSION_GRANTED
|
||||||
|
if (!hasGetAccountsPermission) {
|
||||||
|
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.GET_ACCOUNTS), 34)
|
||||||
|
}
|
||||||
|
|
||||||
storeLocalAccountData()
|
storeLocalAccountData()
|
||||||
initFragments()
|
initFragments()
|
||||||
}
|
}
|
||||||
@ -118,6 +129,10 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
|||||||
favorites_fragment?.startNameWithSurnameChanged(configStartNameWithSurname)
|
favorites_fragment?.startNameWithSurnameChanged(configStartNameWithSurname)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (storedFilterDuplicates != config.filterDuplicates) {
|
||||||
|
refreshContacts(ALL_TABS_MASK)
|
||||||
|
}
|
||||||
|
|
||||||
if (werePermissionsHandled && !isFirstResume) {
|
if (werePermissionsHandled && !isFirstResume) {
|
||||||
if (viewpager.adapter == null) {
|
if (viewpager.adapter == null) {
|
||||||
initFragments()
|
initFragments()
|
||||||
@ -175,6 +190,7 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
|||||||
storedShowContactThumbnails = showContactThumbnails
|
storedShowContactThumbnails = showContactThumbnails
|
||||||
storedShowPhoneNumbers = showPhoneNumbers
|
storedShowPhoneNumbers = showPhoneNumbers
|
||||||
storedStartNameWithSurname = startNameWithSurname
|
storedStartNameWithSurname = startNameWithSurname
|
||||||
|
storedFilterDuplicates = filterDuplicates
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ import android.os.Bundle
|
|||||||
import android.provider.ContactsContract
|
import android.provider.ContactsContract
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import com.simplemobiletools.commons.extensions.appLaunched
|
|
||||||
import com.simplemobiletools.commons.extensions.baseConfig
|
import com.simplemobiletools.commons.extensions.baseConfig
|
||||||
import com.simplemobiletools.commons.extensions.isActivityDestroyed
|
import com.simplemobiletools.commons.extensions.isActivityDestroyed
|
||||||
import com.simplemobiletools.commons.extensions.toast
|
import com.simplemobiletools.commons.extensions.toast
|
||||||
@ -18,6 +17,7 @@ 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.extensions.getContactPublicUri
|
||||||
|
import com.simplemobiletools.contacts.extensions.getVisibleContactSources
|
||||||
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
|
||||||
@ -29,7 +29,6 @@ class SelectContactActivity : SimpleActivity() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.layout_select_contact)
|
setContentView(R.layout.layout_select_contact)
|
||||||
appLaunched()
|
|
||||||
|
|
||||||
handlePermission(PERMISSION_READ_CONTACTS) {
|
handlePermission(PERMISSION_READ_CONTACTS) {
|
||||||
if (it) {
|
if (it) {
|
||||||
@ -98,7 +97,7 @@ class SelectContactActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
} as ArrayList<Contact>
|
} as ArrayList<Contact>
|
||||||
|
|
||||||
val contactSources = config.displayContactSources
|
val contactSources = getVisibleContactSources()
|
||||||
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
|
||||||
|
@ -31,6 +31,7 @@ class SettingsActivity : SimpleActivity() {
|
|||||||
setupShowContactThumbnails()
|
setupShowContactThumbnails()
|
||||||
setupShowPhoneNumbers()
|
setupShowPhoneNumbers()
|
||||||
setupStartNameWithSurname()
|
setupStartNameWithSurname()
|
||||||
|
setupFilterDuplicates()
|
||||||
setupOnContactClick()
|
setupOnContactClick()
|
||||||
updateTextColors(settings_holder)
|
updateTextColors(settings_holder)
|
||||||
}
|
}
|
||||||
@ -97,6 +98,14 @@ class SettingsActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupFilterDuplicates() {
|
||||||
|
settings_filter_duplicates.isChecked = config.filterDuplicates
|
||||||
|
settings_filter_duplicates_holder.setOnClickListener {
|
||||||
|
settings_filter_duplicates.toggle()
|
||||||
|
config.filterDuplicates = settings_filter_duplicates.isChecked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupOnContactClick() {
|
private fun setupOnContactClick() {
|
||||||
settings_on_contact_click.text = getOnContactClickText()
|
settings_on_contact_click.text = getOnContactClickText()
|
||||||
settings_on_contact_click_holder.setOnClickListener {
|
settings_on_contact_click_holder.setOnClickListener {
|
||||||
|
@ -6,7 +6,24 @@ import com.simplemobiletools.contacts.R
|
|||||||
open class SimpleActivity : BaseSimpleActivity() {
|
open class SimpleActivity : BaseSimpleActivity() {
|
||||||
override fun getAppIconIDs() = arrayListOf(
|
override fun getAppIconIDs() = arrayListOf(
|
||||||
R.mipmap.ic_launcher_red,
|
R.mipmap.ic_launcher_red,
|
||||||
R.mipmap.ic_launcher
|
R.mipmap.ic_launcher_pink,
|
||||||
|
R.mipmap.ic_launcher_purple,
|
||||||
|
R.mipmap.ic_launcher_deep_purple,
|
||||||
|
R.mipmap.ic_launcher_indigo,
|
||||||
|
R.mipmap.ic_launcher_blue,
|
||||||
|
R.mipmap.ic_launcher_light_blue,
|
||||||
|
R.mipmap.ic_launcher_cyan,
|
||||||
|
R.mipmap.ic_launcher_teal,
|
||||||
|
R.mipmap.ic_launcher_green,
|
||||||
|
R.mipmap.ic_launcher_light_green,
|
||||||
|
R.mipmap.ic_launcher_lime,
|
||||||
|
R.mipmap.ic_launcher_yellow,
|
||||||
|
R.mipmap.ic_launcher_amber,
|
||||||
|
R.mipmap.ic_launcher,
|
||||||
|
R.mipmap.ic_launcher_deep_orange,
|
||||||
|
R.mipmap.ic_launcher_brown,
|
||||||
|
R.mipmap.ic_launcher_blue_grey,
|
||||||
|
R.mipmap.ic_launcher_grey_black
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun getAppLauncherName() = getString(R.string.app_launcher_name)
|
override fun getAppLauncherName() = getString(R.string.app_launcher_name)
|
||||||
|
@ -125,6 +125,7 @@ class ContactsAdapter(activity: SimpleActivity, var contactItems: ArrayList<Cont
|
|||||||
textToHighlight = highlightText
|
textToHighlight = highlightText
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
fastScroller?.measureRecyclerView()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun editContact() {
|
private fun editContact() {
|
||||||
|
@ -14,7 +14,7 @@ import com.simplemobiletools.contacts.models.ContactSource
|
|||||||
import kotlinx.android.synthetic.main.item_filter_contact_source.view.*
|
import kotlinx.android.synthetic.main.item_filter_contact_source.view.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class FilterContactSourcesAdapter(val activity: SimpleActivity, private val contactSources: List<ContactSource>, private val displayContactSources: Set<String>) :
|
class FilterContactSourcesAdapter(val activity: SimpleActivity, private val contactSources: List<ContactSource>, private val displayContactSources: ArrayList<String>) :
|
||||||
RecyclerView.Adapter<FilterContactSourcesAdapter.ViewHolder>() {
|
RecyclerView.Adapter<FilterContactSourcesAdapter.ViewHolder>() {
|
||||||
private val itemViews = SparseArray<View>()
|
private val itemViews = SparseArray<View>()
|
||||||
private val selectedPositions = HashSet<Int>()
|
private val selectedPositions = HashSet<Int>()
|
||||||
|
@ -77,6 +77,7 @@ class GroupsAdapter(activity: SimpleActivity, var groups: ArrayList<Group>, val
|
|||||||
groups = newItems
|
groups = newItems
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
finishActMode()
|
finishActMode()
|
||||||
|
fastScroller?.measureRecyclerView()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun editGroup() {
|
private fun editGroup() {
|
||||||
|
@ -119,7 +119,9 @@ class SelectContactsAdapter(val activity: SimpleActivity, val contacts: List<Con
|
|||||||
.error(contactDrawable)
|
.error(contactDrawable)
|
||||||
.centerCrop()
|
.centerCrop()
|
||||||
|
|
||||||
|
if (activity.isActivityDestroyed()) {
|
||||||
Glide.with(activity).load(contact.photoUri).transition(DrawableTransitionOptions.withCrossFade()).apply(options).into(contact_tmb)
|
Glide.with(activity).load(contact.photoUri).transition(DrawableTransitionOptions.withCrossFade()).apply(options).into(contact_tmb)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
contact_tmb.setImageDrawable(contactDrawable)
|
contact_tmb.setImageDrawable(contactDrawable)
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import com.simplemobiletools.commons.extensions.*
|
|||||||
import com.simplemobiletools.contacts.R
|
import com.simplemobiletools.contacts.R
|
||||||
import com.simplemobiletools.contacts.activities.SimpleActivity
|
import com.simplemobiletools.contacts.activities.SimpleActivity
|
||||||
import com.simplemobiletools.contacts.adapters.FilterContactSourcesAdapter
|
import com.simplemobiletools.contacts.adapters.FilterContactSourcesAdapter
|
||||||
import com.simplemobiletools.contacts.extensions.config
|
import com.simplemobiletools.contacts.extensions.getVisibleContactSources
|
||||||
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.ContactSource
|
import com.simplemobiletools.contacts.models.ContactSource
|
||||||
@ -25,7 +25,7 @@ class ExportContactsDialog(val activity: SimpleActivity, val path: String, priva
|
|||||||
ContactsHelper(activity).getContactSources {
|
ContactsHelper(activity).getContactSources {
|
||||||
it.mapTo(contactSources, { it.copy() })
|
it.mapTo(contactSources, { it.copy() })
|
||||||
activity.runOnUiThread {
|
activity.runOnUiThread {
|
||||||
export_contacts_list.adapter = FilterContactSourcesAdapter(activity, it, activity.config.displayContactSources)
|
export_contacts_list.adapter = FilterContactSourcesAdapter(activity, it, activity.getVisibleContactSources())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import com.simplemobiletools.contacts.R
|
|||||||
import com.simplemobiletools.contacts.activities.SimpleActivity
|
import com.simplemobiletools.contacts.activities.SimpleActivity
|
||||||
import com.simplemobiletools.contacts.adapters.FilterContactSourcesAdapter
|
import com.simplemobiletools.contacts.adapters.FilterContactSourcesAdapter
|
||||||
import com.simplemobiletools.contacts.extensions.config
|
import com.simplemobiletools.contacts.extensions.config
|
||||||
|
import com.simplemobiletools.contacts.extensions.getVisibleContactSources
|
||||||
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.ContactSource
|
import com.simplemobiletools.contacts.models.ContactSource
|
||||||
@ -24,7 +25,7 @@ class FilterContactSourcesDialog(val activity: SimpleActivity, private val callb
|
|||||||
}
|
}
|
||||||
|
|
||||||
it.mapTo(contactSources, { it.copy() })
|
it.mapTo(contactSources, { it.copy() })
|
||||||
val selectedSources = activity.config.displayContactSources
|
val selectedSources = activity.getVisibleContactSources()
|
||||||
activity.runOnUiThread {
|
activity.runOnUiThread {
|
||||||
view.filter_contact_sources_list.adapter = FilterContactSourcesAdapter(activity, it, selectedSources)
|
view.filter_contact_sources_list.adapter = FilterContactSourcesAdapter(activity, it, selectedSources)
|
||||||
|
|
||||||
@ -40,13 +41,20 @@ class FilterContactSourcesDialog(val activity: SimpleActivity, private val callb
|
|||||||
|
|
||||||
private fun confirmEventTypes() {
|
private fun confirmEventTypes() {
|
||||||
val selectedIndexes = (view.filter_contact_sources_list.adapter as FilterContactSourcesAdapter).getSelectedItemsSet()
|
val selectedIndexes = (view.filter_contact_sources_list.adapter as FilterContactSourcesAdapter).getSelectedItemsSet()
|
||||||
val selectedContactSources = HashSet<String>()
|
val ignoredIndexes = ArrayList<Int>()
|
||||||
selectedIndexes.forEach {
|
for (i in 0 until contactSources.size) {
|
||||||
selectedContactSources.add(if (contactSources[it].type == SMT_PRIVATE) SMT_PRIVATE else contactSources[it].name)
|
if (!selectedIndexes.contains(i)) {
|
||||||
|
ignoredIndexes.add(i)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activity.config.displayContactSources != selectedContactSources) {
|
val ignoredContactSources = HashSet<String>()
|
||||||
activity.config.displayContactSources = selectedContactSources
|
ignoredIndexes.forEach {
|
||||||
|
ignoredContactSources.add(if (contactSources[it].type == SMT_PRIVATE) SMT_PRIVATE else contactSources[it].name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activity.getVisibleContactSources() != ignoredContactSources) {
|
||||||
|
activity.config.ignoredContactSources = ignoredContactSources
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
dialog?.dismiss()
|
dialog?.dismiss()
|
||||||
|
@ -7,6 +7,7 @@ import com.simplemobiletools.contacts.R
|
|||||||
import com.simplemobiletools.contacts.activities.SimpleActivity
|
import com.simplemobiletools.contacts.activities.SimpleActivity
|
||||||
import com.simplemobiletools.contacts.adapters.SelectContactsAdapter
|
import com.simplemobiletools.contacts.adapters.SelectContactsAdapter
|
||||||
import com.simplemobiletools.contacts.extensions.config
|
import com.simplemobiletools.contacts.extensions.config
|
||||||
|
import com.simplemobiletools.contacts.extensions.getVisibleContactSources
|
||||||
import com.simplemobiletools.contacts.models.Contact
|
import com.simplemobiletools.contacts.models.Contact
|
||||||
import kotlinx.android.synthetic.main.layout_select_contact.view.*
|
import kotlinx.android.synthetic.main.layout_select_contact.view.*
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ class SelectContactsDialog(val activity: SimpleActivity, initialContacts: ArrayL
|
|||||||
init {
|
init {
|
||||||
var allContacts = initialContacts
|
var allContacts = initialContacts
|
||||||
if (selectContacts == null) {
|
if (selectContacts == null) {
|
||||||
val contactSources = activity.config.displayContactSources
|
val contactSources = activity.getVisibleContactSources()
|
||||||
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>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.simplemobiletools.contacts.extensions
|
package com.simplemobiletools.contacts.extensions
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.provider.ContactsContract
|
import android.provider.ContactsContract
|
||||||
@ -17,6 +18,7 @@ import com.simplemobiletools.contacts.helpers.ContactsHelper
|
|||||||
import com.simplemobiletools.contacts.helpers.SMT_PRIVATE
|
import com.simplemobiletools.contacts.helpers.SMT_PRIVATE
|
||||||
import com.simplemobiletools.contacts.helpers.VcfExporter
|
import com.simplemobiletools.contacts.helpers.VcfExporter
|
||||||
import com.simplemobiletools.contacts.models.Contact
|
import com.simplemobiletools.contacts.models.Contact
|
||||||
|
import com.simplemobiletools.contacts.models.ContactSource
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
fun SimpleActivity.startCallIntent(recipient: String) {
|
fun SimpleActivity.startCallIntent(recipient: String) {
|
||||||
@ -181,3 +183,11 @@ fun BaseSimpleActivity.getContactPublicUri(contact: Contact): Uri {
|
|||||||
val lookupKey = ContactsHelper(this).getContactLookupKey(contact.id.toString())
|
val lookupKey = ContactsHelper(this).getContactLookupKey(contact.id.toString())
|
||||||
return Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey)
|
return Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Activity.getVisibleContactSources(): ArrayList<String> {
|
||||||
|
val sources = ContactsHelper(this).getDeviceContactSources()
|
||||||
|
sources.add(ContactSource(getString(R.string.phone_storage_hidden), SMT_PRIVATE))
|
||||||
|
val sourceNames = ArrayList(sources).map { if (it.type == SMT_PRIVATE) SMT_PRIVATE else it.name }.toMutableList() as ArrayList<String>
|
||||||
|
sourceNames.removeAll(config.ignoredContactSources)
|
||||||
|
return sourceNames
|
||||||
|
}
|
||||||
|
@ -15,10 +15,7 @@ import com.simplemobiletools.contacts.activities.MainActivity
|
|||||||
import com.simplemobiletools.contacts.activities.SimpleActivity
|
import com.simplemobiletools.contacts.activities.SimpleActivity
|
||||||
import com.simplemobiletools.contacts.adapters.ContactsAdapter
|
import com.simplemobiletools.contacts.adapters.ContactsAdapter
|
||||||
import com.simplemobiletools.contacts.adapters.GroupsAdapter
|
import com.simplemobiletools.contacts.adapters.GroupsAdapter
|
||||||
import com.simplemobiletools.contacts.extensions.config
|
import com.simplemobiletools.contacts.extensions.*
|
||||||
import com.simplemobiletools.contacts.extensions.editContact
|
|
||||||
import com.simplemobiletools.contacts.extensions.tryStartCall
|
|
||||||
import com.simplemobiletools.contacts.extensions.viewContact
|
|
||||||
import com.simplemobiletools.contacts.helpers.*
|
import com.simplemobiletools.contacts.helpers.*
|
||||||
import com.simplemobiletools.contacts.models.Contact
|
import com.simplemobiletools.contacts.models.Contact
|
||||||
import com.simplemobiletools.contacts.models.Group
|
import com.simplemobiletools.contacts.models.Group
|
||||||
@ -103,7 +100,7 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
|
|||||||
this is GroupsFragment -> contacts
|
this is GroupsFragment -> contacts
|
||||||
this is FavoritesFragment -> contacts.filter { it.starred == 1 } as ArrayList<Contact>
|
this is FavoritesFragment -> contacts.filter { it.starred == 1 } as ArrayList<Contact>
|
||||||
else -> {
|
else -> {
|
||||||
val contactSources = config.displayContactSources
|
val contactSources = activity!!.getVisibleContactSources()
|
||||||
contacts.filter { contactSources.contains(it.source) } as ArrayList<Contact>
|
contacts.filter { contactSources.contains(it.source) } as ArrayList<Contact>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,9 @@ class Config(context: Context) : BaseConfig(context) {
|
|||||||
fun newInstance(context: Context) = Config(context)
|
fun newInstance(context: Context) = Config(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
var displayContactSources: Set<String>
|
var ignoredContactSources: HashSet<String>
|
||||||
get() = prefs.getStringSet(DISPLAY_CONTACT_SOURCES, hashSetOf("-1"))
|
get() = prefs.getStringSet(IGNORED_CONTACT_SOURCES, hashSetOf(".")) as HashSet
|
||||||
set(displayContactSources) = prefs.edit().remove(DISPLAY_CONTACT_SOURCES).putStringSet(DISPLAY_CONTACT_SOURCES, displayContactSources).apply()
|
set(ignoreContactSources) = prefs.edit().remove(IGNORED_CONTACT_SOURCES).putStringSet(IGNORED_CONTACT_SOURCES, ignoreContactSources).apply()
|
||||||
|
|
||||||
var showContactThumbnails: Boolean
|
var showContactThumbnails: Boolean
|
||||||
get() = prefs.getBoolean(SHOW_CONTACT_THUMBNAILS, true)
|
get() = prefs.getBoolean(SHOW_CONTACT_THUMBNAILS, true)
|
||||||
@ -44,4 +44,8 @@ class Config(context: Context) : BaseConfig(context) {
|
|||||||
get() = prefs.getInt(SHOW_CONTACT_FIELDS, SHOW_FIRST_NAME_FIELD or SHOW_SURNAME_FIELD or SHOW_PHONE_NUMBERS_FIELD or SHOW_EMAILS_FIELD or
|
get() = prefs.getInt(SHOW_CONTACT_FIELDS, SHOW_FIRST_NAME_FIELD or SHOW_SURNAME_FIELD or SHOW_PHONE_NUMBERS_FIELD or SHOW_EMAILS_FIELD or
|
||||||
SHOW_ADDRESSES_FIELD or SHOW_EVENTS_FIELD or SHOW_NOTES_FIELD or SHOW_GROUPS_FIELD or SHOW_CONTACT_SOURCE_FIELD)
|
SHOW_ADDRESSES_FIELD or SHOW_EVENTS_FIELD or SHOW_NOTES_FIELD or SHOW_GROUPS_FIELD or SHOW_CONTACT_SOURCE_FIELD)
|
||||||
set(showContactFields) = prefs.edit().putInt(SHOW_CONTACT_FIELDS, showContactFields).apply()
|
set(showContactFields) = prefs.edit().putInt(SHOW_CONTACT_FIELDS, showContactFields).apply()
|
||||||
|
|
||||||
|
var filterDuplicates: Boolean
|
||||||
|
get() = prefs.getBoolean(FILTER_DUPLICATES, true)
|
||||||
|
set(filterDuplicates) = prefs.edit().putBoolean(FILTER_DUPLICATES, filterDuplicates).apply()
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,14 @@ import android.provider.ContactsContract.CommonDataKinds
|
|||||||
// shared prefs
|
// shared prefs
|
||||||
const val SHOW_CONTACT_THUMBNAILS = "show_contact_thumbnails"
|
const val SHOW_CONTACT_THUMBNAILS = "show_contact_thumbnails"
|
||||||
const val SHOW_PHONE_NUMBERS = "show_phone_numbers"
|
const val SHOW_PHONE_NUMBERS = "show_phone_numbers"
|
||||||
const val DISPLAY_CONTACT_SOURCES = "display_contact_sources"
|
const val IGNORED_CONTACT_SOURCES = "ignored_contact_sources"
|
||||||
const val START_NAME_WITH_SURNAME = "start_name_with_surname"
|
const val START_NAME_WITH_SURNAME = "start_name_with_surname"
|
||||||
const val LAST_USED_CONTACT_SOURCE = "last_used_contact_source"
|
const val LAST_USED_CONTACT_SOURCE = "last_used_contact_source"
|
||||||
const val LOCAL_ACCOUNT_NAME = "local_account_name"
|
const val LOCAL_ACCOUNT_NAME = "local_account_name"
|
||||||
const val LOCAL_ACCOUNT_TYPE = "local_account_type"
|
const val LOCAL_ACCOUNT_TYPE = "local_account_type"
|
||||||
const val ON_CONTACT_CLICK = "on_contact_click"
|
const val ON_CONTACT_CLICK = "on_contact_click"
|
||||||
const val SHOW_CONTACT_FIELDS = "show_contact_fields"
|
const val SHOW_CONTACT_FIELDS = "show_contact_fields"
|
||||||
|
const val FILTER_DUPLICATES = "filter_duplicates"
|
||||||
|
|
||||||
const val CONTACT_ID = "contact_id"
|
const val CONTACT_ID = "contact_id"
|
||||||
const val SMT_PRIVATE = "smt_private" // used at the contact source of local contacts hidden from other apps
|
const val SMT_PRIVATE = "smt_private" // used at the contact source of local contacts hidden from other apps
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.simplemobiletools.contacts.helpers
|
package com.simplemobiletools.contacts.helpers
|
||||||
|
|
||||||
import android.accounts.AccountManager
|
import android.accounts.AccountManager
|
||||||
|
import android.app.Activity
|
||||||
import android.content.*
|
import android.content.*
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
@ -11,7 +12,6 @@ import android.provider.ContactsContract.CommonDataKinds.Note
|
|||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
|
||||||
import com.simplemobiletools.commons.extensions.*
|
import com.simplemobiletools.commons.extensions.*
|
||||||
import com.simplemobiletools.commons.helpers.SORT_BY_FIRST_NAME
|
import com.simplemobiletools.commons.helpers.SORT_BY_FIRST_NAME
|
||||||
import com.simplemobiletools.commons.helpers.SORT_BY_MIDDLE_NAME
|
import com.simplemobiletools.commons.helpers.SORT_BY_MIDDLE_NAME
|
||||||
@ -20,24 +20,32 @@ import com.simplemobiletools.commons.helpers.SORT_DESCENDING
|
|||||||
import com.simplemobiletools.contacts.R
|
import com.simplemobiletools.contacts.R
|
||||||
import com.simplemobiletools.contacts.extensions.*
|
import com.simplemobiletools.contacts.extensions.*
|
||||||
import com.simplemobiletools.contacts.models.*
|
import com.simplemobiletools.contacts.models.*
|
||||||
|
import com.simplemobiletools.contacts.overloads.times
|
||||||
|
|
||||||
class ContactsHelper(val activity: BaseSimpleActivity) {
|
class ContactsHelper(val activity: Activity) {
|
||||||
private val BATCH_SIZE = 100
|
private val BATCH_SIZE = 100
|
||||||
|
private var displayContactSources = ArrayList<String>()
|
||||||
|
|
||||||
fun getContacts(callback: (ArrayList<Contact>) -> Unit) {
|
fun getContacts(callback: (ArrayList<Contact>) -> Unit) {
|
||||||
Thread {
|
Thread {
|
||||||
val contacts = SparseArray<Contact>()
|
val contacts = SparseArray<Contact>()
|
||||||
|
displayContactSources = activity.getVisibleContactSources()
|
||||||
getDeviceContacts(contacts)
|
getDeviceContacts(contacts)
|
||||||
|
|
||||||
|
if (displayContactSources.contains(SMT_PRIVATE)) {
|
||||||
activity.dbHelper.getContacts(activity).forEach {
|
activity.dbHelper.getContacts(activity).forEach {
|
||||||
contacts.put(it.id, it)
|
contacts.put(it.id, it)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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) }
|
||||||
|
if (activity.config.filterDuplicates) {
|
||||||
resultContacts = resultContacts.distinctBy {
|
resultContacts = resultContacts.distinctBy {
|
||||||
it.getHashToCompare()
|
it.getHashToCompare()
|
||||||
} as ArrayList<Contact>
|
} 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())
|
||||||
@ -60,8 +68,8 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
|
|
||||||
val uri = ContactsContract.Data.CONTENT_URI
|
val uri = ContactsContract.Data.CONTENT_URI
|
||||||
val projection = getContactProjection()
|
val projection = getContactProjection()
|
||||||
val selection = "${ContactsContract.Data.MIMETYPE} = ?"
|
val selection = getSourcesSelection(true)
|
||||||
val selectionArgs = arrayOf(CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
|
val selectionArgs = getSourcesSelectionArgs(CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
|
||||||
val sortOrder = getSortString()
|
val sortOrder = getSortString()
|
||||||
|
|
||||||
var cursor: Cursor? = null
|
var cursor: Cursor? = null
|
||||||
@ -100,7 +108,7 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
cursor?.close()
|
cursor?.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
val phoneNumbers = getPhoneNumbers()
|
val phoneNumbers = getPhoneNumbers(null)
|
||||||
var size = phoneNumbers.size()
|
var size = phoneNumbers.size()
|
||||||
for (i in 0 until size) {
|
for (i in 0 until size) {
|
||||||
val key = phoneNumbers.keyAt(i)
|
val key = phoneNumbers.keyAt(i)
|
||||||
@ -159,8 +167,8 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
CommonDataKinds.Phone.TYPE
|
CommonDataKinds.Phone.TYPE
|
||||||
)
|
)
|
||||||
|
|
||||||
val selection = if (contactId == null) null else "${ContactsContract.Data.RAW_CONTACT_ID} = ?"
|
val selection = if (contactId == null) getSourcesSelection() else "${ContactsContract.Data.RAW_CONTACT_ID} = ?"
|
||||||
val selectionArgs = if (contactId == null) null else arrayOf(contactId.toString())
|
val selectionArgs = if (contactId == null) getSourcesSelectionArgs() else arrayOf(contactId.toString())
|
||||||
|
|
||||||
var cursor: Cursor? = null
|
var cursor: Cursor? = null
|
||||||
try {
|
try {
|
||||||
@ -184,6 +192,7 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
} finally {
|
} finally {
|
||||||
cursor?.close()
|
cursor?.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
return phoneNumbers
|
return phoneNumbers
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,8 +205,8 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
CommonDataKinds.Email.TYPE
|
CommonDataKinds.Email.TYPE
|
||||||
)
|
)
|
||||||
|
|
||||||
val selection = if (contactId == null) null else "${ContactsContract.Data.RAW_CONTACT_ID} = ?"
|
val selection = if (contactId == null) getSourcesSelection() else "${ContactsContract.Data.RAW_CONTACT_ID} = ?"
|
||||||
val selectionArgs = if (contactId == null) null else arrayOf(contactId.toString())
|
val selectionArgs = if (contactId == null) getSourcesSelectionArgs() else arrayOf(contactId.toString())
|
||||||
|
|
||||||
var cursor: Cursor? = null
|
var cursor: Cursor? = null
|
||||||
try {
|
try {
|
||||||
@ -215,7 +224,6 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
emails[id]!!.add(Email(email, type))
|
emails[id]!!.add(Email(email, type))
|
||||||
} while (cursor.moveToNext())
|
} while (cursor.moveToNext())
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
activity.showErrorToast(e)
|
activity.showErrorToast(e)
|
||||||
} finally {
|
} finally {
|
||||||
@ -234,8 +242,8 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
CommonDataKinds.StructuredPostal.TYPE
|
CommonDataKinds.StructuredPostal.TYPE
|
||||||
)
|
)
|
||||||
|
|
||||||
val selection = if (contactId == null) null else "${ContactsContract.Data.RAW_CONTACT_ID} = ?"
|
val selection = if (contactId == null) getSourcesSelection() else "${ContactsContract.Data.RAW_CONTACT_ID} = ?"
|
||||||
val selectionArgs = if (contactId == null) null else arrayOf(contactId.toString())
|
val selectionArgs = if (contactId == null) getSourcesSelectionArgs() else arrayOf(contactId.toString())
|
||||||
|
|
||||||
var cursor: Cursor? = null
|
var cursor: Cursor? = null
|
||||||
try {
|
try {
|
||||||
@ -253,7 +261,6 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
addresses[id]!!.add(Address(address, type))
|
addresses[id]!!.add(Address(address, type))
|
||||||
} while (cursor.moveToNext())
|
} while (cursor.moveToNext())
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
activity.showErrorToast(e)
|
activity.showErrorToast(e)
|
||||||
} finally {
|
} finally {
|
||||||
@ -272,13 +279,8 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
CommonDataKinds.Event.TYPE
|
CommonDataKinds.Event.TYPE
|
||||||
)
|
)
|
||||||
|
|
||||||
var selection = "${ContactsContract.Data.MIMETYPE} = ?"
|
val selection = getSourcesSelection(true, contactId != null)
|
||||||
var selectionArgs = arrayOf(CommonDataKinds.Event.CONTENT_ITEM_TYPE)
|
val selectionArgs = getSourcesSelectionArgs(CommonDataKinds.Event.CONTENT_ITEM_TYPE, contactId)
|
||||||
|
|
||||||
if (contactId != null) {
|
|
||||||
selection += " AND ${ContactsContract.Data.RAW_CONTACT_ID} = ?"
|
|
||||||
selectionArgs = arrayOf(CommonDataKinds.Event.CONTENT_ITEM_TYPE, contactId.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
var cursor: Cursor? = null
|
var cursor: Cursor? = null
|
||||||
try {
|
try {
|
||||||
@ -313,13 +315,8 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
Note.NOTE
|
Note.NOTE
|
||||||
)
|
)
|
||||||
|
|
||||||
var selection = "${ContactsContract.Data.MIMETYPE} = ?"
|
val selection = getSourcesSelection(true, contactId != null)
|
||||||
var selectionArgs = arrayOf(Note.CONTENT_ITEM_TYPE)
|
val selectionArgs = getSourcesSelectionArgs(Note.CONTENT_ITEM_TYPE, contactId)
|
||||||
|
|
||||||
if (contactId != null) {
|
|
||||||
selection += " AND ${ContactsContract.Data.RAW_CONTACT_ID} = ?"
|
|
||||||
selectionArgs = arrayOf(Note.CONTENT_ITEM_TYPE, contactId.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
var cursor: Cursor? = null
|
var cursor: Cursor? = null
|
||||||
try {
|
try {
|
||||||
@ -349,13 +346,8 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
CommonDataKinds.Organization.TITLE
|
CommonDataKinds.Organization.TITLE
|
||||||
)
|
)
|
||||||
|
|
||||||
var selection = "${ContactsContract.Data.MIMETYPE} = ?"
|
val selection = getSourcesSelection(true, contactId != null)
|
||||||
var selectionArgs = arrayOf(CommonDataKinds.Organization.CONTENT_ITEM_TYPE)
|
val selectionArgs = getSourcesSelectionArgs(CommonDataKinds.Organization.CONTENT_ITEM_TYPE, contactId)
|
||||||
|
|
||||||
if (contactId != null) {
|
|
||||||
selection += " AND ${ContactsContract.Data.RAW_CONTACT_ID} = ?"
|
|
||||||
selectionArgs = arrayOf(CommonDataKinds.Organization.CONTENT_ITEM_TYPE, contactId.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
var cursor: Cursor? = null
|
var cursor: Cursor? = null
|
||||||
try {
|
try {
|
||||||
@ -386,13 +378,8 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
CommonDataKinds.Website.URL
|
CommonDataKinds.Website.URL
|
||||||
)
|
)
|
||||||
|
|
||||||
var selection = "${ContactsContract.Data.MIMETYPE} = ?"
|
val selection = getSourcesSelection(true, contactId != null)
|
||||||
var selectionArgs = arrayOf(CommonDataKinds.Website.CONTENT_ITEM_TYPE)
|
val selectionArgs = getSourcesSelectionArgs(CommonDataKinds.Website.CONTENT_ITEM_TYPE, contactId)
|
||||||
|
|
||||||
if (contactId != null) {
|
|
||||||
selection += " AND ${ContactsContract.Data.RAW_CONTACT_ID} = ?"
|
|
||||||
selectionArgs = arrayOf(CommonDataKinds.Website.CONTENT_ITEM_TYPE, contactId.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
var cursor: Cursor? = null
|
var cursor: Cursor? = null
|
||||||
try {
|
try {
|
||||||
@ -430,13 +417,8 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
ContactsContract.Data.DATA1
|
ContactsContract.Data.DATA1
|
||||||
)
|
)
|
||||||
|
|
||||||
var selection = "${ContactsContract.Data.MIMETYPE} = ?"
|
val selection = getSourcesSelection(true, contactId != null, false)
|
||||||
var selectionArgs = arrayOf(CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE)
|
val selectionArgs = getSourcesSelectionArgs(CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE, contactId)
|
||||||
|
|
||||||
if (contactId != null) {
|
|
||||||
selection += " AND ${ContactsContract.Data.CONTACT_ID} = ?"
|
|
||||||
selectionArgs = arrayOf(CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE, contactId.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
var cursor: Cursor? = null
|
var cursor: Cursor? = null
|
||||||
try {
|
try {
|
||||||
@ -463,6 +445,48 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
return groups
|
return groups
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getQuestionMarks() = "?,".times(displayContactSources.filter { it.isNotEmpty() }.size).trimEnd(',')
|
||||||
|
|
||||||
|
private fun getSourcesSelection(addMimeType: Boolean = false, addContactId: Boolean = false, useRawContactId: Boolean = true): String {
|
||||||
|
val strings = ArrayList<String>()
|
||||||
|
if (addMimeType) {
|
||||||
|
strings.add("${ContactsContract.Data.MIMETYPE} = ?")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addContactId) {
|
||||||
|
strings.add("${if (useRawContactId) ContactsContract.Data.RAW_CONTACT_ID else ContactsContract.Data.CONTACT_ID} = ?")
|
||||||
|
} else {
|
||||||
|
// sometimes local device storage has null account_name, handle it properly
|
||||||
|
val accountnameString = StringBuilder()
|
||||||
|
if (displayContactSources.contains("")) {
|
||||||
|
accountnameString.append("(")
|
||||||
|
}
|
||||||
|
accountnameString.append("${ContactsContract.RawContacts.ACCOUNT_NAME} IN (${getQuestionMarks()})")
|
||||||
|
if (displayContactSources.contains("")) {
|
||||||
|
accountnameString.append(" OR ${ContactsContract.RawContacts.ACCOUNT_NAME} IS NULL)")
|
||||||
|
}
|
||||||
|
strings.add(accountnameString.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
return TextUtils.join(" AND ", strings)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSourcesSelectionArgs(mimetype: String? = null, contactId: Int? = null): Array<String> {
|
||||||
|
val args = ArrayList<String>()
|
||||||
|
|
||||||
|
if (mimetype != null) {
|
||||||
|
args.add(mimetype)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contactId != null) {
|
||||||
|
args.add(contactId.toString())
|
||||||
|
} else {
|
||||||
|
args.addAll(displayContactSources.filter { it.isNotEmpty() })
|
||||||
|
}
|
||||||
|
|
||||||
|
return args.toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
fun getStoredGroups(): ArrayList<Group> {
|
fun getStoredGroups(): ArrayList<Group> {
|
||||||
val groups = getDeviceStoredGroups()
|
val groups = getDeviceStoredGroups()
|
||||||
groups.addAll(activity.dbHelper.getGroups())
|
groups.addAll(activity.dbHelper.getGroups())
|
||||||
@ -622,13 +646,17 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
|
|
||||||
fun getContactSources(callback: (ArrayList<ContactSource>) -> Unit) {
|
fun getContactSources(callback: (ArrayList<ContactSource>) -> Unit) {
|
||||||
Thread {
|
Thread {
|
||||||
val sources = getDeviceContactSources()
|
callback(getContactSourcesSync())
|
||||||
sources.add(ContactSource(activity.getString(R.string.phone_storage_hidden), SMT_PRIVATE))
|
|
||||||
callback(ArrayList(sources))
|
|
||||||
}.start()
|
}.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getDeviceContactSources(): LinkedHashSet<ContactSource> {
|
private fun getContactSourcesSync(): ArrayList<ContactSource> {
|
||||||
|
val sources = getDeviceContactSources()
|
||||||
|
sources.add(ContactSource(activity.getString(R.string.phone_storage_hidden), SMT_PRIVATE))
|
||||||
|
return ArrayList(sources)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDeviceContactSources(): LinkedHashSet<ContactSource> {
|
||||||
val sources = LinkedHashSet<ContactSource>()
|
val sources = LinkedHashSet<ContactSource>()
|
||||||
if (!activity.hasContactPermissions()) {
|
if (!activity.hasContactPermissions()) {
|
||||||
return sources
|
return sources
|
||||||
@ -1220,13 +1248,18 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
val operations = ArrayList<ContentProviderOperation>()
|
val operations = ArrayList<ContentProviderOperation>()
|
||||||
val selection = "${ContactsContract.Data.CONTACT_ID} = ?"
|
val selection = "${ContactsContract.RawContacts._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.RawContacts.CONTENT_URI).apply {
|
||||||
val selectionArgs = arrayOf(it.contactId.toString())
|
val selectionArgs = arrayOf(it.id.toString())
|
||||||
withSelection(selection, selectionArgs)
|
withSelection(selection, selectionArgs)
|
||||||
operations.add(build())
|
operations.add(build())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (operations.size % BATCH_SIZE == 0) {
|
||||||
|
activity.contentResolver.applyBatch(ContactsContract.AUTHORITY, operations)
|
||||||
|
operations.clear()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
activity.contentResolver.applyBatch(ContactsContract.AUTHORITY, operations)
|
activity.contentResolver.applyBatch(ContactsContract.AUTHORITY, operations)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.simplemobiletools.contacts.helpers
|
package com.simplemobiletools.contacts.helpers
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.database.sqlite.SQLiteDatabase
|
import android.database.sqlite.SQLiteDatabase
|
||||||
@ -11,7 +12,6 @@ import android.provider.MediaStore
|
|||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
|
||||||
import com.simplemobiletools.commons.extensions.getBlobValue
|
import com.simplemobiletools.commons.extensions.getBlobValue
|
||||||
import com.simplemobiletools.commons.extensions.getIntValue
|
import com.simplemobiletools.commons.extensions.getIntValue
|
||||||
import com.simplemobiletools.commons.extensions.getLongValue
|
import com.simplemobiletools.commons.extensions.getLongValue
|
||||||
@ -249,7 +249,7 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getContacts(activity: BaseSimpleActivity, selection: String? = null, selectionArgs: Array<String>? = null): ArrayList<Contact> {
|
fun getContacts(activity: Activity, selection: String? = null, selectionArgs: Array<String>? = null): ArrayList<Contact> {
|
||||||
val storedGroups = ContactsHelper(activity).getStoredGroups()
|
val storedGroups = ContactsHelper(activity).getStoredGroups()
|
||||||
val contacts = ArrayList<Contact>()
|
val contacts = ArrayList<Contact>()
|
||||||
val projection = arrayOf(COL_ID, COL_PREFIX, COL_FIRST_NAME, COL_MIDDLE_NAME, COL_SURNAME, COL_SUFFIX, COL_PHONE_NUMBERS, COL_EMAILS,
|
val projection = arrayOf(COL_ID, COL_PREFIX, COL_FIRST_NAME, COL_MIDDLE_NAME, COL_SURNAME, COL_SUFFIX, COL_PHONE_NUMBERS, COL_EMAILS,
|
||||||
@ -319,7 +319,7 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
|
|||||||
return contacts
|
return contacts
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getContactWithId(activity: BaseSimpleActivity, id: Int): Contact? {
|
fun getContactWithId(activity: Activity, id: Int): Contact? {
|
||||||
val selection = "$COL_ID = ?"
|
val selection = "$COL_ID = ?"
|
||||||
val selectionArgs = arrayOf(id.toString())
|
val selectionArgs = arrayOf(id.toString())
|
||||||
return getContacts(activity, selection, selectionArgs).firstOrNull()
|
return getContacts(activity, selection, selectionArgs).firstOrNull()
|
||||||
|
@ -86,6 +86,7 @@ data class Contact(val id: Int, var prefix: String, var firstName: String, var m
|
|||||||
fun getHashToCompare(): Int {
|
fun getHashToCompare(): Int {
|
||||||
val newPhoneNumbers = ArrayList<PhoneNumber>()
|
val newPhoneNumbers = ArrayList<PhoneNumber>()
|
||||||
phoneNumbers.mapTo(newPhoneNumbers, { PhoneNumber(it.value.replace(pattern, ""), 0) })
|
phoneNumbers.mapTo(newPhoneNumbers, { PhoneNumber(it.value.replace(pattern, ""), 0) })
|
||||||
return copy(id = 0, phoneNumbers = newPhoneNumbers).hashCode()
|
return copy(id = 0, prefix = "", firstName = getFullName().toLowerCase(), middleName = "", surname = "", suffix = "", photoUri = "",
|
||||||
|
phoneNumbers = newPhoneNumbers, source = "", starred = 0, contactId = 0, thumbnailUri = "", notes = "").hashCode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
<vector
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportHeight="108"
|
|
||||||
android:viewportWidth="108">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="m55,53.39c5.06,0 9.22,-4.08 9.22,-9.22 0,-5.14 -4.08,-9.22 -9.22,-9.22 -5.14,0 -9.22,4.08 -9.22,9.22 0,5.14 4.16,9.22 9.22,9.22zM55,57.96c-6.12,0 -18.36,3.1 -18.36,9.22l0,4.57 36.72,0 0,-4.57C73.36,61.06 61.12,57.96 55,57.96Z"/>
|
|
||||||
</vector>
|
|
@ -193,6 +193,29 @@
|
|||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/settings_filter_duplicates_holder"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/medium_margin"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:paddingBottom="@dimen/activity_margin"
|
||||||
|
android:paddingLeft="@dimen/normal_margin"
|
||||||
|
android:paddingRight="@dimen/normal_margin"
|
||||||
|
android:paddingTop="@dimen/activity_margin">
|
||||||
|
|
||||||
|
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||||
|
android:id="@+id/settings_filter_duplicates"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@null"
|
||||||
|
android:clickable="false"
|
||||||
|
android:paddingLeft="@dimen/medium_margin"
|
||||||
|
android:paddingStart="@dimen/medium_margin"
|
||||||
|
android:text="@string/filter_duplicates"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/settings_on_contact_click_holder"
|
android:id="@+id/settings_on_contact_click_holder"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@color/color_primary"/>
|
<background android:drawable="@color/md_orange_700"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_amber.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_amber_700"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_blue.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_blue_700"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_blue_grey_700"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_brown.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_brown_700"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_cyan.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_cyan_700"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_deep_orange_700"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_deep_purple_700"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_green.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_green_700"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_grey_black"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_indigo_700"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_light_blue_700"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_light_green_700"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_lime.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_lime_700"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_pink.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_pink_700"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_purple_700"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_red.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_red_700"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_teal.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_teal_700"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/md_yellow_700"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 4.0 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_amber.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_blue.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_blue_grey.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_brown.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_cyan.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_deep_orange.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_deep_purple.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_green.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_grey_black.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_indigo.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_light_blue.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_light_green.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_lime.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_pink.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_purple.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 3.7 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_teal.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_yellow.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_amber.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_blue.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_blue_grey.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_brown.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_cyan.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_deep_orange.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_deep_purple.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_green.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_grey_black.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_indigo.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_light_blue.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_light_green.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_lime.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_pink.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_purple.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_red.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_teal.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_yellow.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 6.0 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_amber.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_blue.png
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_blue_grey.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_brown.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_cyan.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_deep_orange.png
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_deep_purple.png
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_green.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_grey_black.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_indigo.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_light_blue.png
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_light_green.png
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_lime.png
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_pink.png
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_purple.png
Normal file
After Width: | Height: | Size: 6.1 KiB |