From 93e7d73d9120ed7efd5b531a29c33fc2237c8a73 Mon Sep 17 00:00:00 2001 From: tibbi Date: Thu, 1 Feb 2018 21:25:28 +0100 Subject: [PATCH 01/35] update commons to 3.9.9 --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 0b3e3353..8a7ac1c6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -42,7 +42,7 @@ ext { } dependencies { - implementation 'com.simplemobiletools:commons:3.9.5' + implementation 'com.simplemobiletools:commons:3.9.9' implementation 'joda-time:joda-time:2.9.9' debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanaryVersion" From 6c33c069ac9c5949700232513a6a616539835777 Mon Sep 17 00:00:00 2001 From: Nikola Trubitsyn Date: Tue, 30 Jan 2018 23:58:22 +0300 Subject: [PATCH 02/35] Set unique applicationIdSuffix in debug builds --- app/build.gradle | 3 +++ app/src/debug/res/values/strings.xml | 4 ++++ 2 files changed, 7 insertions(+) create mode 100644 app/src/debug/res/values/strings.xml diff --git a/app/build.gradle b/app/build.gradle index 0b3e3353..fe5c371e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -20,6 +20,9 @@ android { } buildTypes { + debug { + applicationIdSuffix ".debug" + } release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' diff --git a/app/src/debug/res/values/strings.xml b/app/src/debug/res/values/strings.xml new file mode 100644 index 00000000..de1f12cb --- /dev/null +++ b/app/src/debug/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Contacts_debug + \ No newline at end of file From 6f82aadcb9a0c8513c76201023cef6b4ee74303e Mon Sep 17 00:00:00 2001 From: tibbi Date: Thu, 1 Feb 2018 23:54:36 +0100 Subject: [PATCH 03/35] store the local account type in shared prefs --- .../contacts/activities/MainActivity.kt | 25 +++++++++++++++++++ .../contacts/helpers/Config.kt | 4 +++ .../contacts/helpers/Constants.kt | 1 + .../contacts/helpers/ContactsHelper.kt | 23 +++++++++++++++++ 4 files changed, 53 insertions(+) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt index 8bbd46cd..4fe8fa9c 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt @@ -51,6 +51,7 @@ class MainActivity : SimpleActivity(), RefreshContactsListener { setContentView(R.layout.activity_main) appLaunched() setupTabColors() + storeLocalAccountType() handlePermission(PERMISSION_READ_CONTACTS) { if (it) { @@ -214,6 +215,30 @@ class MainActivity : SimpleActivity(), RefreshContactsListener { } } + private fun storeLocalAccountType() { + 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).getContactTypes { + var localAccountType = "" + it.forEach { + if (localAccountTypes.contains(it)) { + localAccountType = it + } + } + config.localAccountType = localAccountType + } + } + } + private fun getOtherViewPagerItem(used: Int) = if (used == 1) 0 else 1 private fun initFragments() { diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Config.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Config.kt index 77b8ca32..707a9c23 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Config.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Config.kt @@ -43,4 +43,8 @@ class Config(context: Context) : BaseConfig(context) { var lastUsedViewPagerPage: Int get() = prefs.getInt(LAST_USED_VIEW_PAGER_PAGE, 0) set(lastUsedViewPagerPage) = prefs.edit().putInt(LAST_USED_VIEW_PAGER_PAGE, lastUsedViewPagerPage).apply() + + var localAccountType: String + get() = prefs.getString(LOCAL_ACCOUNT_TYPE, "-1") + set(localAccountType) = prefs.edit().putString(LOCAL_ACCOUNT_TYPE, localAccountType).apply() } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt index 9bbcb459..441289db 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt @@ -10,6 +10,7 @@ const val DISPLAY_CONTACT_SOURCES = "display_contact_sources" const val START_NAME_WITH_SURNAME = "start_name_with_surname" const val LAST_USED_CONTACT_SOURCE = "last_used_contact_source" const val LAST_USED_VIEW_PAGER_PAGE = "last_used_view_pager_page" +const val LOCAL_ACCOUNT_TYPE = "local_account_type" const val CONTACT_ID = "contact_id" diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt index be32e742..bad36eb1 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt @@ -252,6 +252,29 @@ class ContactsHelper(val activity: BaseSimpleActivity) { }.start() } + fun getContactTypes(callback: (ArrayList) -> Unit) { + val accounts = HashSet() + Thread { + val uri = ContactsContract.RawContacts.CONTENT_URI + val projection = arrayOf(ContactsContract.RawContacts.ACCOUNT_TYPE) + + var cursor: Cursor? = null + try { + cursor = activity.contentResolver.query(uri, projection, null, null, null) + if (cursor?.moveToFirst() == true) { + do { + val type = cursor.getStringValue(ContactsContract.RawContacts.ACCOUNT_TYPE) ?: continue + accounts.add(type) + } while (cursor.moveToNext()) + } + } finally { + cursor?.close() + } + + callback(ArrayList(accounts)) + }.start() + } + private fun getContactSourceType(accountName: String): String { if (accountName.isEmpty()) { return "" From f0a2f585b861b5d19b1392c4522cebe670c0b0ce Mon Sep 17 00:00:00 2001 From: tibbi Date: Fri, 2 Feb 2018 11:30:11 +0100 Subject: [PATCH 04/35] use a new model ContactSource --- .../contacts/activities/MainActivity.kt | 4 +- .../contacts/dialogs/ExportContactsDialog.kt | 2 +- .../dialogs/FilterContactSourcesDialog.kt | 2 +- .../contacts/extensions/Activity.kt | 2 +- .../contacts/helpers/ContactsHelper.kt | 38 ++++--------------- .../contacts/models/Contact.kt | 2 +- .../contacts/models/ContactSource.kt | 3 ++ 7 files changed, 16 insertions(+), 37 deletions(-) create mode 100644 app/src/main/kotlin/com/simplemobiletools/contacts/models/ContactSource.kt diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt index 4fe8fa9c..d0c43f17 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt @@ -227,9 +227,9 @@ class MainActivity : SimpleActivity(), RefreshContactsListener { "com.android.huawei.phone", "Local Phone Account") - ContactsHelper(this).getContactTypes { + ContactsHelper(this).getContactSources { var localAccountType = "" - it.forEach { + it.map { it.type }.forEach { if (localAccountTypes.contains(it)) { localAccountType = it } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ExportContactsDialog.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ExportContactsDialog.kt index 494ddf1a..e9e4094f 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ExportContactsDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ExportContactsDialog.kt @@ -20,7 +20,7 @@ class ExportContactsDialog(val activity: SimpleActivity, val path: String, priva ContactsHelper(activity).getContactSources { activity.runOnUiThread { - export_contacts_list.adapter = FilterContactSourcesAdapter(activity, it, activity.config.displayContactSources) + export_contacts_list.adapter = FilterContactSourcesAdapter(activity, it.map { it.name }, activity.config.displayContactSources) } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/FilterContactSourcesDialog.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/FilterContactSourcesDialog.kt index 6a516e01..faf36ef8 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/FilterContactSourcesDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/FilterContactSourcesDialog.kt @@ -21,7 +21,7 @@ class FilterContactSourcesDialog(val activity: SimpleActivity, private val callb val selectedSources = activity.config.displayContactSources activity.runOnUiThread { - view.filter_contact_sources_list.adapter = FilterContactSourcesAdapter(activity, it, selectedSources) + view.filter_contact_sources_list.adapter = FilterContactSourcesAdapter(activity, it.map { it.name }, selectedSources) dialog = AlertDialog.Builder(activity) .setPositiveButton(R.string.ok, { dialogInterface, i -> confirmEventTypes() }) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Activity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Activity.kt index 0f1eeb83..fafb689c 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Activity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Activity.kt @@ -51,7 +51,7 @@ fun SimpleActivity.tryStartCall(contact: Contact) { fun SimpleActivity.showContactSourcePicker(currentSource: String, callback: (newSource: String) -> Unit) { ContactsHelper(this).getContactSources { val items = ArrayList() - val sources = it + val sources = it.map { it.name } var currentSourceIndex = -1 sources.forEachIndexed { index, account -> items.add(RadioItem(index, account)) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt index bad36eb1..8a06ffe6 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt @@ -22,10 +22,7 @@ import com.simplemobiletools.commons.helpers.SORT_BY_SURNAME import com.simplemobiletools.commons.helpers.SORT_DESCENDING import com.simplemobiletools.contacts.R import com.simplemobiletools.contacts.extensions.config -import com.simplemobiletools.contacts.models.Contact -import com.simplemobiletools.contacts.models.Email -import com.simplemobiletools.contacts.models.Event -import com.simplemobiletools.contacts.models.PhoneNumber +import com.simplemobiletools.contacts.models.* import java.io.ByteArrayOutputStream import java.util.* @@ -229,11 +226,11 @@ class ContactsHelper(val activity: BaseSimpleActivity) { return null } - fun getContactSources(callback: (ArrayList) -> Unit) { - val accounts = HashSet() + fun getContactSources(callback: (ArrayList) -> Unit) { + val sources = HashSet() Thread { val uri = ContactsContract.RawContacts.CONTENT_URI - val projection = arrayOf(ContactsContract.RawContacts.ACCOUNT_NAME) + val projection = arrayOf(ContactsContract.RawContacts.ACCOUNT_NAME, ContactsContract.RawContacts.ACCOUNT_TYPE) var cursor: Cursor? = null try { @@ -241,37 +238,16 @@ class ContactsHelper(val activity: BaseSimpleActivity) { if (cursor?.moveToFirst() == true) { do { val name = cursor.getStringValue(ContactsContract.RawContacts.ACCOUNT_NAME) ?: continue - accounts.add(name) - } while (cursor.moveToNext()) - } - } finally { - cursor?.close() - } - - callback(ArrayList(accounts)) - }.start() - } - - fun getContactTypes(callback: (ArrayList) -> Unit) { - val accounts = HashSet() - Thread { - val uri = ContactsContract.RawContacts.CONTENT_URI - val projection = arrayOf(ContactsContract.RawContacts.ACCOUNT_TYPE) - - var cursor: Cursor? = null - try { - cursor = activity.contentResolver.query(uri, projection, null, null, null) - if (cursor?.moveToFirst() == true) { - do { val type = cursor.getStringValue(ContactsContract.RawContacts.ACCOUNT_TYPE) ?: continue - accounts.add(type) + val contactSource = ContactSource(name, type) + sources.add(contactSource) } while (cursor.moveToNext()) } } finally { cursor?.close() } - callback(ArrayList(accounts)) + callback(ArrayList(sources)) }.start() } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/models/Contact.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/models/Contact.kt index 95131fe6..b41e6e6b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/models/Contact.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/models/Contact.kt @@ -8,7 +8,7 @@ data class Contact(val id: Int, var firstName: String, var middleName: String, v var phoneNumbers: ArrayList, var emails: ArrayList, var events: ArrayList, var source: String, var starred: Int, val contactId: Int, val thumbnailUri: String) : Comparable { companion object { - var sorting: Int = 0 + var sorting = 0 } override fun compareTo(other: Contact): Int { diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/models/ContactSource.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/models/ContactSource.kt new file mode 100644 index 00000000..b37197e8 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/models/ContactSource.kt @@ -0,0 +1,3 @@ +package com.simplemobiletools.contacts.models + +data class ContactSource(var name: String, var type: String) From 029db0d8538a7ff572df00851b1bd928ba8d21a6 Mon Sep 17 00:00:00 2001 From: tibbi Date: Fri, 2 Feb 2018 11:44:38 +0100 Subject: [PATCH 05/35] add a new string for private phone contacts --- app/src/main/res/values-de/strings.xml | 1 + app/src/main/res/values-ko-rKR/strings.xml | 1 + app/src/main/res/values-pt/strings.xml | 1 + app/src/main/res/values-ru/strings.xml | 1 + app/src/main/res/values-sk/strings.xml | 1 + app/src/main/res/values-sv/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 7 files changed, 7 insertions(+) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index db5df3c6..8d89a52a 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -5,6 +5,7 @@ Einfügen… Aktualisiere… Gerätespeicher + Phone storage (not visible by other apps) Neuer Kontakt Kontakt bearbeiten diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index 08c93d35..a9551607 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -5,6 +5,7 @@ 등록중… 수정중… Phone storage + Phone storage (not visible by other apps) 새로운 연락처 연락처 수정 diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 4831a362..dac3a713 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -5,6 +5,7 @@ Inserting… Updating… Phone storage + Phone storage (not visible by other apps) Novo contacto Editar contacto diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 58af51cf..31ecbd97 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -5,6 +5,7 @@ Добавление… Обновление… Память устройства + Phone storage (not visible by other apps) Новый контакт Редактировать контакт diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index a9fd79d1..a8450b05 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -5,6 +5,7 @@ Vytvára sa… Upravuje sa… Úložisko mobilu + Úložisko mobilu (neviditeľné pre ostatné apky) Nový kontakt Upraviť kontakt diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index aadd2363..d15d5762 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -5,6 +5,7 @@ Lägger till… Uppdaterar… Phone storage + Phone storage (not visible by other apps) Ny kontakt Redigera kontakt diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0a735653..35c13d18 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -5,6 +5,7 @@ Inserting… Updating… Phone storage + Phone storage (not visible by other apps) New contact Edit contact From 3bb7860bb7c12c378f32a50aad66ef17c1007253 Mon Sep 17 00:00:00 2001 From: tibbi Date: Fri, 2 Feb 2018 11:53:01 +0100 Subject: [PATCH 06/35] store the local account name too --- .../contacts/activities/MainActivity.kt | 14 +++++++++----- .../simplemobiletools/contacts/helpers/Config.kt | 6 +++++- .../contacts/helpers/Constants.kt | 1 + 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt index d0c43f17..6fc48b2c 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt @@ -51,12 +51,12 @@ class MainActivity : SimpleActivity(), RefreshContactsListener { setContentView(R.layout.activity_main) appLaunched() setupTabColors() - storeLocalAccountType() handlePermission(PERMISSION_READ_CONTACTS) { if (it) { handlePermission(PERMISSION_WRITE_CONTACTS) { if (it) { + storeLocalAccountData() initFragments() } else { toast(R.string.no_contacts_permission) @@ -215,7 +215,7 @@ class MainActivity : SimpleActivity(), RefreshContactsListener { } } - private fun storeLocalAccountType() { + private fun storeLocalAccountData() { if (config.localAccountType == "-1") { // some manufacturer contact account types from https://stackoverflow.com/a/44802016/1967672 val localAccountTypes = arrayListOf("vnd.sec.contact.phone", @@ -229,12 +229,16 @@ class MainActivity : SimpleActivity(), RefreshContactsListener { ContactsHelper(this).getContactSources { var localAccountType = "" - it.map { it.type }.forEach { - if (localAccountTypes.contains(it)) { - localAccountType = it + var localAccountName = "" + it.forEach { + if (localAccountTypes.contains(it.type)) { + localAccountType = it.type + localAccountName = it.name } } + config.localAccountType = localAccountType + config.localAccountName = localAccountName } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Config.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Config.kt index 707a9c23..1ebd3024 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Config.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Config.kt @@ -24,7 +24,7 @@ class Config(context: Context) : BaseConfig(context) { fun showAllContacts() = displayContactSources.size == 1 && displayContactSources.first() == "-1" - var showContactThumbnails : Boolean + var showContactThumbnails: Boolean get() = prefs.getBoolean(SHOW_CONTACT_THUMBNAILS, true) set(showContactThumbnails) = prefs.edit().putBoolean(SHOW_CONTACT_THUMBNAILS, showContactThumbnails).apply() @@ -44,6 +44,10 @@ class Config(context: Context) : BaseConfig(context) { get() = prefs.getInt(LAST_USED_VIEW_PAGER_PAGE, 0) set(lastUsedViewPagerPage) = prefs.edit().putInt(LAST_USED_VIEW_PAGER_PAGE, lastUsedViewPagerPage).apply() + var localAccountName: String + get() = prefs.getString(LOCAL_ACCOUNT_NAME, "-1") + set(localAccountName) = prefs.edit().putString(LOCAL_ACCOUNT_NAME, localAccountName).apply() + var localAccountType: String get() = prefs.getString(LOCAL_ACCOUNT_TYPE, "-1") set(localAccountType) = prefs.edit().putString(LOCAL_ACCOUNT_TYPE, localAccountType).apply() diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt index 441289db..67c98c8b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt @@ -10,6 +10,7 @@ const val DISPLAY_CONTACT_SOURCES = "display_contact_sources" const val START_NAME_WITH_SURNAME = "start_name_with_surname" const val LAST_USED_CONTACT_SOURCE = "last_used_contact_source" const val LAST_USED_VIEW_PAGER_PAGE = "last_used_view_pager_page" +const val LOCAL_ACCOUNT_NAME = "local_account_name" const val LOCAL_ACCOUNT_TYPE = "local_account_type" const val CONTACT_ID = "contact_id" From 996a9ead0a30ef92bf5338c5f1032bc1daa23a41 Mon Sep 17 00:00:00 2001 From: tibbi Date: Fri, 2 Feb 2018 12:30:33 +0100 Subject: [PATCH 07/35] show the modified contact source at the FilterContactSources adapter --- .../adapters/FilterContactSourcesAdapter.kt | 19 ++++++++++--------- .../contacts/dialogs/ExportContactsDialog.kt | 14 +++++++++++--- .../dialogs/FilterContactSourcesDialog.kt | 17 +++++++++++++---- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/FilterContactSourcesAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/FilterContactSourcesAdapter.kt index 05bb831a..1af2218f 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/FilterContactSourcesAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/FilterContactSourcesAdapter.kt @@ -9,19 +9,24 @@ import com.simplemobiletools.commons.interfaces.MyAdapterListener import com.simplemobiletools.contacts.R import com.simplemobiletools.contacts.activities.SimpleActivity import com.simplemobiletools.contacts.extensions.config +import com.simplemobiletools.contacts.models.ContactSource import kotlinx.android.synthetic.main.item_filter_contact_source.view.* import java.util.* -class FilterContactSourcesAdapter(val activity: SimpleActivity, private val contactSources: List, private val displayContactSources: Set) : +class FilterContactSourcesAdapter(val activity: SimpleActivity, private val contactSources: List, private val displayContactSources: Set) : RecyclerView.Adapter() { private val itemViews = SparseArray() private val selectedPositions = HashSet() init { - contactSources.forEachIndexed { index, value -> - if (activity.config.showAllContacts() || displayContactSources.contains(value)) { + contactSources.forEachIndexed { index, contactSource -> + if (activity.config.showAllContacts() || displayContactSources.contains(contactSource.name)) { selectedPositions.add(index) } + + if (contactSource.name == activity.config.localAccountName && contactSource.type == activity.config.localAccountType) { + contactSource.name = activity.getString(R.string.phone_storage) + } } } @@ -47,11 +52,7 @@ class FilterContactSourcesAdapter(val activity: SimpleActivity, private val cont override fun itemLongClicked(position: Int) {} } - fun getSelectedItemsSet(): HashSet { - val selectedItemsSet = HashSet(selectedPositions.size) - selectedPositions.forEach { selectedItemsSet.add(contactSources[it]) } - return selectedItemsSet - } + fun getSelectedItemsSet() = selectedPositions override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder { val view = activity.layoutInflater.inflate(R.layout.item_filter_contact_source, parent, false) @@ -60,7 +61,7 @@ class FilterContactSourcesAdapter(val activity: SimpleActivity, private val cont override fun onBindViewHolder(holder: ViewHolder, position: Int) { val contactSource = contactSources[position] - itemViews.put(position, holder.bindView(contactSource)) + itemViews.put(position, holder.bindView(contactSource.name)) toggleItemSelection(selectedPositions.contains(position), position) } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ExportContactsDialog.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ExportContactsDialog.kt index e9e4094f..f19ce9f6 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ExportContactsDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ExportContactsDialog.kt @@ -8,10 +8,13 @@ import com.simplemobiletools.contacts.activities.SimpleActivity import com.simplemobiletools.contacts.adapters.FilterContactSourcesAdapter import com.simplemobiletools.contacts.extensions.config import com.simplemobiletools.contacts.helpers.ContactsHelper +import com.simplemobiletools.contacts.models.ContactSource import kotlinx.android.synthetic.main.dialog_export_contacts.view.* import java.io.File +import java.util.* class ExportContactsDialog(val activity: SimpleActivity, val path: String, private val callback: (file: File, contactSources: HashSet) -> Unit) { + private var contactSources = ArrayList() init { val view = (activity.layoutInflater.inflate(R.layout.dialog_export_contacts, null) as ViewGroup).apply { @@ -19,8 +22,9 @@ class ExportContactsDialog(val activity: SimpleActivity, val path: String, priva export_contacts_filename.setText("contacts_${System.currentTimeMillis() / 1000}") ContactsHelper(activity).getContactSources { + it.mapTo(contactSources, { it.copy() }) activity.runOnUiThread { - export_contacts_list.adapter = FilterContactSourcesAdapter(activity, it.map { it.name }, activity.config.displayContactSources) + export_contacts_list.adapter = FilterContactSourcesAdapter(activity, it, activity.config.displayContactSources) } } } @@ -41,8 +45,12 @@ class ExportContactsDialog(val activity: SimpleActivity, val path: String, priva return@setOnClickListener } - val contactSources = (view.export_contacts_list.adapter as FilterContactSourcesAdapter).getSelectedItemsSet() - callback(file, contactSources) + val selectedIndexes = (view.export_contacts_list.adapter as FilterContactSourcesAdapter).getSelectedItemsSet() + val selectedContactSources = HashSet() + selectedIndexes.forEach { + selectedContactSources.add(contactSources[it].name) + } + callback(file, selectedContactSources) dismiss() } else -> activity.toast(R.string.invalid_name) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/FilterContactSourcesDialog.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/FilterContactSourcesDialog.kt index faf36ef8..a01dc8f8 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/FilterContactSourcesDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/FilterContactSourcesDialog.kt @@ -7,11 +7,14 @@ import com.simplemobiletools.contacts.activities.SimpleActivity import com.simplemobiletools.contacts.adapters.FilterContactSourcesAdapter import com.simplemobiletools.contacts.extensions.config import com.simplemobiletools.contacts.helpers.ContactsHelper +import com.simplemobiletools.contacts.models.ContactSource import kotlinx.android.synthetic.main.dialog_filter_contact_sources.view.* +import java.util.* class FilterContactSourcesDialog(val activity: SimpleActivity, private val callback: () -> Unit) { private var dialog: AlertDialog? = null private val view = activity.layoutInflater.inflate(R.layout.dialog_filter_contact_sources, null) + private var contactSources = ArrayList() init { ContactsHelper(activity).getContactSources { @@ -19,9 +22,10 @@ class FilterContactSourcesDialog(val activity: SimpleActivity, private val callb return@getContactSources } + it.mapTo(contactSources, { it.copy() }) val selectedSources = activity.config.displayContactSources activity.runOnUiThread { - view.filter_contact_sources_list.adapter = FilterContactSourcesAdapter(activity, it.map { it.name }, selectedSources) + view.filter_contact_sources_list.adapter = FilterContactSourcesAdapter(activity, it, selectedSources) dialog = AlertDialog.Builder(activity) .setPositiveButton(R.string.ok, { dialogInterface, i -> confirmEventTypes() }) @@ -34,9 +38,14 @@ class FilterContactSourcesDialog(val activity: SimpleActivity, private val callb } private fun confirmEventTypes() { - val selectedItems = (view.filter_contact_sources_list.adapter as FilterContactSourcesAdapter).getSelectedItemsSet() - if (activity.config.displayContactSources != selectedItems) { - activity.config.displayContactSources = selectedItems + val selectedIndexes = (view.filter_contact_sources_list.adapter as FilterContactSourcesAdapter).getSelectedItemsSet() + val selectedContactSources = HashSet() + selectedIndexes.forEach { + selectedContactSources.add(contactSources[it].name) + } + + if (activity.config.displayContactSources != selectedContactSources) { + activity.config.displayContactSources = selectedContactSources callback() } dialog?.dismiss() From b72c6cb7879046a05f2baa098be5a13dceb63000 Mon Sep 17 00:00:00 2001 From: tibbi Date: Fri, 2 Feb 2018 13:57:24 +0100 Subject: [PATCH 08/35] properly show the public contact source on all visible places --- .../contacts/activities/EditContactActivity.kt | 13 +++++++------ .../contacts/dialogs/ImportContactsDialog.kt | 14 +++++++++----- .../contacts/extensions/Activity.kt | 9 ++++++++- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt index 86be6271..1f7d4758 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt @@ -226,7 +226,7 @@ class EditContactActivity : SimpleActivity() { contact_first_name.setText(contact!!.firstName) contact_middle_name.setText(contact!!.middleName) contact_surname.setText(contact!!.surname) - contact_source.text = contact!!.source + contact_source.text = getPublicContactSource(contact!!.source) contact_toggle_favorite.apply { beVisible() @@ -302,11 +302,12 @@ class EditContactActivity : SimpleActivity() { private fun setupNewContact() { window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE) supportActionBar?.title = resources.getString(R.string.new_contact) - contact = Contact(0, "", "", "", "", ArrayList(), ArrayList(), ArrayList(), "", 0, 0, "") - contact_source.text = config.lastUsedContactSource + contact = Contact(0, "", "", "", "", ArrayList(), ArrayList(), ArrayList(), config.lastUsedContactSource, 0, 0, "") + contact_source.text = getPublicContactSource(contact!!.source) contact_source.setOnClickListener { - showContactSourcePicker(contact_source.value) { - contact_source.text = it + showContactSourcePicker(contact!!.source) { + contact!!.source = it + contact_source.text = getPublicContactSource(it) } } } @@ -515,7 +516,7 @@ class EditContactActivity : SimpleActivity() { phoneNumbers = getFilledPhoneNumbers() emails = getFilledEmails() events = getFilledEvents() - source = contact_source.value + source = contact!!.source starred = if (isContactStarred()) 1 else 0 Thread { diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ImportContactsDialog.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ImportContactsDialog.kt index a83c9f87..5c872afe 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ImportContactsDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ImportContactsDialog.kt @@ -4,22 +4,26 @@ import android.support.v7.app.AlertDialog import android.view.ViewGroup import com.simplemobiletools.commons.extensions.setupDialogStuff import com.simplemobiletools.commons.extensions.toast -import com.simplemobiletools.commons.extensions.value import com.simplemobiletools.contacts.R import com.simplemobiletools.contacts.activities.SimpleActivity import com.simplemobiletools.contacts.extensions.config +import com.simplemobiletools.contacts.extensions.getPublicContactSource import com.simplemobiletools.contacts.extensions.showContactSourcePicker import com.simplemobiletools.contacts.helpers.VcfImporter import com.simplemobiletools.contacts.helpers.VcfImporter.ImportResult.IMPORT_FAIL import kotlinx.android.synthetic.main.dialog_import_contacts.view.* class ImportContactsDialog(val activity: SimpleActivity, val path: String, private val callback: (refreshView: Boolean) -> Unit) { + private var targetContactSource = "" + init { val view = (activity.layoutInflater.inflate(R.layout.dialog_import_contacts, null) as ViewGroup).apply { - import_contacts_title.text = activity.config.lastUsedContactSource + targetContactSource = activity.config.lastUsedContactSource + import_contacts_title.text = activity.getPublicContactSource(targetContactSource) import_contacts_title.setOnClickListener { - activity.showContactSourcePicker(import_contacts_title.value) { - import_contacts_title.text = it + activity.showContactSourcePicker(targetContactSource) { + targetContactSource = it + import_contacts_title.text = activity.getPublicContactSource(it) } } } @@ -32,7 +36,7 @@ class ImportContactsDialog(val activity: SimpleActivity, val path: String, priva getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { activity.toast(R.string.importing) Thread { - val result = VcfImporter(activity).importContacts(path, view.import_contacts_title.value) + val result = VcfImporter(activity).importContacts(path, targetContactSource) handleParseResult(result) dismiss() }.start() diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Activity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Activity.kt index fafb689c..a7e390a9 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Activity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Activity.kt @@ -54,7 +54,12 @@ fun SimpleActivity.showContactSourcePicker(currentSource: String, callback: (new val sources = it.map { it.name } var currentSourceIndex = -1 sources.forEachIndexed { index, account -> - items.add(RadioItem(index, account)) + var publicAccount = account + if (account == config.localAccountName) { + publicAccount = getString(com.simplemobiletools.contacts.R.string.phone_storage) + } + + items.add(RadioItem(index, publicAccount)) if (account == currentSource) { currentSourceIndex = index } @@ -68,6 +73,8 @@ fun SimpleActivity.showContactSourcePicker(currentSource: String, callback: (new } } +fun SimpleActivity.getPublicContactSource(source: String) = if (source == config.localAccountName) getString(com.simplemobiletools.contacts.R.string.phone_storage) else source + fun BaseSimpleActivity.shareContacts(contacts: ArrayList) { val file = getTempFile() if (file == null) { From 6ec8355ac6b4fb38b125539a970f87927c2abb20 Mon Sep 17 00:00:00 2001 From: Phoenix1747 Date: Fri, 2 Feb 2018 14:52:33 +0100 Subject: [PATCH 09/35] Update strings.xml --- app/src/main/res/values-de/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 8d89a52a..530d1152 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -5,7 +5,7 @@ Einfügen… Aktualisiere… Gerätespeicher - Phone storage (not visible by other apps) + Gerätespeicher (nicht sichtbar für andere Apps) Neuer Kontakt Kontakt bearbeiten From 4a78ccedf2e538b6ea5db3646a29fe7fd6b53ad9 Mon Sep 17 00:00:00 2001 From: Nikola Trubitsyn Date: Fri, 2 Feb 2018 17:43:12 +0300 Subject: [PATCH 10/35] Update strings.xml --- app/src/main/res/values-ru/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 31ecbd97..bc349ac4 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -5,7 +5,7 @@ Добавление… Обновление… Память устройства - Phone storage (not visible by other apps) + Память устройства (не видна другим приложениям) Новый контакт Редактировать контакт From d4be18cb814dcbb8aa57f4f3c8038eeb7fd4a2f7 Mon Sep 17 00:00:00 2001 From: tibbi Date: Fri, 2 Feb 2018 16:29:14 +0100 Subject: [PATCH 11/35] fix #62, properly handle ansi encoded names --- .../contacts/helpers/Constants.kt | 2 +- .../contacts/helpers/QuotedPrintable.kt | 43 +++++++++++++++++++ .../contacts/helpers/VcfExporter.kt | 2 +- .../contacts/helpers/VcfImporter.kt | 10 +++-- 4 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 app/src/main/kotlin/com/simplemobiletools/contacts/helpers/QuotedPrintable.kt diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt index 67c98c8b..dab9f899 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt @@ -29,7 +29,7 @@ const val DEFAULT_EVENT_TYPE = CommonDataKinds.Event.TYPE_BIRTHDAY // export/import const val BEGIN_VCARD = "BEGIN:VCARD" const val END_VCARD = "END:VCARD" -const val N = "N:" +const val N = "N" const val TEL = "TEL" const val BDAY = "BDAY:" const val ANNIVERSARY = "ANNIVERSARY:" diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/QuotedPrintable.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/QuotedPrintable.kt new file mode 100644 index 00000000..7d415cc9 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/QuotedPrintable.kt @@ -0,0 +1,43 @@ +package com.simplemobiletools.contacts.helpers + +import java.io.ByteArrayOutputStream + +// https://alvinalexander.com/java/jwarehouse/android/core/java/com/google/android/mms/pdu/QuotedPrintable.java.shtml +object QuotedPrintable { + private const val ESCAPE_CHAR: Byte = '='.toByte() + fun decode(value: String?): String { + val bytes = value?.toByteArray() + if (bytes == null || bytes.isEmpty()) { + return "" + } + + val buffer = ByteArrayOutputStream() + var i = 0 + while (i < bytes.size) { + val b = bytes[i].toInt() + if (b == ESCAPE_CHAR.toInt()) { + try { + if ('\r' == bytes[i + 1].toChar() && '\n' == bytes[i + 2].toChar()) { + i += 2 + continue + } + + val u = Character.digit(bytes[++i].toChar(), 16) + val l = Character.digit(bytes[++i].toChar(), 16) + if (u == -1 || l == -1) { + return "" + } + + buffer.write(((u shl 4) + l).toChar().toInt()) + } catch (e: ArrayIndexOutOfBoundsException) { + return "" + } + + } else { + buffer.write(b) + } + i++ + } + return String(buffer.toByteArray()) + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfExporter.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfExporter.kt index 6bf5d141..74cc6ad7 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfExporter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfExporter.kt @@ -36,7 +36,7 @@ class VcfExporter { for (contact in contacts) { out.writeLn(BEGIN_VCARD) out.writeLn(VERSION_2_1) - out.writeLn("$N${contact.surname};${contact.firstName};${contact.middleName};;") + out.writeLn("$N:${contact.surname};${contact.firstName};${contact.middleName};;") contact.phoneNumbers.forEach { out.writeLn("$TEL;${getPhoneNumberLabel(it.type)}:${it.value}") diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfImporter.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfImporter.kt index d42f7fbd..6a5d8ee1 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfImporter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfImporter.kt @@ -82,11 +82,13 @@ class VcfImporter(val activity: SimpleActivity) { } private fun parseNames(names: String) { - val nameParts = names.split(";") - curSurname = nameParts[0] - curFirstName = nameParts[1] + val parts = names.split(":") + val isANSI = parts.first().toUpperCase().contains("QUOTED-PRINTABLE") + val nameParts = parts[1].split(";") + curSurname = if (isANSI) QuotedPrintable.decode(nameParts[0]) else nameParts[0] + curFirstName = if (isANSI) QuotedPrintable.decode(nameParts[1]) else nameParts[1] if (nameParts.size > 2) { - curMiddleName = nameParts[2] + curMiddleName = if (isANSI) QuotedPrintable.decode(nameParts[2]) else nameParts[2] } } From e4718ffa8232ae50d445d05636e875ac3c8fa93c Mon Sep 17 00:00:00 2001 From: tibbi Date: Fri, 2 Feb 2018 17:23:41 +0100 Subject: [PATCH 12/35] properly parse encoded names stretching to multiple lines too --- .../contacts/helpers/VcfImporter.kt | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfImporter.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfImporter.kt index 6a5d8ee1..5d991428 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfImporter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfImporter.kt @@ -34,6 +34,10 @@ class VcfImporter(val activity: SimpleActivity) { private var currentPhotoString = StringBuilder() private var currentPhotoCompressionFormat = Bitmap.CompressFormat.JPEG + private var isGettingName = false + private var currentNameIsANSI = false + private var currentNameString = StringBuilder() + private var contactsImported = 0 private var contactsFailed = 0 @@ -54,11 +58,15 @@ class VcfImporter(val activity: SimpleActivity) { isGettingPhoto = false } continue + } else if (line.startsWith('\t') && isGettingName) { + currentNameString.append(line.trimStart('\t')) + isGettingName = false + parseNames() } when { line.toUpperCase() == BEGIN_VCARD -> resetValues() - line.toUpperCase().startsWith(N) -> parseNames(line.substring(N.length)) + line.toUpperCase().startsWith(N) -> addNames(line.substring(N.length)) line.toUpperCase().startsWith(TEL) -> addPhoneNumber(line.substring(TEL.length)) line.toUpperCase().startsWith(EMAIL) -> addEmail(line.substring(EMAIL.length)) line.toUpperCase().startsWith(BDAY) -> addBirthday(line.substring(BDAY.length)) @@ -81,14 +89,23 @@ class VcfImporter(val activity: SimpleActivity) { } } - private fun parseNames(names: String) { + private fun addNames(names: String) { val parts = names.split(":") - val isANSI = parts.first().toUpperCase().contains("QUOTED-PRINTABLE") - val nameParts = parts[1].split(";") - curSurname = if (isANSI) QuotedPrintable.decode(nameParts[0]) else nameParts[0] - curFirstName = if (isANSI) QuotedPrintable.decode(nameParts[1]) else nameParts[1] + currentNameIsANSI = parts.first().toUpperCase().contains("QUOTED-PRINTABLE") + currentNameString.append(parts[1].trimEnd('=')) + if (!isGettingName && currentNameIsANSI && names.endsWith('=')) { + isGettingName = true + } else { + parseNames() + } + } + + private fun parseNames() { + val nameParts = currentNameString.split(";") + curSurname = if (currentNameIsANSI) QuotedPrintable.decode(nameParts[0]) else nameParts[0] + curFirstName = if (currentNameIsANSI) QuotedPrintable.decode(nameParts[1]) else nameParts[1] if (nameParts.size > 2) { - curMiddleName = if (isANSI) QuotedPrintable.decode(nameParts[2]) else nameParts[2] + curMiddleName = if (currentNameIsANSI) QuotedPrintable.decode(nameParts[2]) else nameParts[2] } } @@ -200,5 +217,9 @@ class VcfImporter(val activity: SimpleActivity) { isGettingPhoto = false currentPhotoString = StringBuilder() currentPhotoCompressionFormat = Bitmap.CompressFormat.JPEG + + isGettingName = false + currentNameIsANSI = false + currentNameString = StringBuilder() } } From 6fd77147258c98b5a9f4fe4f66d9e8bdb983848f Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 3 Feb 2018 23:17:19 +0100 Subject: [PATCH 13/35] properly encode exported names when appropriate --- .../contacts/helpers/QuotedPrintable.kt | 23 ++++++++++++++++++- .../contacts/helpers/VcfExporter.kt | 18 ++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/QuotedPrintable.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/QuotedPrintable.kt index 7d415cc9..ce974b81 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/QuotedPrintable.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/QuotedPrintable.kt @@ -1,6 +1,7 @@ package com.simplemobiletools.contacts.helpers import java.io.ByteArrayOutputStream +import java.net.URLEncoder // https://alvinalexander.com/java/jwarehouse/android/core/java/com/google/android/mms/pdu/QuotedPrintable.java.shtml object QuotedPrintable { @@ -18,7 +19,7 @@ object QuotedPrintable { if (b == ESCAPE_CHAR.toInt()) { try { if ('\r' == bytes[i + 1].toChar() && '\n' == bytes[i + 2].toChar()) { - i += 2 + i += 3 continue } @@ -40,4 +41,24 @@ object QuotedPrintable { } return String(buffer.toByteArray()) } + + fun encode(value: String): String { + val result = StringBuilder() + value.forEach { + if (it == ' ') { + result.append(' ') + } else { + val urlEncoded = urlEncode(it.toString()) + if (urlEncoded == it.toString()) { + val hex = String.format("%04x", it.toInt()).trimStart('0').toUpperCase() + result.append("=$hex") + } else { + result.append(urlEncoded) + } + } + } + return result.toString() + } + + fun urlEncode(value: String) = URLEncoder.encode(value, "UTF-8").replace("+", " ").replace('%', '=') } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfExporter.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfExporter.kt index 74cc6ad7..052447f0 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfExporter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfExporter.kt @@ -36,7 +36,7 @@ class VcfExporter { for (contact in contacts) { out.writeLn(BEGIN_VCARD) out.writeLn(VERSION_2_1) - out.writeLn("$N:${contact.surname};${contact.firstName};${contact.middleName};;") + out.writeLn("$N:${getNames(contact)}") contact.phoneNumbers.forEach { out.writeLn("$TEL;${getPhoneNumberLabel(it.type)}:${it.value}") @@ -91,6 +91,22 @@ class VcfExporter { }) } + private fun getNames(contact: Contact): String { + var firstName = contact.firstName + var surName = contact.surname + var middleName = contact.middleName + + if (QuotedPrintable.urlEncode(firstName) != firstName + || QuotedPrintable.urlEncode(surName) != surName + || QuotedPrintable.urlEncode(middleName) != middleName) { + firstName = QuotedPrintable.encode(firstName) + surName = QuotedPrintable.encode(surName) + middleName = QuotedPrintable.encode(middleName) + } + + return "$surName;$firstName;$middleName;;" + } + private fun getPhoneNumberLabel(type: Int) = when (type) { CommonDataKinds.Phone.TYPE_MOBILE -> CELL CommonDataKinds.Phone.TYPE_HOME -> HOME From e66ec05ba616aa2e932491a90675babd1caa7fda Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 3 Feb 2018 23:47:45 +0100 Subject: [PATCH 14/35] add the info declaring quoted-printable at exported vcf when necessary --- .../com/simplemobiletools/contacts/helpers/VcfExporter.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfExporter.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfExporter.kt index 052447f0..85fa0bec 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfExporter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/VcfExporter.kt @@ -36,7 +36,7 @@ class VcfExporter { for (contact in contacts) { out.writeLn(BEGIN_VCARD) out.writeLn(VERSION_2_1) - out.writeLn("$N:${getNames(contact)}") + out.writeLn("$N${getNames(contact)}") contact.phoneNumbers.forEach { out.writeLn("$TEL;${getPhoneNumberLabel(it.type)}:${it.value}") @@ -92,6 +92,7 @@ class VcfExporter { } private fun getNames(contact: Contact): String { + var result = "" var firstName = contact.firstName var surName = contact.surname var middleName = contact.middleName @@ -102,9 +103,10 @@ class VcfExporter { firstName = QuotedPrintable.encode(firstName) surName = QuotedPrintable.encode(surName) middleName = QuotedPrintable.encode(middleName) + result += ";CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE" } - return "$surName;$firstName;$middleName;;" + return "$result:$surName;$firstName;$middleName;;" } private fun getPhoneNumberLabel(type: Int) = when (type) { From b2fe9e6be33bca3f5806a8c9c4b1d397488efd90 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 3 Feb 2018 23:53:45 +0100 Subject: [PATCH 15/35] add a toggle for avoiding showing Whats New on startup --- app/build.gradle | 2 +- .../contacts/activities/SettingsActivity.kt | 9 +++++++++ app/src/main/res/layout/activity_settings.xml | 20 +++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 005739bf..e40cad5c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -45,7 +45,7 @@ ext { } dependencies { - implementation 'com.simplemobiletools:commons:3.9.9' + implementation 'com.simplemobiletools:commons:3.9.10' implementation 'joda-time:joda-time:2.9.9' debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanaryVersion" diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/SettingsActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/SettingsActivity.kt index 23b3bc80..294bc22e 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/SettingsActivity.kt @@ -20,6 +20,7 @@ class SettingsActivity : SimpleActivity() { setupCustomizeColors() setupUseEnglish() + setupAvoidWhatsNew() setupShowInfoBubble() setupShowContactThumbnails() setupShowPhoneNumbers() @@ -44,6 +45,14 @@ class SettingsActivity : SimpleActivity() { } } + private fun setupAvoidWhatsNew() { + settings_avoid_whats_new.isChecked = config.avoidWhatsNew + settings_avoid_whats_new_holder.setOnClickListener { + settings_avoid_whats_new.toggle() + config.avoidWhatsNew = settings_avoid_whats_new.isChecked + } + } + private fun setupShowInfoBubble() { settings_show_info_bubble.isChecked = config.showInfoBubble settings_show_info_bubble_holder.setOnClickListener { diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index c4415743..f9c46bfd 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -50,6 +50,26 @@ + + + + + + Date: Sat, 3 Feb 2018 23:56:08 +0100 Subject: [PATCH 16/35] update version to 3.1.4 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index e40cad5c..4433a8ca 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "com.simplemobiletools.contacts" minSdkVersion 16 targetSdkVersion 27 - versionCode 8 - versionName "3.1.3" + versionCode 9 + versionName "3.1.4" setProperty("archivesBaseName", "contacts") } From 5261f2e648edb9e6dc3b4af1066208440b1a2549 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 3 Feb 2018 23:56:14 +0100 Subject: [PATCH 17/35] updating changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67ec3478..6cc26c16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ Changelog ========== +Version 3.1.4 *(2018-02-03)* +---------------------------- + + * Add a unified "Phone storage" label to local phone storage + * Properly handle special characters at contact ex/importing + Version 3.1.3 *(2018-01-29)* ---------------------------- From ae58b7282de83486e72b2c85d5cb92df1474c1d2 Mon Sep 17 00:00:00 2001 From: Primokorn Date: Mon, 5 Feb 2018 09:27:33 +0100 Subject: [PATCH 18/35] Create FR strings.xml --- app/src/main/res/values-fr/strings.xml | 88 ++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 app/src/main/res/values-fr/strings.xml diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml new file mode 100644 index 00000000..fc0b2c8f --- /dev/null +++ b/app/src/main/res/values-fr/strings.xml @@ -0,0 +1,88 @@ + + Simple Contacts + Contacts + Adresse + Ajout… + Mise à jour… + Stockage du téléphone + Stockage du téléphone (non visible par d\'autres applis) + + Nouveau contact + Modifier contact + Sélectionner un contact + Sélectionner des contacts + Prénom + Nom + Surnom + + + Prendre une photo + Choisir une photo + Supprimer la photo + + + Appuyer pour appeler le contact + Commencer le nom par le surnom + Afficher les numéros de téléphone sur l\'écran principal + Afficher les vignettes des contacts + Sur appui du contact + Appeler le contact + Ouvrir l\éditeur de contact + Voir les détails du contact + + + E-mail + Maison + Travail + Autre + + + Numéro + Mobile + Principal + Fax travail + Fax maison + Bipeur + Aucun numéro de téléphone n\'a été trouvé + + + Naissance + Anniversaire + + + Il semble que vous n\'ayez pas encore ajouté de contact favori. + Ajouter des favoris + Ajouter aux favoris + Retirer des favoris + + + Rechercher des contacts + Rechercher des favoris + + + Importer des contacts + Exporter des contacts + Importer des contacts depuis un fichier .vcf + Exporter des contacts vers un fichier .vcf + Source du contact cible + Inclure les sources du contact + Nom du fichier (sans .vcf) + + + + Une appli de contacts pour gérer vos contacts sans pubs. + + Une appli simple pour créer et gérer vos contacts depuis n\'importe quelle source. Les contacts peuvent être stockés sur votre appareil mais aussi synchronisés via Google ou d\'autres comptes. Vous pouvez afficher vos contacts favoris dans une liste séparée. + + Vous pouvez l\'utiliser pour gérer les e-mail et événements de vos contacts. Elle permet de trier/filter via de multiples paramètres, et même afficher le surnom en premier. + + Aucune publicité ni de permission inutile. Elle est entièrement open source et vous permet de personnaliser les couleurs. + + Cette application fait parti d\'un groupe d\'applications. Vous pouvez trouver le reste des applis sur http://www.simplemobiletools.com + + + + From 3c834fe5212b2c5e2336f97ea7f55ca1b5423550 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 10 Feb 2018 16:43:47 +0100 Subject: [PATCH 19/35] add null checks at search query change updates --- .../simplemobiletools/contacts/fragments/MyViewPagerFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/fragments/MyViewPagerFragment.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/fragments/MyViewPagerFragment.kt index 5b66c30f..709ff448 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/fragments/MyViewPagerFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/fragments/MyViewPagerFragment.kt @@ -166,7 +166,7 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet) } fun onSearchQueryChanged(text: String) { - (fragment_list.adapter as ContactsAdapter).apply { + (fragment_list.adapter as? ContactsAdapter)?.apply { val filtered = contactsIgnoringSearch.filter { it.getFullName(startNameWithSurname).contains(text, true) || it.phoneNumbers.any { it.value.contains(text, true) } || From b8b118c62c4e14066ce98ec07149e3707eb3b571 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 10 Feb 2018 16:49:50 +0100 Subject: [PATCH 20/35] catch exceptions thrown at looking up contacts --- .../simplemobiletools/contacts/extensions/Context.kt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt index 86d978a5..1e310640 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt @@ -55,7 +55,9 @@ fun Context.getLookupUriRawId(dataUri: Uri): Int { val lookupKey = getLookupKeyFromUri(dataUri) if (lookupKey != null && isLollipopPlus()) { val uri = lookupContactUri(lookupKey, this) - return getContactUriRawId(uri) + if (uri != null) { + getContactUriRawId(uri) + } } return -1 } @@ -94,9 +96,13 @@ fun isEncodedContactUri(uri: Uri?): Boolean { return lastPathSegment == "encoded" } -fun lookupContactUri(lookup: String, context: Context): Uri { +fun lookupContactUri(lookup: String, context: Context): Uri? { val lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookup) - return ContactsContract.Contacts.lookupContact(context.contentResolver, lookupUri) + return try { + ContactsContract.Contacts.lookupContact(context.contentResolver, lookupUri) + } catch (e: Exception) { + null + } } fun Context.getCachePhoto(): File { From e1406b231d1c5660c81564a02958fed8d2bf0052 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 10 Feb 2018 16:51:19 +0100 Subject: [PATCH 21/35] add some null checks at addFavoritesDialog --- .../simplemobiletools/contacts/dialogs/AddFavoritesDialog.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/AddFavoritesDialog.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/AddFavoritesDialog.kt index c846d0fc..f31f0c4a 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/AddFavoritesDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/AddFavoritesDialog.kt @@ -58,7 +58,7 @@ class AddFavoritesDialog(val activity: SimpleActivity, private val callback: () val contactsHelper = ContactsHelper(activity) val allDisplayedContacts = ArrayList() allContacts.mapTo(allDisplayedContacts, { it }) - val selectedContacts = (view.select_contact_list.adapter as SelectContactsAdapter).getSelectedItemsSet() + val selectedContacts = (view?.select_contact_list?.adapter as? SelectContactsAdapter)?.getSelectedItemsSet() ?: LinkedHashSet() val contactIDsToAdd = selectedContacts.map { it.contactId.toString() } as ArrayList contactsHelper.addFavorites(contactIDsToAdd) From 7d2c4e18a37f51acf7042fa9fff1617edf9e01a6 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 10 Feb 2018 17:04:10 +0100 Subject: [PATCH 22/35] increase the font size at contact lists --- app/src/main/res/layout/item_add_favorite_with_number.xml | 4 ++-- app/src/main/res/layout/item_add_favorite_without_number.xml | 2 +- app/src/main/res/layout/item_contact_with_number.xml | 4 ++-- app/src/main/res/layout/item_contact_without_number.xml | 2 +- app/src/main/res/values/dimens.xml | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/src/main/res/layout/item_add_favorite_with_number.xml b/app/src/main/res/layout/item_add_favorite_with_number.xml index be9e0498..7747f757 100644 --- a/app/src/main/res/layout/item_add_favorite_with_number.xml +++ b/app/src/main/res/layout/item_add_favorite_with_number.xml @@ -34,7 +34,7 @@ android:paddingLeft="@dimen/small_margin" android:paddingRight="@dimen/small_margin" android:paddingTop="@dimen/small_margin" - android:textSize="@dimen/normal_text_size" + android:textSize="@dimen/bigger_text_size" tools:text="John Doe"/> diff --git a/app/src/main/res/layout/item_contact_without_number.xml b/app/src/main/res/layout/item_contact_without_number.xml index fc5eee9e..26b64417 100644 --- a/app/src/main/res/layout/item_contact_without_number.xml +++ b/app/src/main/res/layout/item_contact_without_number.xml @@ -31,7 +31,7 @@ android:ellipsize="end" android:gravity="center_vertical" android:maxLines="1" - android:textSize="@dimen/bigger_text_size" + android:textSize="@dimen/big_text_size" tools:text="John Doe"/> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index bb8f1a28..4061e3b5 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -3,5 +3,5 @@ 80dp 45dp 40dp - 48dp + 52dp From b1d4f2241b56898f9f3b3d8c05ce2f499593d8b6 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 10 Feb 2018 17:07:41 +0100 Subject: [PATCH 23/35] reduce side padding at setting items --- app/build.gradle | 2 +- app/src/main/res/layout/activity_settings.xml | 40 +++++++++++++++---- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 4433a8ca..cb38a5e9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -45,7 +45,7 @@ ext { } dependencies { - implementation 'com.simplemobiletools:commons:3.9.10' + implementation 'com.simplemobiletools:commons:3.11.2' implementation 'joda-time:joda-time:2.9.9' debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanaryVersion" diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index f9c46bfd..135429e7 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -17,7 +17,10 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/medium_margin" android:background="?attr/selectableItemBackground" - android:padding="@dimen/activity_margin"> + android:paddingBottom="@dimen/activity_margin" + android:paddingLeft="@dimen/normal_margin" + android:paddingRight="@dimen/normal_margin" + android:paddingTop="@dimen/activity_margin"> + android:paddingBottom="@dimen/activity_margin" + android:paddingLeft="@dimen/normal_margin" + android:paddingRight="@dimen/normal_margin" + android:paddingTop="@dimen/activity_margin"> + android:paddingBottom="@dimen/activity_margin" + android:paddingLeft="@dimen/normal_margin" + android:paddingRight="@dimen/normal_margin" + android:paddingTop="@dimen/activity_margin"> + android:paddingBottom="@dimen/activity_margin" + android:paddingLeft="@dimen/normal_margin" + android:paddingRight="@dimen/normal_margin" + android:paddingTop="@dimen/activity_margin"> + android:paddingBottom="@dimen/activity_margin" + android:paddingLeft="@dimen/normal_margin" + android:paddingRight="@dimen/normal_margin" + android:paddingTop="@dimen/activity_margin"> + android:paddingBottom="@dimen/activity_margin" + android:paddingLeft="@dimen/normal_margin" + android:paddingRight="@dimen/normal_margin" + android:paddingTop="@dimen/activity_margin"> + android:paddingBottom="@dimen/activity_margin" + android:paddingLeft="@dimen/normal_margin" + android:paddingRight="@dimen/normal_margin" + android:paddingTop="@dimen/activity_margin"> + android:paddingBottom="@dimen/activity_margin" + android:paddingLeft="@dimen/normal_margin" + android:paddingRight="@dimen/normal_margin" + android:paddingTop="@dimen/activity_margin"> Date: Sat, 10 Feb 2018 17:23:02 +0100 Subject: [PATCH 24/35] adding a new string for contact details --- app/src/main/res/values-de/strings.xml | 1 + app/src/main/res/values-fr/strings.xml | 1 + app/src/main/res/values-ko-rKR/strings.xml | 1 + app/src/main/res/values-pt/strings.xml | 1 + app/src/main/res/values-ru/strings.xml | 1 + app/src/main/res/values-sk/strings.xml | 1 + app/src/main/res/values-sv/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 8 files changed, 8 insertions(+) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 530d1152..30024fc8 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -9,6 +9,7 @@ Neuer Kontakt Kontakt bearbeiten + Contact details Kontakt auswählen Kontakte auswählen Vorname diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index fc0b2c8f..6c32e441 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -9,6 +9,7 @@ Nouveau contact Modifier contact + Contact details Sélectionner un contact Sélectionner des contacts Prénom diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index a9551607..708736a4 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -9,6 +9,7 @@ 새로운 연락처 연락처 수정 + Contact details 단건 연락처 선택 다건 연락처 선택 이름 diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index dac3a713..f5171470 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -9,6 +9,7 @@ Novo contacto Editar contacto + Contact details Select contact Select contacts First name diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index bc349ac4..5df94e81 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -9,6 +9,7 @@ Новый контакт Редактировать контакт + Contact details Выбрать контакт Выбрать контакты Имя diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index a8450b05..0fc3855f 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -9,6 +9,7 @@ Nový kontakt Upraviť kontakt + Detaily kontaktu Zvoľte kontakt Zvoľte kontakty Krstné meno diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index d15d5762..94305817 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -9,6 +9,7 @@ Ny kontakt Redigera kontakt + Contact details Välj kontakt Välj kontakter Förnamn diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 35c13d18..c78d99d3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -9,6 +9,7 @@ New contact Edit contact + Contact details Select contact Select contacts First name From 02850c99b64558485b97de2c06005e75fb4ad7cc Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 10 Feb 2018 20:28:04 +0100 Subject: [PATCH 25/35] remove the Contact details string --- app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-fr/strings.xml | 1 - app/src/main/res/values-ko-rKR/strings.xml | 1 - app/src/main/res/values-pt/strings.xml | 1 - app/src/main/res/values-ru/strings.xml | 1 - app/src/main/res/values-sk/strings.xml | 1 - app/src/main/res/values-sv/strings.xml | 1 - app/src/main/res/values/strings.xml | 1 - 8 files changed, 8 deletions(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 30024fc8..530d1152 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -9,7 +9,6 @@ Neuer Kontakt Kontakt bearbeiten - Contact details Kontakt auswählen Kontakte auswählen Vorname diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 6c32e441..fc0b2c8f 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -9,7 +9,6 @@ Nouveau contact Modifier contact - Contact details Sélectionner un contact Sélectionner des contacts Prénom diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index 708736a4..a9551607 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -9,7 +9,6 @@ 새로운 연락처 연락처 수정 - Contact details 단건 연락처 선택 다건 연락처 선택 이름 diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index f5171470..dac3a713 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -9,7 +9,6 @@ Novo contacto Editar contacto - Contact details Select contact Select contacts First name diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 5df94e81..bc349ac4 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -9,7 +9,6 @@ Новый контакт Редактировать контакт - Contact details Выбрать контакт Выбрать контакты Имя diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 0fc3855f..a8450b05 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -9,7 +9,6 @@ Nový kontakt Upraviť kontakt - Detaily kontaktu Zvoľte kontakt Zvoľte kontakty Krstné meno diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 94305817..d15d5762 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -9,7 +9,6 @@ Ny kontakt Redigera kontakt - Contact details Välj kontakt Välj kontakter Förnamn diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c78d99d3..35c13d18 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -9,7 +9,6 @@ New contact Edit contact - Contact details Select contact Select contacts First name From 32a9fa688407595781de6c40d476c2aaa848d74d Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 10 Feb 2018 21:19:34 +0100 Subject: [PATCH 26/35] create a separate activity for viewing contact details, without editing --- app/build.gradle | 2 +- app/src/main/AndroidManifest.xml | 5 + .../activities/EditContactActivity.kt | 20 +- .../activities/ViewContactActivity.kt | 401 ++++++++++++++++++ .../contacts/extensions/Context.kt | 4 +- .../main/res/layout/activity_edit_contact.xml | 9 +- .../main/res/layout/activity_view_contact.xml | 239 +++++++++++ .../{item_email.xml => item_edit_email.xml} | 0 ..._number.xml => item_edit_phone_number.xml} | 0 app/src/main/res/layout/item_event.xml | 4 +- app/src/main/res/layout/item_view_email.xml | 38 ++ .../res/layout/item_view_phone_number.xml | 38 ++ ...menu_contact.xml => menu_edit_contact.xml} | 10 +- app/src/main/res/menu/menu_view_contact.xml | 19 + 14 files changed, 766 insertions(+), 23 deletions(-) create mode 100644 app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt create mode 100644 app/src/main/res/layout/activity_view_contact.xml rename app/src/main/res/layout/{item_email.xml => item_edit_email.xml} (100%) rename app/src/main/res/layout/{item_phone_number.xml => item_edit_phone_number.xml} (100%) create mode 100644 app/src/main/res/layout/item_view_email.xml create mode 100644 app/src/main/res/layout/item_view_phone_number.xml rename app/src/main/res/menu/{menu_contact.xml => menu_edit_contact.xml} (100%) create mode 100644 app/src/main/res/menu/menu_view_contact.xml diff --git a/app/build.gradle b/app/build.gradle index cb38a5e9..92b6ece5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -45,7 +45,7 @@ ext { } dependencies { - implementation 'com.simplemobiletools:commons:3.11.2' + implementation 'com.simplemobiletools:commons:3.11.3' implementation 'joda-time:joda-time:2.9.9' debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanaryVersion" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index eb13cd3a..180ba002 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -74,6 +74,11 @@ android:label="@string/settings" android:parentActivityName=".activities.MainActivity"/> + + diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt index 1f7d4758..f73bc94f 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt @@ -39,9 +39,9 @@ import com.simplemobiletools.contacts.models.Email import com.simplemobiletools.contacts.models.Event import com.simplemobiletools.contacts.models.PhoneNumber import kotlinx.android.synthetic.main.activity_edit_contact.* -import kotlinx.android.synthetic.main.item_email.view.* +import kotlinx.android.synthetic.main.item_edit_email.view.* +import kotlinx.android.synthetic.main.item_edit_phone_number.view.* import kotlinx.android.synthetic.main.item_event.view.* -import kotlinx.android.synthetic.main.item_phone_number.view.* import org.joda.time.DateTime import org.joda.time.format.DateTimeFormat import java.text.DateFormat @@ -88,7 +88,7 @@ class EditContactActivity : SimpleActivity() { } override fun onCreateOptionsMenu(menu: Menu): Boolean { - menuInflater.inflate(R.menu.menu_contact, menu) + menuInflater.inflate(R.menu.menu_edit_contact, menu) if (wasActivityInitialized) { menu.findItem(R.id.delete).isVisible = contact?.id != 0 menu.findItem(R.id.share).isVisible = contact?.id != 0 @@ -244,11 +244,11 @@ class EditContactActivity : SimpleActivity() { contact!!.phoneNumbers.forEachIndexed { index, number -> var numberHolder = contact_numbers_holder.getChildAt(index) if (numberHolder == null) { - numberHolder = layoutInflater.inflate(R.layout.item_phone_number, contact_numbers_holder, false) + numberHolder = layoutInflater.inflate(R.layout.item_edit_phone_number, contact_numbers_holder, false) contact_numbers_holder.addView(numberHolder) } - (numberHolder as? ViewGroup)?.apply { + numberHolder!!.apply { contact_number.setText(number.value) setupPhoneNumberTypePicker(contact_number_type, number.type) } @@ -259,11 +259,11 @@ class EditContactActivity : SimpleActivity() { contact!!.emails.forEachIndexed { index, email -> var emailHolder = contact_emails_holder.getChildAt(index) if (emailHolder == null) { - emailHolder = layoutInflater.inflate(R.layout.item_email, contact_emails_holder, false) + emailHolder = layoutInflater.inflate(R.layout.item_edit_email, contact_emails_holder, false) contact_emails_holder.addView(emailHolder) } - (emailHolder as? ViewGroup)?.apply { + emailHolder!!.apply { contact_email.setText(email.value) setupEmailTypePicker(contact_email_type, email.type) } @@ -278,7 +278,7 @@ class EditContactActivity : SimpleActivity() { contact_events_holder.addView(eventHolder) } - (eventHolder as? ViewGroup)?.apply { + (eventHolder as ViewGroup).apply { val contactEvent = contact_event.apply { getDateTime(event.value, this) tag = event.value @@ -609,7 +609,7 @@ class EditContactActivity : SimpleActivity() { } private fun addNewPhoneNumberField() { - val numberHolder = layoutInflater.inflate(R.layout.item_phone_number, contact_numbers_holder, false) as ViewGroup + val numberHolder = layoutInflater.inflate(R.layout.item_edit_phone_number, contact_numbers_holder, false) as ViewGroup updateTextColors(numberHolder) setupPhoneNumberTypePicker(numberHolder.contact_number_type) contact_numbers_holder.addView(numberHolder) @@ -620,7 +620,7 @@ class EditContactActivity : SimpleActivity() { } private fun addNewEmailField() { - val emailHolder = layoutInflater.inflate(R.layout.item_email, contact_emails_holder, false) as ViewGroup + val emailHolder = layoutInflater.inflate(R.layout.item_edit_email, contact_emails_holder, false) as ViewGroup updateTextColors(emailHolder) setupEmailTypePicker(emailHolder.contact_email_type) contact_emails_holder.addView(emailHolder) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt new file mode 100644 index 00000000..0cc71dab --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt @@ -0,0 +1,401 @@ +package com.simplemobiletools.contacts.activities + +import android.content.Intent +import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.Drawable +import android.os.Bundle +import android.provider.ContactsContract +import android.provider.ContactsContract.CommonDataKinds +import android.view.Menu +import android.view.MenuItem +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.RelativeLayout +import android.widget.TextView +import com.bumptech.glide.Glide +import com.bumptech.glide.load.DataSource +import com.bumptech.glide.load.engine.DiskCacheStrategy +import com.bumptech.glide.load.engine.GlideException +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions +import com.bumptech.glide.request.RequestListener +import com.bumptech.glide.request.RequestOptions +import com.bumptech.glide.request.target.Target +import com.simplemobiletools.commons.dialogs.ConfirmationDialog +import com.simplemobiletools.commons.dialogs.RadioGroupDialog +import com.simplemobiletools.commons.extensions.* +import com.simplemobiletools.commons.helpers.PERMISSION_READ_CONTACTS +import com.simplemobiletools.commons.helpers.getDateFormats +import com.simplemobiletools.commons.models.RadioItem +import com.simplemobiletools.contacts.R +import com.simplemobiletools.contacts.extensions.* +import com.simplemobiletools.contacts.helpers.* +import com.simplemobiletools.contacts.models.Contact +import kotlinx.android.synthetic.main.activity_view_contact.* +import kotlinx.android.synthetic.main.item_event.view.* +import kotlinx.android.synthetic.main.item_view_email.view.* +import kotlinx.android.synthetic.main.item_view_phone_number.view.* +import org.joda.time.DateTime +import org.joda.time.format.DateTimeFormat +import java.text.DateFormat +import java.text.SimpleDateFormat +import java.util.* + +class ViewContactActivity : SimpleActivity() { + private var currentContactPhotoPath = "" + private var contact: Contact? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_view_contact) + + handlePermission(PERMISSION_READ_CONTACTS) { + if (it) { + initContact() + } else { + toast(R.string.no_contacts_permission) + finish() + } + } + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + menuInflater.inflate(R.menu.menu_view_contact, menu) + return true + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + R.id.edit -> editContact() + R.id.share -> shareContact() + R.id.delete -> deleteContact() + else -> return super.onOptionsItemSelected(item) + } + return true + } + + private fun initContact() { + var contactId = intent.getIntExtra(CONTACT_ID, 0) + val action = intent.action + if (contactId == 0 && (action == ContactsContract.QuickContact.ACTION_QUICK_CONTACT || action == Intent.ACTION_VIEW)) { + val data = intent.data + if (data != null) { + val rawId = if (data.path.contains("lookup")) { + getLookupUriRawId(data) + } else { + getContactUriRawId(data) + } + + if (rawId != -1) { + contactId = rawId + } + } + } + + if (contactId != 0) { + contact = ContactsHelper(this).getContactWithId(contactId) + if (contact == null) { + toast(R.string.unknown_error_occurred) + finish() + return + } + } + + if (contact == null) { + finish() + return + } + + setupEditContact() + + setupTypePickers() + contact_send_sms.beVisibleIf(contact!!.phoneNumbers.isNotEmpty()) + contact_start_call.beVisibleIf(contact!!.phoneNumbers.isNotEmpty()) + contact_send_email.beVisibleIf(contact!!.emails.isNotEmpty()) + + contact_photo.background = ColorDrawable(config.primaryColor) + + if (contact!!.photoUri.isEmpty()) { + showPhotoPlaceholder() + } else { + updateContactPhoto(contact!!.photoUri) + } + + val textColor = config.textColor + contact_send_sms.applyColorFilter(textColor) + contact_start_call.applyColorFilter(textColor) + contact_send_email.applyColorFilter(textColor) + contact_name_image.applyColorFilter(textColor) + contact_number_image.applyColorFilter(textColor) + contact_email_image.applyColorFilter(textColor) + contact_event_image.applyColorFilter(textColor) + contact_source_image.applyColorFilter(textColor) + + contact_send_sms.setOnClickListener { trySendSMS() } + contact_start_call.setOnClickListener { tryStartCall(contact!!) } + contact_send_email.setOnClickListener { trySendEmail() } + + updateTextColors(contact_scrollview) + invalidateOptionsMenu() + } + + private fun setupEditContact() { + window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN) + contact!!.apply { + contact_first_name.text = firstName + contact_first_name.beVisibleIf(firstName.isNotEmpty()) + + contact_middle_name.text = middleName + contact_middle_name.beVisibleIf(middleName.isNotEmpty()) + + contact_surname.text = surname + contact_surname.beVisibleIf(surname.isNotEmpty()) + + if (firstName.isEmpty() && middleName.isEmpty() && surname.isEmpty()) { + contact_name_image.beInvisible() + (contact_photo.layoutParams as RelativeLayout.LayoutParams).bottomMargin = resources.getDimension(R.dimen.medium_margin).toInt() + } + contact_source.text = getPublicContactSource(source) + } + + contact_toggle_favorite.apply { + beVisible() + setImageDrawable(getStarDrawable(contact!!.starred == 1)) + tag = contact!!.starred + applyColorFilter(config.textColor) + } + + setupPhoneNumbers() + setupEmails() + setupEvents() + } + + private fun setupPhoneNumbers() { + val phoneNumbers = contact!!.phoneNumbers + phoneNumbers.forEachIndexed { index, number -> + var numberHolder = contact_numbers_holder.getChildAt(index) + if (numberHolder == null) { + numberHolder = layoutInflater.inflate(R.layout.item_view_phone_number, contact_numbers_holder, false) + contact_numbers_holder.addView(numberHolder) + } + + numberHolder?.apply { + contact_number.text = number.value + setupPhoneNumberTypePicker(contact_number_type, number.type) + } + } + + contact_number_image.beVisibleIf(phoneNumbers.isNotEmpty()) + contact_numbers_holder.beVisibleIf(phoneNumbers.isNotEmpty()) + } + + private fun setupEmails() { + val emails = contact!!.emails + emails.forEachIndexed { index, email -> + var emailHolder = contact_emails_holder.getChildAt(index) + if (emailHolder == null) { + emailHolder = layoutInflater.inflate(R.layout.item_view_email, contact_emails_holder, false) + contact_emails_holder.addView(emailHolder) + } + + emailHolder?.apply { + contact_email.text = email.value + setupEmailTypePicker(contact_email_type, email.type) + } + } + + contact_email_image.beVisibleIf(emails.isNotEmpty()) + contact_emails_holder.beVisibleIf(emails.isNotEmpty()) + } + + private fun setupEvents() { + val events = contact!!.events + events.forEachIndexed { index, event -> + var eventHolder = contact_events_holder.getChildAt(index) + if (eventHolder == null) { + eventHolder = layoutInflater.inflate(R.layout.item_event, contact_events_holder, false) + contact_events_holder.addView(eventHolder) + } + + (eventHolder as? ViewGroup)?.apply { + contact_event.apply { + getDateTime(event.value, this) + tag = event.value + alpha = 1f + } + + setupEventTypePicker(this, event.type) + contact_event_remove.beGone() + } + } + + contact_event_image.beVisibleIf(events.isNotEmpty()) + contact_events_holder.beVisibleIf(events.isNotEmpty()) + } + + private fun editContact() { + Intent(applicationContext, EditContactActivity::class.java).apply { + putExtra(CONTACT_ID, contact!!.id) + startActivity(this) + } + } + + private fun shareContact() { + shareContacts(arrayListOf(contact!!)) + } + + private fun showPhotoPlaceholder() { + val placeholder = resources.getColoredBitmap(R.drawable.ic_person, config.primaryColor.getContrastColor()) + val padding = resources.getDimension(R.dimen.activity_margin).toInt() + contact_photo.setPadding(padding, padding, padding, padding) + contact_photo.setImageBitmap(placeholder) + currentContactPhotoPath = "" + } + + private fun updateContactPhoto(path: String) { + currentContactPhotoPath = path + val options = RequestOptions() + .diskCacheStrategy(DiskCacheStrategy.RESOURCE) + .centerCrop() + + Glide.with(this) + .load(path) + .transition(DrawableTransitionOptions.withCrossFade()) + .apply(options) + .listener(object : RequestListener { + override fun onResourceReady(resource: Drawable?, model: Any?, target: Target?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { + contact_photo.setPadding(0, 0, 0, 0) + return false + } + + override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean { + showPhotoPlaceholder() + return true + } + }).into(contact_photo) + } + + private fun setupTypePickers() { + if (contact!!.phoneNumbers.isEmpty()) { + val numberHolder = contact_numbers_holder.getChildAt(0) + (numberHolder as? ViewGroup)?.contact_number_type?.apply { + setupPhoneNumberTypePicker(this) + } + } + + if (contact!!.emails.isEmpty()) { + val emailHolder = contact_emails_holder.getChildAt(0) + (emailHolder as? ViewGroup)?.contact_email_type?.apply { + setupEmailTypePicker(this) + } + } + + if (contact!!.events.isEmpty()) { + val eventHolder = contact_events_holder.getChildAt(0) + (eventHolder as? ViewGroup)?.apply { + setupEventTypePicker(this) + } + } + } + + private fun setupPhoneNumberTypePicker(numberTypeField: TextView, type: Int = DEFAULT_PHONE_NUMBER_TYPE) { + numberTypeField.setText(getPhoneNumberTextId(type)) + } + + private fun setupEmailTypePicker(emailTypeField: TextView, type: Int = DEFAULT_EMAIL_TYPE) { + emailTypeField.setText(getEmailTextId(type)) + } + + private fun setupEventTypePicker(eventHolder: ViewGroup, type: Int = DEFAULT_EVENT_TYPE) { + eventHolder.contact_event_type.setText(getEventTextId(type)) + } + + private fun getDateTime(dateString: String, viewToUpdate: TextView? = null): DateTime { + val dateFormats = getDateFormats() + var date = DateTime() + for (format in dateFormats) { + try { + date = DateTime.parse(dateString, DateTimeFormat.forPattern(format)) + + val formatter = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault()) + var localPattern = (formatter as SimpleDateFormat).toLocalizedPattern() + + val hasYear = format.contains("y") + if (!hasYear) { + localPattern = localPattern.replace("y", "").trim() + date = date.withYear(DateTime().year) + } + + val formattedString = date.toString(localPattern) + viewToUpdate?.text = formattedString + break + } catch (ignored: Exception) { + } + } + return date + } + + private fun deleteContact() { + ConfirmationDialog(this) { + ContactsHelper(this).deleteContact(contact!!) + finish() + } + } + + private fun getStarDrawable(on: Boolean) = resources.getDrawable(if (on) R.drawable.ic_star_on_big else R.drawable.ic_star_off_big) + + private fun trySendSMS() { + val numbers = contact!!.phoneNumbers + if (numbers.size == 1) { + sendSMSIntent(numbers.first().value) + } else if (numbers.size > 1) { + val items = ArrayList() + numbers.forEachIndexed { index, phoneNumber -> + items.add(RadioItem(index, phoneNumber.value, phoneNumber.value)) + } + + RadioGroupDialog(this, items) { + sendSMSIntent(it as String) + } + } + } + + private fun trySendEmail() { + val emails = contact!!.emails + if (emails.size == 1) { + sendEmailIntent(emails.first().value) + } else if (emails.size > 1) { + val items = ArrayList() + emails.forEachIndexed { index, email -> + items.add(RadioItem(index, email.value, email.value)) + } + + RadioGroupDialog(this, items) { + sendEmailIntent(it as String) + } + } + } + + private fun getPhoneNumberTextId(type: Int) = when (type) { + CommonDataKinds.Phone.TYPE_MOBILE -> R.string.mobile + CommonDataKinds.Phone.TYPE_HOME -> R.string.home + CommonDataKinds.Phone.TYPE_WORK -> R.string.work + CommonDataKinds.Phone.TYPE_MAIN -> R.string.main_number + CommonDataKinds.Phone.TYPE_FAX_WORK -> R.string.work_fax + CommonDataKinds.Phone.TYPE_FAX_HOME -> R.string.home_fax + CommonDataKinds.Phone.TYPE_PAGER -> R.string.pager + else -> R.string.other + } + + private fun getEmailTextId(type: Int) = when (type) { + CommonDataKinds.Email.TYPE_HOME -> R.string.home + CommonDataKinds.Email.TYPE_WORK -> R.string.work + CommonDataKinds.Email.TYPE_MOBILE -> R.string.mobile + else -> R.string.other + } + + private fun getEventTextId(type: Int) = when (type) { + CommonDataKinds.Event.TYPE_BIRTHDAY -> R.string.birthday + CommonDataKinds.Event.TYPE_ANNIVERSARY -> R.string.anniversary + else -> R.string.other + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt index 1e310640..9dde3d5a 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt @@ -13,7 +13,7 @@ import com.simplemobiletools.commons.extensions.getIntValue import com.simplemobiletools.commons.extensions.isLollipopPlus import com.simplemobiletools.commons.extensions.toast import com.simplemobiletools.contacts.BuildConfig -import com.simplemobiletools.contacts.activities.EditContactActivity +import com.simplemobiletools.contacts.activities.ViewContactActivity import com.simplemobiletools.contacts.helpers.CONTACT_ID import com.simplemobiletools.contacts.helpers.Config import com.simplemobiletools.contacts.models.Contact @@ -22,7 +22,7 @@ import java.io.File val Context.config: Config get() = Config.newInstance(applicationContext) fun Context.openContact(contact: Contact) { - Intent(applicationContext, EditContactActivity::class.java).apply { + Intent(applicationContext, ViewContactActivity::class.java).apply { putExtra(CONTACT_ID, contact.id) startActivity(this) } diff --git a/app/src/main/res/layout/activity_edit_contact.xml b/app/src/main/res/layout/activity_edit_contact.xml index 9d1477b4..4767e5a0 100644 --- a/app/src/main/res/layout/activity_edit_contact.xml +++ b/app/src/main/res/layout/activity_edit_contact.xml @@ -10,7 +10,10 @@ android:id="@+id/contact_holder" android:layout_width="match_parent" android:layout_height="wrap_content" - android:padding="@dimen/activity_margin"> + android:paddingBottom="@dimen/medium_margin" + android:paddingLeft="@dimen/normal_margin" + android:paddingRight="@dimen/normal_margin" + android:paddingTop="@dimen/activity_margin"> - + @@ -193,7 +196,7 @@ android:layout_toRightOf="@+id/contact_name_image" android:orientation="vertical"> - + diff --git a/app/src/main/res/layout/activity_view_contact.xml b/app/src/main/res/layout/activity_view_contact.xml new file mode 100644 index 00000000..16e0ea48 --- /dev/null +++ b/app/src/main/res/layout/activity_view_contact.xml @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_email.xml b/app/src/main/res/layout/item_edit_email.xml similarity index 100% rename from app/src/main/res/layout/item_email.xml rename to app/src/main/res/layout/item_edit_email.xml diff --git a/app/src/main/res/layout/item_phone_number.xml b/app/src/main/res/layout/item_edit_phone_number.xml similarity index 100% rename from app/src/main/res/layout/item_phone_number.xml rename to app/src/main/res/layout/item_edit_phone_number.xml diff --git a/app/src/main/res/layout/item_event.xml b/app/src/main/res/layout/item_event.xml index 9d3c11c5..ae370f5d 100644 --- a/app/src/main/res/layout/item_event.xml +++ b/app/src/main/res/layout/item_event.xml @@ -15,8 +15,8 @@ android:alpha="0.5" android:background="?attr/selectableItemBackground" android:paddingBottom="@dimen/normal_margin" - android:paddingLeft="@dimen/medium_margin" - android:paddingRight="@dimen/medium_margin" + android:paddingLeft="@dimen/small_margin" + android:paddingRight="@dimen/small_margin" android:paddingTop="@dimen/normal_margin" android:text="@string/unknown" android:textSize="@dimen/bigger_text_size"/> diff --git a/app/src/main/res/layout/item_view_email.xml b/app/src/main/res/layout/item_view_email.xml new file mode 100644 index 00000000..8c4a2401 --- /dev/null +++ b/app/src/main/res/layout/item_view_email.xml @@ -0,0 +1,38 @@ + + + + + + + + diff --git a/app/src/main/res/layout/item_view_phone_number.xml b/app/src/main/res/layout/item_view_phone_number.xml new file mode 100644 index 00000000..8fca1a77 --- /dev/null +++ b/app/src/main/res/layout/item_view_phone_number.xml @@ -0,0 +1,38 @@ + + + + + + + + diff --git a/app/src/main/res/menu/menu_contact.xml b/app/src/main/res/menu/menu_edit_contact.xml similarity index 100% rename from app/src/main/res/menu/menu_contact.xml rename to app/src/main/res/menu/menu_edit_contact.xml index f7605732..12208f19 100644 --- a/app/src/main/res/menu/menu_contact.xml +++ b/app/src/main/res/menu/menu_edit_contact.xml @@ -6,14 +6,14 @@ android:icon="@drawable/ic_check" android:title="@string/save" app:showAsAction="ifRoom"/> - + diff --git a/app/src/main/res/menu/menu_view_contact.xml b/app/src/main/res/menu/menu_view_contact.xml new file mode 100644 index 00000000..4da28f74 --- /dev/null +++ b/app/src/main/res/menu/menu_view_contact.xml @@ -0,0 +1,19 @@ + + + + + + From 67511c07d00c0f893509c6f0ee294828f061a959 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 10 Feb 2018 21:50:38 +0100 Subject: [PATCH 27/35] move some edit and view shared functions into ContactActivity --- .../contacts/activities/ContactActivity.kt | 161 ++++++++++++++++++ .../activities/EditContactActivity.kt | 148 +--------------- .../activities/ViewContactActivity.kt | 159 +---------------- .../contacts/extensions/Context.kt | 2 +- 4 files changed, 174 insertions(+), 296 deletions(-) create mode 100644 app/src/main/kotlin/com/simplemobiletools/contacts/activities/ContactActivity.kt diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ContactActivity.kt new file mode 100644 index 00000000..12db14bf --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ContactActivity.kt @@ -0,0 +1,161 @@ +package com.simplemobiletools.contacts.activities + +import android.graphics.drawable.Drawable +import android.provider.ContactsContract +import android.widget.ImageView +import android.widget.TextView +import com.bumptech.glide.Glide +import com.bumptech.glide.load.DataSource +import com.bumptech.glide.load.engine.DiskCacheStrategy +import com.bumptech.glide.load.engine.GlideException +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions +import com.bumptech.glide.request.RequestListener +import com.bumptech.glide.request.RequestOptions +import com.bumptech.glide.request.target.Target +import com.simplemobiletools.commons.dialogs.ConfirmationDialog +import com.simplemobiletools.commons.dialogs.RadioGroupDialog +import com.simplemobiletools.commons.extensions.getColoredBitmap +import com.simplemobiletools.commons.extensions.getContrastColor +import com.simplemobiletools.commons.helpers.getDateFormats +import com.simplemobiletools.commons.models.RadioItem +import com.simplemobiletools.contacts.R +import com.simplemobiletools.contacts.extensions.config +import com.simplemobiletools.contacts.extensions.sendEmailIntent +import com.simplemobiletools.contacts.extensions.sendSMSIntent +import com.simplemobiletools.contacts.extensions.shareContacts +import com.simplemobiletools.contacts.helpers.ContactsHelper +import com.simplemobiletools.contacts.models.Contact +import org.joda.time.DateTime +import org.joda.time.format.DateTimeFormat +import java.text.DateFormat +import java.text.SimpleDateFormat +import java.util.* + +abstract class ContactActivity : SimpleActivity() { + var isEditActivity = false + var contact: Contact? = null + var currentContactPhotoPath = "" + + fun showPhotoPlaceholder(photoView: ImageView) { + val placeholder = resources.getColoredBitmap(R.drawable.ic_person, config.primaryColor.getContrastColor()) + val padding = resources.getDimension(R.dimen.activity_margin).toInt() + photoView.setPadding(padding, padding, padding, padding) + photoView.setImageBitmap(placeholder) + currentContactPhotoPath = "" + } + + fun updateContactPhoto(path: String, photoView: ImageView) { + currentContactPhotoPath = path + val options = RequestOptions() + .diskCacheStrategy(DiskCacheStrategy.RESOURCE) + .centerCrop() + + Glide.with(this) + .load(path) + .transition(DrawableTransitionOptions.withCrossFade()) + .apply(options) + .listener(object : RequestListener { + override fun onResourceReady(resource: Drawable?, model: Any?, target: Target?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { + photoView.setPadding(0, 0, 0, 0) + return false + } + + override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean { + showPhotoPlaceholder(photoView) + return true + } + }).into(photoView) + } + + fun getDateTime(dateString: String, viewToUpdate: TextView? = null): DateTime { + val dateFormats = getDateFormats() + var date = DateTime() + for (format in dateFormats) { + try { + date = DateTime.parse(dateString, DateTimeFormat.forPattern(format)) + + val formatter = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault()) + var localPattern = (formatter as SimpleDateFormat).toLocalizedPattern() + + val hasYear = format.contains("y") + if (!hasYear) { + localPattern = localPattern.replace("y", "").trim() + date = date.withYear(DateTime().year) + } + + val formattedString = date.toString(localPattern) + viewToUpdate?.text = formattedString + break + } catch (ignored: Exception) { + } + } + return date + } + + fun deleteContact() { + ConfirmationDialog(this) { + ContactsHelper(this).deleteContact(contact!!) + finish() + } + } + + fun shareContact() { + shareContacts(arrayListOf(contact!!)) + } + + fun trySendSMS() { + val numbers = contact!!.phoneNumbers + if (numbers.size == 1) { + sendSMSIntent(numbers.first().value) + } else if (numbers.size > 1) { + val items = ArrayList() + numbers.forEachIndexed { index, phoneNumber -> + items.add(RadioItem(index, phoneNumber.value, phoneNumber.value)) + } + + RadioGroupDialog(this, items) { + sendSMSIntent(it as String) + } + } + } + + fun trySendEmail() { + val emails = contact!!.emails + if (emails.size == 1) { + sendEmailIntent(emails.first().value) + } else if (emails.size > 1) { + val items = ArrayList() + emails.forEachIndexed { index, email -> + items.add(RadioItem(index, email.value, email.value)) + } + + RadioGroupDialog(this, items) { + sendEmailIntent(it as String) + } + } + } + + fun getPhoneNumberTextId(type: Int) = when (type) { + ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE -> R.string.mobile + ContactsContract.CommonDataKinds.Phone.TYPE_HOME -> R.string.home + ContactsContract.CommonDataKinds.Phone.TYPE_WORK -> R.string.work + ContactsContract.CommonDataKinds.Phone.TYPE_MAIN -> R.string.main_number + ContactsContract.CommonDataKinds.Phone.TYPE_FAX_WORK -> R.string.work_fax + ContactsContract.CommonDataKinds.Phone.TYPE_FAX_HOME -> R.string.home_fax + ContactsContract.CommonDataKinds.Phone.TYPE_PAGER -> R.string.pager + else -> R.string.other + } + + fun getEmailTextId(type: Int) = when (type) { + ContactsContract.CommonDataKinds.Email.TYPE_HOME -> R.string.home + ContactsContract.CommonDataKinds.Email.TYPE_WORK -> R.string.work + ContactsContract.CommonDataKinds.Email.TYPE_MOBILE -> R.string.mobile + else -> R.string.other + } + + fun getEventTextId(type: Int) = when (type) { + ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY -> R.string.birthday + ContactsContract.CommonDataKinds.Event.TYPE_ANNIVERSARY -> R.string.anniversary + else -> R.string.other + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt index f73bc94f..5c5f87c7 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt @@ -4,7 +4,6 @@ import android.app.DatePickerDialog import android.content.ClipData import android.content.Intent import android.graphics.drawable.ColorDrawable -import android.graphics.drawable.Drawable import android.net.Uri import android.os.Bundle import android.provider.ContactsContract @@ -16,20 +15,10 @@ import android.view.ViewGroup import android.view.WindowManager import android.widget.ImageView import android.widget.TextView -import com.bumptech.glide.Glide -import com.bumptech.glide.load.DataSource -import com.bumptech.glide.load.engine.DiskCacheStrategy -import com.bumptech.glide.load.engine.GlideException -import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions -import com.bumptech.glide.request.RequestListener -import com.bumptech.glide.request.RequestOptions -import com.bumptech.glide.request.target.Target -import com.simplemobiletools.commons.dialogs.ConfirmationDialog import com.simplemobiletools.commons.dialogs.RadioGroupDialog import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.PERMISSION_READ_CONTACTS import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_CONTACTS -import com.simplemobiletools.commons.helpers.getDateFormats import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.contacts.R import com.simplemobiletools.contacts.extensions.* @@ -44,11 +33,9 @@ import kotlinx.android.synthetic.main.item_edit_phone_number.view.* import kotlinx.android.synthetic.main.item_event.view.* import org.joda.time.DateTime import org.joda.time.format.DateTimeFormat -import java.text.DateFormat -import java.text.SimpleDateFormat import java.util.* -class EditContactActivity : SimpleActivity() { +class EditContactActivity : ContactActivity() { private val INTENT_TAKE_PHOTO = 1 private val INTENT_CHOOSE_PHOTO = 2 private val INTENT_CROP_PHOTO = 3 @@ -60,9 +47,7 @@ class EditContactActivity : SimpleActivity() { private val KEY_PHONE = "phone" private var wasActivityInitialized = false - private var currentContactPhotoPath = "" private var lastPhotoIntentUri: Uri? = null - private var contact: Contact? = null private var isSaving = false override fun onCreate(savedInstanceState: Bundle?) { @@ -111,7 +96,7 @@ class EditContactActivity : SimpleActivity() { if (resultCode == RESULT_OK) { when (requestCode) { INTENT_TAKE_PHOTO, INTENT_CHOOSE_PHOTO -> startCropPhotoIntent(lastPhotoIntentUri!!) - INTENT_CROP_PHOTO -> updateContactPhoto(lastPhotoIntentUri.toString()) + INTENT_CROP_PHOTO -> updateContactPhoto(lastPhotoIntentUri.toString(), contact_photo) } } } @@ -165,9 +150,9 @@ class EditContactActivity : SimpleActivity() { contact_photo.background = ColorDrawable(config.primaryColor) if (contact!!.photoUri.isEmpty()) { - showPhotoPlaceholder() + showPhotoPlaceholder(contact_photo) } else { - updateContactPhoto(contact!!.photoUri) + updateContactPhoto(contact!!.photoUri, contact_photo) } val textColor = config.textColor @@ -312,41 +297,6 @@ class EditContactActivity : SimpleActivity() { } } - private fun shareContact() { - shareContacts(arrayListOf(contact!!)) - } - - private fun showPhotoPlaceholder() { - val placeholder = resources.getColoredBitmap(R.drawable.ic_person, config.primaryColor.getContrastColor()) - val padding = resources.getDimension(R.dimen.activity_margin).toInt() - contact_photo.setPadding(padding, padding, padding, padding) - contact_photo.setImageBitmap(placeholder) - currentContactPhotoPath = "" - } - - private fun updateContactPhoto(path: String) { - currentContactPhotoPath = path - val options = RequestOptions() - .diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop() - - Glide.with(this) - .load(path) - .transition(DrawableTransitionOptions.withCrossFade()) - .apply(options) - .listener(object : RequestListener { - override fun onResourceReady(resource: Drawable?, model: Any?, target: Target?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { - contact_photo.setPadding(0, 0, 0, 0) - return false - } - - override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean { - showPhotoPlaceholder() - return true - } - }).into(contact_photo) - } - private fun setupTypePickers() { if (contact!!.phoneNumbers.isEmpty()) { val numberHolder = contact_numbers_holder.getChildAt(0) @@ -431,31 +381,6 @@ class EditContactActivity : SimpleActivity() { removeContactEventButton.beGone() } - private fun getDateTime(dateString: String, viewToUpdate: TextView? = null): DateTime { - val dateFormats = getDateFormats() - var date = DateTime() - for (format in dateFormats) { - try { - date = DateTime.parse(dateString, DateTimeFormat.forPattern(format)) - - val formatter = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault()) - var localPattern = (formatter as SimpleDateFormat).toLocalizedPattern() - - val hasYear = format.contains("y") - if (!hasYear) { - localPattern = localPattern.replace("y", "").trim() - date = date.withYear(DateTime().year) - } - - val formattedString = date.toString(localPattern) - viewToUpdate?.text = formattedString - break - } catch (ignored: Exception) { - } - } - return date - } - private fun showNumberTypePicker(numberTypeField: TextView) { val items = arrayListOf( RadioItem(CommonDataKinds.Phone.TYPE_MOBILE, getString(R.string.mobile)), @@ -637,13 +562,6 @@ class EditContactActivity : SimpleActivity() { contact_events_holder.addView(eventHolder) } - private fun deleteContact() { - ConfirmationDialog(this) { - ContactsHelper(this).deleteContact(contact!!) - finish() - } - } - private fun toggleFavorite() { val isStarred = isContactStarred() contact_toggle_favorite.apply { @@ -671,39 +589,7 @@ class EditContactActivity : SimpleActivity() { when (it as Int) { TAKE_PHOTO -> startTakePhotoIntent() CHOOSE_PHOTO -> startChoosePhotoIntent() - else -> showPhotoPlaceholder() - } - } - } - - private fun trySendSMS() { - val numbers = contact!!.phoneNumbers - if (numbers.size == 1) { - sendSMSIntent(numbers.first().value) - } else if (numbers.size > 1) { - val items = ArrayList() - numbers.forEachIndexed { index, phoneNumber -> - items.add(RadioItem(index, phoneNumber.value, phoneNumber.value)) - } - - RadioGroupDialog(this, items) { - sendSMSIntent(it as String) - } - } - } - - private fun trySendEmail() { - val emails = contact!!.emails - if (emails.size == 1) { - sendEmailIntent(emails.first().value) - } else if (emails.size > 1) { - val items = ArrayList() - emails.forEachIndexed { index, email -> - items.add(RadioItem(index, email.value, email.value)) - } - - RadioGroupDialog(this, items) { - sendEmailIntent(it as String) + else -> showPhotoPlaceholder(contact_photo) } } } @@ -737,17 +623,6 @@ class EditContactActivity : SimpleActivity() { } } - private fun getPhoneNumberTextId(type: Int) = when (type) { - CommonDataKinds.Phone.TYPE_MOBILE -> R.string.mobile - CommonDataKinds.Phone.TYPE_HOME -> R.string.home - CommonDataKinds.Phone.TYPE_WORK -> R.string.work - CommonDataKinds.Phone.TYPE_MAIN -> R.string.main_number - CommonDataKinds.Phone.TYPE_FAX_WORK -> R.string.work_fax - CommonDataKinds.Phone.TYPE_FAX_HOME -> R.string.home_fax - CommonDataKinds.Phone.TYPE_PAGER -> R.string.pager - else -> R.string.other - } - private fun getPhoneNumberTypeId(value: String) = when (value) { getString(R.string.mobile) -> CommonDataKinds.Phone.TYPE_MOBILE getString(R.string.home) -> CommonDataKinds.Phone.TYPE_HOME @@ -759,13 +634,6 @@ class EditContactActivity : SimpleActivity() { else -> CommonDataKinds.Phone.TYPE_OTHER } - private fun getEmailTextId(type: Int) = when (type) { - CommonDataKinds.Email.TYPE_HOME -> R.string.home - CommonDataKinds.Email.TYPE_WORK -> R.string.work - CommonDataKinds.Email.TYPE_MOBILE -> R.string.mobile - else -> R.string.other - } - private fun getEmailTypeId(value: String) = when (value) { getString(R.string.home) -> CommonDataKinds.Email.TYPE_HOME getString(R.string.work) -> CommonDataKinds.Email.TYPE_WORK @@ -773,12 +641,6 @@ class EditContactActivity : SimpleActivity() { else -> CommonDataKinds.Email.TYPE_OTHER } - private fun getEventTextId(type: Int) = when (type) { - CommonDataKinds.Event.TYPE_BIRTHDAY -> R.string.birthday - CommonDataKinds.Event.TYPE_ANNIVERSARY -> R.string.anniversary - else -> R.string.other - } - private fun getEventTypeId(value: String) = when (value) { getString(R.string.birthday) -> CommonDataKinds.Event.TYPE_BIRTHDAY getString(R.string.anniversary) -> CommonDataKinds.Event.TYPE_ANNIVERSARY diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt index 0cc71dab..8db8f01a 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt @@ -2,51 +2,29 @@ package com.simplemobiletools.contacts.activities import android.content.Intent import android.graphics.drawable.ColorDrawable -import android.graphics.drawable.Drawable import android.os.Bundle import android.provider.ContactsContract -import android.provider.ContactsContract.CommonDataKinds import android.view.Menu import android.view.MenuItem import android.view.ViewGroup import android.view.WindowManager import android.widget.RelativeLayout import android.widget.TextView -import com.bumptech.glide.Glide -import com.bumptech.glide.load.DataSource -import com.bumptech.glide.load.engine.DiskCacheStrategy -import com.bumptech.glide.load.engine.GlideException -import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions -import com.bumptech.glide.request.RequestListener -import com.bumptech.glide.request.RequestOptions -import com.bumptech.glide.request.target.Target -import com.simplemobiletools.commons.dialogs.ConfirmationDialog -import com.simplemobiletools.commons.dialogs.RadioGroupDialog import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.PERMISSION_READ_CONTACTS -import com.simplemobiletools.commons.helpers.getDateFormats -import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.contacts.R import com.simplemobiletools.contacts.extensions.* import com.simplemobiletools.contacts.helpers.* -import com.simplemobiletools.contacts.models.Contact import kotlinx.android.synthetic.main.activity_view_contact.* import kotlinx.android.synthetic.main.item_event.view.* import kotlinx.android.synthetic.main.item_view_email.view.* import kotlinx.android.synthetic.main.item_view_phone_number.view.* -import org.joda.time.DateTime -import org.joda.time.format.DateTimeFormat -import java.text.DateFormat -import java.text.SimpleDateFormat -import java.util.* - -class ViewContactActivity : SimpleActivity() { - private var currentContactPhotoPath = "" - private var contact: Contact? = null +class ViewContactActivity : ContactActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_view_contact) + isEditActivity = false handlePermission(PERMISSION_READ_CONTACTS) { if (it) { @@ -115,9 +93,9 @@ class ViewContactActivity : SimpleActivity() { contact_photo.background = ColorDrawable(config.primaryColor) if (contact!!.photoUri.isEmpty()) { - showPhotoPlaceholder() + showPhotoPlaceholder(contact_photo) } else { - updateContactPhoto(contact!!.photoUri) + updateContactPhoto(contact!!.photoUri, contact_photo) } val textColor = config.textColor @@ -178,7 +156,7 @@ class ViewContactActivity : SimpleActivity() { contact_numbers_holder.addView(numberHolder) } - numberHolder?.apply { + numberHolder!!.apply { contact_number.text = number.value setupPhoneNumberTypePicker(contact_number_type, number.type) } @@ -197,7 +175,7 @@ class ViewContactActivity : SimpleActivity() { contact_emails_holder.addView(emailHolder) } - emailHolder?.apply { + emailHolder!!.apply { contact_email.text = email.value setupEmailTypePicker(contact_email_type, email.type) } @@ -216,7 +194,7 @@ class ViewContactActivity : SimpleActivity() { contact_events_holder.addView(eventHolder) } - (eventHolder as? ViewGroup)?.apply { + (eventHolder as ViewGroup).apply { contact_event.apply { getDateTime(event.value, this) tag = event.value @@ -239,41 +217,6 @@ class ViewContactActivity : SimpleActivity() { } } - private fun shareContact() { - shareContacts(arrayListOf(contact!!)) - } - - private fun showPhotoPlaceholder() { - val placeholder = resources.getColoredBitmap(R.drawable.ic_person, config.primaryColor.getContrastColor()) - val padding = resources.getDimension(R.dimen.activity_margin).toInt() - contact_photo.setPadding(padding, padding, padding, padding) - contact_photo.setImageBitmap(placeholder) - currentContactPhotoPath = "" - } - - private fun updateContactPhoto(path: String) { - currentContactPhotoPath = path - val options = RequestOptions() - .diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .centerCrop() - - Glide.with(this) - .load(path) - .transition(DrawableTransitionOptions.withCrossFade()) - .apply(options) - .listener(object : RequestListener { - override fun onResourceReady(resource: Drawable?, model: Any?, target: Target?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { - contact_photo.setPadding(0, 0, 0, 0) - return false - } - - override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean { - showPhotoPlaceholder() - return true - } - }).into(contact_photo) - } - private fun setupTypePickers() { if (contact!!.phoneNumbers.isEmpty()) { val numberHolder = contact_numbers_holder.getChildAt(0) @@ -309,93 +252,5 @@ class ViewContactActivity : SimpleActivity() { eventHolder.contact_event_type.setText(getEventTextId(type)) } - private fun getDateTime(dateString: String, viewToUpdate: TextView? = null): DateTime { - val dateFormats = getDateFormats() - var date = DateTime() - for (format in dateFormats) { - try { - date = DateTime.parse(dateString, DateTimeFormat.forPattern(format)) - - val formatter = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault()) - var localPattern = (formatter as SimpleDateFormat).toLocalizedPattern() - - val hasYear = format.contains("y") - if (!hasYear) { - localPattern = localPattern.replace("y", "").trim() - date = date.withYear(DateTime().year) - } - - val formattedString = date.toString(localPattern) - viewToUpdate?.text = formattedString - break - } catch (ignored: Exception) { - } - } - return date - } - - private fun deleteContact() { - ConfirmationDialog(this) { - ContactsHelper(this).deleteContact(contact!!) - finish() - } - } - private fun getStarDrawable(on: Boolean) = resources.getDrawable(if (on) R.drawable.ic_star_on_big else R.drawable.ic_star_off_big) - - private fun trySendSMS() { - val numbers = contact!!.phoneNumbers - if (numbers.size == 1) { - sendSMSIntent(numbers.first().value) - } else if (numbers.size > 1) { - val items = ArrayList() - numbers.forEachIndexed { index, phoneNumber -> - items.add(RadioItem(index, phoneNumber.value, phoneNumber.value)) - } - - RadioGroupDialog(this, items) { - sendSMSIntent(it as String) - } - } - } - - private fun trySendEmail() { - val emails = contact!!.emails - if (emails.size == 1) { - sendEmailIntent(emails.first().value) - } else if (emails.size > 1) { - val items = ArrayList() - emails.forEachIndexed { index, email -> - items.add(RadioItem(index, email.value, email.value)) - } - - RadioGroupDialog(this, items) { - sendEmailIntent(it as String) - } - } - } - - private fun getPhoneNumberTextId(type: Int) = when (type) { - CommonDataKinds.Phone.TYPE_MOBILE -> R.string.mobile - CommonDataKinds.Phone.TYPE_HOME -> R.string.home - CommonDataKinds.Phone.TYPE_WORK -> R.string.work - CommonDataKinds.Phone.TYPE_MAIN -> R.string.main_number - CommonDataKinds.Phone.TYPE_FAX_WORK -> R.string.work_fax - CommonDataKinds.Phone.TYPE_FAX_HOME -> R.string.home_fax - CommonDataKinds.Phone.TYPE_PAGER -> R.string.pager - else -> R.string.other - } - - private fun getEmailTextId(type: Int) = when (type) { - CommonDataKinds.Email.TYPE_HOME -> R.string.home - CommonDataKinds.Email.TYPE_WORK -> R.string.work - CommonDataKinds.Email.TYPE_MOBILE -> R.string.mobile - else -> R.string.other - } - - private fun getEventTextId(type: Int) = when (type) { - CommonDataKinds.Event.TYPE_BIRTHDAY -> R.string.birthday - CommonDataKinds.Event.TYPE_ANNIVERSARY -> R.string.anniversary - else -> R.string.other - } } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt index 9dde3d5a..1fed4980 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt @@ -8,11 +8,11 @@ import android.net.Uri import android.os.Build import android.provider.ContactsContract import android.support.v4.content.FileProvider -import com.simplemobiletools.commons.R import com.simplemobiletools.commons.extensions.getIntValue import com.simplemobiletools.commons.extensions.isLollipopPlus import com.simplemobiletools.commons.extensions.toast import com.simplemobiletools.contacts.BuildConfig +import com.simplemobiletools.contacts.R import com.simplemobiletools.contacts.activities.ViewContactActivity import com.simplemobiletools.contacts.helpers.CONTACT_ID import com.simplemobiletools.contacts.helpers.Config From b1c8b5a94183694a690e0c55bc285f131f56fefd Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 10 Feb 2018 21:55:28 +0100 Subject: [PATCH 28/35] remove the "Call contact on click" setting --- .../contacts/activities/SettingsActivity.kt | 9 -------- .../contacts/adapters/ContactsAdapter.kt | 2 +- .../contacts/fragments/MyViewPagerFragment.kt | 2 +- .../contacts/helpers/Config.kt | 4 ---- .../contacts/helpers/Constants.kt | 1 - app/src/main/res/layout/activity_settings.xml | 23 ------------------- app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-fr/strings.xml | 1 - app/src/main/res/values-ko-rKR/strings.xml | 1 - app/src/main/res/values-pt/strings.xml | 1 - app/src/main/res/values-ru/strings.xml | 1 - app/src/main/res/values-sk/strings.xml | 1 - app/src/main/res/values-sv/strings.xml | 1 - app/src/main/res/values/strings.xml | 1 - 14 files changed, 2 insertions(+), 47 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/SettingsActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/SettingsActivity.kt index 294bc22e..5dfdc8d3 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/SettingsActivity.kt @@ -24,7 +24,6 @@ class SettingsActivity : SimpleActivity() { setupShowInfoBubble() setupShowContactThumbnails() setupShowPhoneNumbers() - setupCallContactOnClick() setupStartNameWithSurname() updateTextColors(settings_holder) } @@ -77,14 +76,6 @@ class SettingsActivity : SimpleActivity() { } } - private fun setupCallContactOnClick() { - settings_call_contact_on_click.isChecked = config.callContact - settings_call_contact_on_click_holder.setOnClickListener { - settings_call_contact_on_click.toggle() - config.callContact = settings_call_contact_on_click.isChecked - } - } - private fun setupStartNameWithSurname() { settings_start_with_surname.isChecked = config.startNameWithSurname settings_start_with_surname_holder.setOnClickListener { diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/ContactsAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/ContactsAdapter.kt index fc72ab44..0109cc59 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/ContactsAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/ContactsAdapter.kt @@ -51,7 +51,7 @@ class ContactsAdapter(activity: SimpleActivity, var contactItems: MutableList get() = prefs.getStringSet(DISPLAY_CONTACT_SOURCES, hashSetOf("-1")) set(displayContactSources) = prefs.edit().remove(DISPLAY_CONTACT_SOURCES).putStringSet(DISPLAY_CONTACT_SOURCES, displayContactSources).apply() diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt index dab9f899..5453d913 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt @@ -3,7 +3,6 @@ package com.simplemobiletools.contacts.helpers import android.provider.ContactsContract.CommonDataKinds // shared prefs -const val CALL_CONTACT_ON_CLICK = "call_contact_on_click" const val SHOW_CONTACT_THUMBNAILS = "show_contact_thumbnails" const val SHOW_PHONE_NUMBERS = "show_phone_numbers" const val DISPLAY_CONTACT_SOURCES = "display_contact_sources" diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 135429e7..8bdb6e93 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -148,29 +148,6 @@ - - - - - - Foto entfernen - Kontakt bei Klick anrufen Namen mit Nachnamen beginnen Zeige Telefonnummern im Hauptmenü Zeige Vorschaubilder für Kontakte diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index fc0b2c8f..333ac75d 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -21,7 +21,6 @@ Supprimer la photo - Appuyer pour appeler le contact Commencer le nom par le surnom Afficher les numéros de téléphone sur l\'écran principal Afficher les vignettes des contacts diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index a9551607..66716cf5 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -21,7 +21,6 @@ 사진 삭제 - 클릭으로 전화걸기 성을 먼저 표시 메인 스크린에 전화번호 표시 Show contact thumbnails diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index dac3a713..70db9bfa 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -21,7 +21,6 @@ Remove photo - Call contact on click Start name with surname Show phone numbers on the main screen Show contact thumbnails diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index bc349ac4..0377228e 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -21,7 +21,6 @@ Удалить фото - Вызывать контакт при нажатии Показывать сначала фамилию Показывать номера телефонов на главном экране Показывать фото контакта diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index a8450b05..9ba0e348 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -21,7 +21,6 @@ Odstrániť foto - Zavolať kontakt po kliknutí Začať meno priezviskom Zobraziť telefónne čísla na hlavnej obrazovke Zobraziť obrázky kontaktov diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index d15d5762..a5714f11 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -21,7 +21,6 @@ Ta bort foto - Ring kontakter när jag trycker på dem Visa efternamn först Visa telefonnummer i huvudvyn Show contact thumbnails diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 35c13d18..761dec5e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -21,7 +21,6 @@ Remove photo - Call contact on click Start name with surname Show phone numbers on the main screen Show contact thumbnails From 962ff318e6a3c0f92bf2aa0601e2450e5b85c2d2 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 10 Feb 2018 22:17:38 +0100 Subject: [PATCH 29/35] add a setting for selecting what should happen on contact click --- .../contacts/activities/SettingsActivity.kt | 27 ++++++++++++++ .../activities/ViewContactActivity.kt | 9 +---- .../contacts/adapters/ContactsAdapter.kt | 5 ++- .../contacts/extensions/Context.kt | 10 +++++- .../contacts/fragments/MyViewPagerFragment.kt | 24 +++++++------ .../contacts/helpers/Config.kt | 4 +++ .../contacts/helpers/Constants.kt | 5 +++ app/src/main/res/layout/activity_settings.xml | 35 +++++++++++++++++++ app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-fr/strings.xml | 1 - app/src/main/res/values-ko-rKR/strings.xml | 1 - app/src/main/res/values-pt/strings.xml | 1 - app/src/main/res/values-ru/strings.xml | 1 - app/src/main/res/values-sk/strings.xml | 1 - app/src/main/res/values-sv/strings.xml | 1 - app/src/main/res/values/strings.xml | 1 - 16 files changed, 96 insertions(+), 31 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/SettingsActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/SettingsActivity.kt index 5dfdc8d3..bfc35114 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/SettingsActivity.kt @@ -1,11 +1,16 @@ package com.simplemobiletools.contacts.activities import android.os.Bundle +import com.simplemobiletools.commons.dialogs.RadioGroupDialog import com.simplemobiletools.commons.extensions.beVisibleIf import com.simplemobiletools.commons.extensions.updateTextColors import com.simplemobiletools.commons.extensions.useEnglishToggled +import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.contacts.R import com.simplemobiletools.contacts.extensions.config +import com.simplemobiletools.contacts.helpers.ON_CLICK_CALL_CONTACT +import com.simplemobiletools.contacts.helpers.ON_CLICK_EDIT_CONTACT +import com.simplemobiletools.contacts.helpers.ON_CLICK_VIEW_CONTACT import kotlinx.android.synthetic.main.activity_settings.* import java.util.* @@ -25,6 +30,7 @@ class SettingsActivity : SimpleActivity() { setupShowContactThumbnails() setupShowPhoneNumbers() setupStartNameWithSurname() + setupOnContactClick() updateTextColors(settings_holder) } @@ -83,4 +89,25 @@ class SettingsActivity : SimpleActivity() { config.startNameWithSurname = settings_start_with_surname.isChecked } } + + private fun setupOnContactClick() { + settings_on_contact_click.text = getOnContactClickText() + settings_on_contact_click_holder.setOnClickListener { + val items = arrayListOf( + RadioItem(ON_CLICK_CALL_CONTACT, getString(R.string.call_contact)), + RadioItem(ON_CLICK_VIEW_CONTACT, getString(R.string.view_contact)), + RadioItem(ON_CLICK_EDIT_CONTACT, getString(R.string.edit_contact))) + + RadioGroupDialog(this@SettingsActivity, items, config.onContactClick) { + config.onContactClick = it as Int + settings_on_contact_click.text = getOnContactClickText() + } + } + } + + private fun getOnContactClickText() = getString(when (config.onContactClick) { + ON_CLICK_CALL_CONTACT -> R.string.call_contact + ON_CLICK_VIEW_CONTACT -> R.string.view_contact + else -> R.string.edit_contact + }) } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt index 8db8f01a..5119db88 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt @@ -43,7 +43,7 @@ class ViewContactActivity : ContactActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { - R.id.edit -> editContact() + R.id.edit -> editContact(contact!!) R.id.share -> shareContact() R.id.delete -> deleteContact() else -> return super.onOptionsItemSelected(item) @@ -210,13 +210,6 @@ class ViewContactActivity : ContactActivity() { contact_events_holder.beVisibleIf(events.isNotEmpty()) } - private fun editContact() { - Intent(applicationContext, EditContactActivity::class.java).apply { - putExtra(CONTACT_ID, contact!!.id) - startActivity(this) - } - } - private fun setupTypePickers() { if (contact!!.phoneNumbers.isEmpty()) { val numberHolder = contact_numbers_holder.getChildAt(0) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/ContactsAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/ContactsAdapter.kt index 0109cc59..9d49925e 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/ContactsAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/adapters/ContactsAdapter.kt @@ -19,7 +19,7 @@ import com.simplemobiletools.commons.views.MyRecyclerView import com.simplemobiletools.contacts.R import com.simplemobiletools.contacts.activities.SimpleActivity import com.simplemobiletools.contacts.extensions.config -import com.simplemobiletools.contacts.extensions.openContact +import com.simplemobiletools.contacts.extensions.editContact import com.simplemobiletools.contacts.extensions.shareContacts import com.simplemobiletools.contacts.helpers.ContactsHelper import com.simplemobiletools.contacts.interfaces.RefreshContactsListener @@ -104,8 +104,7 @@ class ContactsAdapter(activity: SimpleActivity, var contactItems: MutableList { + val contact = it as Contact + if (contact.phoneNumbers.isNotEmpty()) { + (activity as SimpleActivity).tryStartCall(it) + } else { + activity!!.toast(R.string.no_phone_number_found) + } } - } else { - context!!.openContact(it as Contact) + ON_CLICK_VIEW_CONTACT -> context!!.viewContact(it as Contact) + ON_CLICK_EDIT_CONTACT -> context!!.editContact(it as Contact) } }.apply { setupDragListener(true) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Config.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Config.kt index ce8fce7e..d34fbc68 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Config.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Config.kt @@ -47,4 +47,8 @@ class Config(context: Context) : BaseConfig(context) { var localAccountType: String get() = prefs.getString(LOCAL_ACCOUNT_TYPE, "-1") set(localAccountType) = prefs.edit().putString(LOCAL_ACCOUNT_TYPE, localAccountType).apply() + + var onContactClick: Int + get() = prefs.getInt(ON_CONTACT_CLICK, ON_CLICK_VIEW_CONTACT) + set(onContactClick) = prefs.edit().putInt(ON_CONTACT_CLICK, onContactClick).apply() } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt index 5453d913..fa0e6a8c 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt @@ -11,6 +11,7 @@ const val LAST_USED_CONTACT_SOURCE = "last_used_contact_source" const val LAST_USED_VIEW_PAGER_PAGE = "last_used_view_pager_page" const val LOCAL_ACCOUNT_NAME = "local_account_name" const val LOCAL_ACCOUNT_TYPE = "local_account_type" +const val ON_CONTACT_CLICK = "on_contact_click" const val CONTACT_ID = "contact_id" @@ -51,3 +52,7 @@ const val HOME_FAX = "HOME;FAX" const val PAGER = "PAGER" const val MOBILE = "MOBILE" const val VOICE = "VOICE" + +const val ON_CLICK_CALL_CONTACT = 1 +const val ON_CLICK_VIEW_CONTACT = 2 +const val ON_CLICK_EDIT_CONTACT = 3 diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 8bdb6e93..35f4ccf3 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -170,5 +170,40 @@ android:text="@string/start_name_with_surname"/> + + + + + + + + diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 5f16fcb4..1e54adbf 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -26,7 +26,6 @@ Zeige Vorschaubilder für Kontakte Beim Klicken auf den Kontakt Kontakt anrufen - Kontakt bearbeiten Kontaktdetails ansehen diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 333ac75d..323ce16a 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -26,7 +26,6 @@ Afficher les vignettes des contacts Sur appui du contact Appeler le contact - Ouvrir l\éditeur de contact Voir les détails du contact diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index 66716cf5..9db78c56 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -26,7 +26,6 @@ Show contact thumbnails On contact click Call contact - Open contact editor View contact details diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 70db9bfa..17b3cd75 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -26,7 +26,6 @@ Show contact thumbnails On contact click Call contact - Open contact editor View contact details diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 0377228e..cc0a7cc6 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -26,7 +26,6 @@ Показывать фото контакта При нажатии на контакт Позвонить контакту - Открыть редактор контактов Просмотреть подробности о контакте diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 9ba0e348..00f2d6fb 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -26,7 +26,6 @@ Zobraziť obrázky kontaktov Po kliknutí na kontakt Zavolať kontakt - Otvoriť editor kontaktov Zobraziť údaje kontaktu diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index a5714f11..73c90220 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -26,7 +26,6 @@ Show contact thumbnails On contact click Call contact - Open contact editor View contact details diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 761dec5e..1e05a942 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -26,7 +26,6 @@ Show contact thumbnails On contact click Call contact - Open contact editor View contact details From dd678cc7d2f24a541130024252ea722c0a852079 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 10 Feb 2018 23:36:22 +0100 Subject: [PATCH 30/35] allow adding a contact to Favorites during creating --- .../activities/EditContactActivity.kt | 13 ++++---- .../contacts/helpers/ContactsHelper.kt | 31 +++++++++++++++++-- .../main/res/layout/activity_edit_contact.xml | 3 +- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt index 5c5f87c7..74dee76d 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt @@ -182,6 +182,12 @@ class EditContactActivity : ContactActivity() { contact_email_add_new.setOnClickListener { addNewEmailField() } contact_event_add_new.setOnClickListener { addNewEventField() } + contact_toggle_favorite.apply { + setImageDrawable(getStarDrawable(contact!!.starred == 1)) + tag = contact!!.starred + applyColorFilter(textColor) + } + updateTextColors(contact_scrollview) wasActivityInitialized = true invalidateOptionsMenu() @@ -213,13 +219,6 @@ class EditContactActivity : ContactActivity() { contact_surname.setText(contact!!.surname) contact_source.text = getPublicContactSource(contact!!.source) - contact_toggle_favorite.apply { - beVisible() - setImageDrawable(getStarDrawable(contact!!.starred == 1)) - tag = contact!!.starred - applyColorFilter(config.textColor) - } - setupPhoneNumbers() setupEmails() setupEvents() diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt index 8a06ffe6..e4903577 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt @@ -301,6 +301,24 @@ class ContactsHelper(val activity: BaseSimpleActivity) { return sort } + private fun getRealContactId(id: Long): Int { + val uri = ContactsContract.Data.CONTENT_URI + val projection = getContactProjection() + val selection = "${ContactsContract.Data.MIMETYPE} = ? AND ${ContactsContract.Data.RAW_CONTACT_ID} = ?" + val selectionArgs = arrayOf(CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, id.toString()) + var cursor: Cursor? = null + try { + cursor = activity.contentResolver.query(uri, projection, selection, selectionArgs, null) + if (cursor?.moveToFirst() == true) { + return cursor.getIntValue(ContactsContract.Data.CONTACT_ID) + } + } finally { + cursor?.close() + } + + return 0 + } + fun updateContact(contact: Contact, photoUpdateStatus: Int): Boolean { return try { activity.toast(R.string.updating) @@ -515,9 +533,18 @@ class ContactsHelper(val activity: BaseSimpleActivity) { } // fullsize photo + val rawId = ContentUris.parseId(results[0].uri) if (contact.photoUri.isNotEmpty() && fullSizePhotoData != null) { - val rawContactId = ContentUris.parseId(results[0].uri) - addFullSizePhoto(rawContactId, fullSizePhotoData) + addFullSizePhoto(rawId, fullSizePhotoData) + } + + // favorite + val userId = getRealContactId(rawId) + if (userId != 0 && contact.starred == 1) { + val uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, userId.toString()) + val contentValues = ContentValues(1) + contentValues.put(ContactsContract.Contacts.STARRED, contact.starred) + activity.contentResolver.update(uri, contentValues, null, null) } true diff --git a/app/src/main/res/layout/activity_edit_contact.xml b/app/src/main/res/layout/activity_edit_contact.xml index 4767e5a0..6684ce6d 100644 --- a/app/src/main/res/layout/activity_edit_contact.xml +++ b/app/src/main/res/layout/activity_edit_contact.xml @@ -31,8 +31,7 @@ android:layout_toRightOf="@+id/contact_photo" android:adjustViewBounds="true" android:padding="@dimen/tiny_margin" - android:src="@drawable/ic_star_off_big" - android:visibility="gone"/> + android:src="@drawable/ic_star_off_big"/> Date: Sat, 10 Feb 2018 23:42:11 +0100 Subject: [PATCH 31/35] move contact init at ViewContactActivity to resume --- .../contacts/activities/ContactActivity.kt | 1 - .../activities/ViewContactActivity.kt | 24 ++++++++++++------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ContactActivity.kt index 12db14bf..01f9ff0e 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ContactActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ContactActivity.kt @@ -32,7 +32,6 @@ import java.text.SimpleDateFormat import java.util.* abstract class ContactActivity : SimpleActivity() { - var isEditActivity = false var contact: Contact? = null var currentContactPhotoPath = "" diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt index 5119db88..c86ee0c6 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt @@ -24,16 +24,11 @@ class ViewContactActivity : ContactActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_view_contact) - isEditActivity = false + } - handlePermission(PERMISSION_READ_CONTACTS) { - if (it) { - initContact() - } else { - toast(R.string.no_contacts_permission) - finish() - } - } + override fun onResume() { + super.onResume() + tryInitContact() } override fun onCreateOptionsMenu(menu: Menu): Boolean { @@ -51,6 +46,17 @@ class ViewContactActivity : ContactActivity() { return true } + private fun tryInitContact() { + handlePermission(PERMISSION_READ_CONTACTS) { + if (it) { + initContact() + } else { + toast(R.string.no_contacts_permission) + finish() + } + } + } + private fun initContact() { var contactId = intent.getIntExtra(CONTACT_ID, 0) val action = intent.action From 9cd4288862dabb33b48bd228cdeff7100a78ff72 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sat, 10 Feb 2018 23:48:50 +0100 Subject: [PATCH 32/35] handle View intents with the new ViewContactActivity --- app/src/main/AndroidManifest.xml | 59 ++++++++++--------- .../activities/EditContactActivity.kt | 5 +- 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 180ba002..99f7f95d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -77,7 +77,36 @@ + android:parentActivityName=".activities.MainActivity"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - @@ -144,16 +155,6 @@ - - - - - - - - - - Date: Sat, 10 Feb 2018 23:52:47 +0100 Subject: [PATCH 33/35] adding a missing return statement --- .../kotlin/com/simplemobiletools/contacts/extensions/Context.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt index ef7a1ebe..9d5b9aa0 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt @@ -64,7 +64,7 @@ fun Context.getLookupUriRawId(dataUri: Uri): Int { if (lookupKey != null && isLollipopPlus()) { val uri = lookupContactUri(lookupKey, this) if (uri != null) { - getContactUriRawId(uri) + return getContactUriRawId(uri) } } return -1 From 640073546349f9d07bd00a02bbfbce59f3dba258 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sun, 11 Feb 2018 12:30:30 +0100 Subject: [PATCH 34/35] use a human readable default filename at exporting --- .../simplemobiletools/contacts/dialogs/ExportContactsDialog.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ExportContactsDialog.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ExportContactsDialog.kt index f19ce9f6..d59ada5d 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ExportContactsDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ExportContactsDialog.kt @@ -19,7 +19,7 @@ class ExportContactsDialog(val activity: SimpleActivity, val path: String, priva init { val view = (activity.layoutInflater.inflate(R.layout.dialog_export_contacts, null) as ViewGroup).apply { export_contacts_folder.text = activity.humanizePath(path) - export_contacts_filename.setText("contacts_${System.currentTimeMillis() / 1000}") + export_contacts_filename.setText("contacts_${activity.getCurrentFormattedDateTime()}") ContactsHelper(activity).getContactSources { it.mapTo(contactSources, { it.copy() }) From 8e207414ef4c2037411e593bac2990b199bf3835 Mon Sep 17 00:00:00 2001 From: tibbi Date: Sun, 11 Feb 2018 13:10:21 +0100 Subject: [PATCH 35/35] add a new source for storing contacts locally, without sharing with other apps --- .../activities/EditContactActivity.kt | 2 +- .../contacts/extensions/Activity.kt | 6 +- .../contacts/helpers/Constants.kt | 1 + .../contacts/helpers/ContactsHelper.kt | 203 +++++++++--------- 4 files changed, 111 insertions(+), 101 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt index ecf3c3ce..3b8b0092 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt @@ -287,7 +287,7 @@ class EditContactActivity : ContactActivity() { contact_source.text = getPublicContactSource(contact!!.source) contact_source.setOnClickListener { showContactSourcePicker(contact!!.source) { - contact!!.source = it + contact!!.source = if (it == getString(R.string.phone_storage_hidden)) SMT_PRIVATE else it contact_source.text = getPublicContactSource(it) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Activity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Activity.kt index a7e390a9..02a87f7b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Activity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Activity.kt @@ -2,7 +2,6 @@ package com.simplemobiletools.contacts.extensions import android.content.Intent import android.net.Uri -import com.simplemobiletools.commons.R import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.dialogs.RadioGroupDialog import com.simplemobiletools.commons.extensions.getFilePublicUri @@ -11,6 +10,7 @@ import com.simplemobiletools.commons.extensions.toast import com.simplemobiletools.commons.helpers.PERMISSION_CALL_PHONE import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.contacts.BuildConfig +import com.simplemobiletools.contacts.R import com.simplemobiletools.contacts.activities.SimpleActivity import com.simplemobiletools.contacts.helpers.ContactsHelper import com.simplemobiletools.contacts.helpers.VcfExporter @@ -56,7 +56,7 @@ fun SimpleActivity.showContactSourcePicker(currentSource: String, callback: (new sources.forEachIndexed { index, account -> var publicAccount = account if (account == config.localAccountName) { - publicAccount = getString(com.simplemobiletools.contacts.R.string.phone_storage) + publicAccount = getString(R.string.phone_storage) } items.add(RadioItem(index, publicAccount)) @@ -73,7 +73,7 @@ fun SimpleActivity.showContactSourcePicker(currentSource: String, callback: (new } } -fun SimpleActivity.getPublicContactSource(source: String) = if (source == config.localAccountName) getString(com.simplemobiletools.contacts.R.string.phone_storage) else source +fun SimpleActivity.getPublicContactSource(source: String) = if (source == config.localAccountName) getString(R.string.phone_storage) else source fun BaseSimpleActivity.shareContacts(contacts: ArrayList) { val file = getTempFile() diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt index fa0e6a8c..c8dbce1b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt @@ -14,6 +14,7 @@ const val LOCAL_ACCOUNT_TYPE = "local_account_type" const val ON_CONTACT_CLICK = "on_contact_click" const val CONTACT_ID = "contact_id" +const val SMT_PRIVATE = "smt_private" // contact photo changes const val PHOTO_ADDED = 1 diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt index e4903577..d5d8de29 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt @@ -227,7 +227,7 @@ class ContactsHelper(val activity: BaseSimpleActivity) { } fun getContactSources(callback: (ArrayList) -> Unit) { - val sources = HashSet() + val sources = LinkedHashSet() Thread { val uri = ContactsContract.RawContacts.CONTENT_URI val projection = arrayOf(ContactsContract.RawContacts.ACCOUNT_NAME, ContactsContract.RawContacts.ACCOUNT_TYPE) @@ -247,6 +247,7 @@ class ContactsHelper(val activity: BaseSimpleActivity) { cursor?.close() } + sources.add(ContactSource(activity.getString(R.string.phone_storage_hidden), SMT_PRIVATE)) callback(ArrayList(sources)) }.start() } @@ -451,109 +452,117 @@ class ContactsHelper(val activity: BaseSimpleActivity) { } fun insertContact(contact: Contact): Boolean { - return try { - val operations = ArrayList() - ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI).apply { - withValue(ContactsContract.RawContacts.ACCOUNT_NAME, contact.source) - withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, getContactSourceType(contact.source)) - operations.add(build()) - } - - // names - ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { - withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) - withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) - withValue(CommonDataKinds.StructuredName.GIVEN_NAME, contact.firstName) - withValue(CommonDataKinds.StructuredName.MIDDLE_NAME, contact.middleName) - withValue(CommonDataKinds.StructuredName.FAMILY_NAME, contact.surname) - operations.add(build()) - } - - // phone numbers - contact.phoneNumbers.forEach { - ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { - withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) - withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE) - withValue(CommonDataKinds.Phone.NUMBER, it.value) - withValue(CommonDataKinds.Phone.TYPE, it.type) - operations.add(build()) - } - } - - // emails - contact.emails.forEach { - ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { - withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) - withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Email.CONTENT_ITEM_TYPE) - withValue(CommonDataKinds.Email.DATA, it.value) - withValue(CommonDataKinds.Email.TYPE, it.type) - operations.add(build()) - } - } - - // events - contact.events.forEach { - ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { - withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) - withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Event.CONTENT_ITEM_TYPE) - withValue(CommonDataKinds.Event.START_DATE, it.value) - withValue(CommonDataKinds.Event.TYPE, it.type) - operations.add(build()) - } - } - - // photo (inspired by https://gist.github.com/slightfoot/5985900) - var fullSizePhotoData: ByteArray? = null - var scaledSizePhotoData: ByteArray? - if (contact.photoUri.isNotEmpty()) { - val photoUri = Uri.parse(contact.photoUri) - val bitmap = MediaStore.Images.Media.getBitmap(activity.contentResolver, photoUri) - - val thumbnailSize = getThumbnailSize() - val scaledPhoto = Bitmap.createScaledBitmap(bitmap, thumbnailSize, thumbnailSize, false) - scaledSizePhotoData = bitmapToByteArray(scaledPhoto) - - fullSizePhotoData = bitmapToByteArray(bitmap) - scaledPhoto.recycle() - bitmap.recycle() - - ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { - withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) - withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Photo.CONTENT_ITEM_TYPE) - withValue(CommonDataKinds.Photo.PHOTO, scaledSizePhotoData) - operations.add(build()) - } - } - - val results: Array + return if (contact.source == SMT_PRIVATE) { + insertLocalContact(contact) + } else { try { - results = activity.contentResolver.applyBatch(ContactsContract.AUTHORITY, operations) - } finally { - scaledSizePhotoData = null - } + val operations = ArrayList() + ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI).apply { + withValue(ContactsContract.RawContacts.ACCOUNT_NAME, contact.source) + withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, getContactSourceType(contact.source)) + operations.add(build()) + } - // fullsize photo - val rawId = ContentUris.parseId(results[0].uri) - if (contact.photoUri.isNotEmpty() && fullSizePhotoData != null) { - addFullSizePhoto(rawId, fullSizePhotoData) - } + // names + ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { + withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) + withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) + withValue(CommonDataKinds.StructuredName.GIVEN_NAME, contact.firstName) + withValue(CommonDataKinds.StructuredName.MIDDLE_NAME, contact.middleName) + withValue(CommonDataKinds.StructuredName.FAMILY_NAME, contact.surname) + operations.add(build()) + } - // favorite - val userId = getRealContactId(rawId) - if (userId != 0 && contact.starred == 1) { - val uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, userId.toString()) - val contentValues = ContentValues(1) - contentValues.put(ContactsContract.Contacts.STARRED, contact.starred) - activity.contentResolver.update(uri, contentValues, null, null) - } + // phone numbers + contact.phoneNumbers.forEach { + ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { + withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) + withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE) + withValue(CommonDataKinds.Phone.NUMBER, it.value) + withValue(CommonDataKinds.Phone.TYPE, it.type) + operations.add(build()) + } + } - true - } catch (e: Exception) { - activity.showErrorToast(e) - false + // emails + contact.emails.forEach { + ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { + withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) + withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Email.CONTENT_ITEM_TYPE) + withValue(CommonDataKinds.Email.DATA, it.value) + withValue(CommonDataKinds.Email.TYPE, it.type) + operations.add(build()) + } + } + + // events + contact.events.forEach { + ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { + withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) + withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Event.CONTENT_ITEM_TYPE) + withValue(CommonDataKinds.Event.START_DATE, it.value) + withValue(CommonDataKinds.Event.TYPE, it.type) + operations.add(build()) + } + } + + // photo (inspired by https://gist.github.com/slightfoot/5985900) + var fullSizePhotoData: ByteArray? = null + var scaledSizePhotoData: ByteArray? + if (contact.photoUri.isNotEmpty()) { + val photoUri = Uri.parse(contact.photoUri) + val bitmap = MediaStore.Images.Media.getBitmap(activity.contentResolver, photoUri) + + val thumbnailSize = getThumbnailSize() + val scaledPhoto = Bitmap.createScaledBitmap(bitmap, thumbnailSize, thumbnailSize, false) + scaledSizePhotoData = bitmapToByteArray(scaledPhoto) + + fullSizePhotoData = bitmapToByteArray(bitmap) + scaledPhoto.recycle() + bitmap.recycle() + + ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply { + withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) + withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Photo.CONTENT_ITEM_TYPE) + withValue(CommonDataKinds.Photo.PHOTO, scaledSizePhotoData) + operations.add(build()) + } + } + + val results: Array + try { + results = activity.contentResolver.applyBatch(ContactsContract.AUTHORITY, operations) + } finally { + scaledSizePhotoData = null + } + + // fullsize photo + val rawId = ContentUris.parseId(results[0].uri) + if (contact.photoUri.isNotEmpty() && fullSizePhotoData != null) { + addFullSizePhoto(rawId, fullSizePhotoData) + } + + // favorite + val userId = getRealContactId(rawId) + if (userId != 0 && contact.starred == 1) { + val uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, userId.toString()) + val contentValues = ContentValues(1) + contentValues.put(ContactsContract.Contacts.STARRED, contact.starred) + activity.contentResolver.update(uri, contentValues, null, null) + } + + true + } catch (e: Exception) { + activity.showErrorToast(e) + false + } } } + private fun insertLocalContact(contact: Contact): Boolean { + return true + } + private fun addFullSizePhoto(contactId: Long, fullSizePhotoData: ByteArray) { val baseUri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, contactId) val displayPhotoUri = Uri.withAppendedPath(baseUri, ContactsContract.RawContacts.DisplayPhoto.CONTENT_DIRECTORY)