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)*
----------------------------
diff --git a/app/build.gradle b/app/build.gradle
index 0b3e3353..92b6ece5 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")
}
@@ -20,6 +20,9 @@ android {
}
buildTypes {
+ debug {
+ applicationIdSuffix ".debug"
+ }
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
@@ -42,7 +45,7 @@ ext {
}
dependencies {
- implementation 'com.simplemobiletools:commons:3.9.5'
+ 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/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
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index eb13cd3a..99f7f95d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -74,6 +74,40 @@
android:label="@string/settings"
android:parentActivityName=".activities.MainActivity"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -111,24 +145,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -139,16 +155,6 @@
-
-
-
-
-
-
-
-
-
-
{
+ 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 86be6271..3b8b0092 100644
--- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt
+++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/EditContactActivity.kt
@@ -4,10 +4,8 @@ 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
import android.provider.ContactsContract.CommonDataKinds
import android.provider.MediaStore
import android.view.Menu
@@ -16,20 +14,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.*
@@ -39,16 +27,14 @@ 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
-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 +46,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?) {
@@ -88,7 +72,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
@@ -111,7 +95,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)
}
}
}
@@ -119,9 +103,7 @@ class EditContactActivity : SimpleActivity() {
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 ||
- action == Intent.ACTION_EDIT)) {
+ if (contactId == 0 && action == Intent.ACTION_EDIT) {
val data = intent.data
if (data != null) {
val rawId = if (data.path.contains("lookup")) {
@@ -165,9 +147,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
@@ -197,6 +179,12 @@ class EditContactActivity : SimpleActivity() {
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()
@@ -226,14 +214,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_toggle_favorite.apply {
- beVisible()
- setImageDrawable(getStarDrawable(contact!!.starred == 1))
- tag = contact!!.starred
- applyColorFilter(config.textColor)
- }
+ contact_source.text = getPublicContactSource(contact!!.source)
setupPhoneNumbers()
setupEmails()
@@ -244,11 +225,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 +240,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 +259,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
@@ -302,50 +283,16 @@ 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 = if (it == getString(R.string.phone_storage_hidden)) SMT_PRIVATE else it
+ contact_source.text = getPublicContactSource(it)
}
}
}
- 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)
@@ -430,31 +377,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)),
@@ -515,7 +437,7 @@ class EditContactActivity : SimpleActivity() {
phoneNumbers = getFilledPhoneNumbers()
emails = getFilledEmails()
events = getFilledEvents()
- source = contact_source.value
+ source = contact!!.source
starred = if (isContactStarred()) 1 else 0
Thread {
@@ -608,7 +530,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)
@@ -619,7 +541,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)
@@ -636,13 +558,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 {
@@ -670,39 +585,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)
}
}
}
@@ -736,17 +619,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
@@ -758,13 +630,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
@@ -772,12 +637,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/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt
index 8bbd46cd..6fc48b2c 100644
--- a/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt
+++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/MainActivity.kt
@@ -56,6 +56,7 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
if (it) {
handlePermission(PERMISSION_WRITE_CONTACTS) {
if (it) {
+ storeLocalAccountData()
initFragments()
} else {
toast(R.string.no_contacts_permission)
@@ -214,6 +215,34 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
}
}
+ 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",
+ "com.htc.android.pcsc",
+ "com.sonyericsson.localcontacts",
+ "com.lge.sync",
+ "com.lge.phone",
+ "vnd.tmobileus.contact.phone",
+ "com.android.huawei.phone",
+ "Local Phone Account")
+
+ ContactsHelper(this).getContactSources {
+ var localAccountType = ""
+ var localAccountName = ""
+ it.forEach {
+ if (localAccountTypes.contains(it.type)) {
+ localAccountType = it.type
+ localAccountName = it.name
+ }
+ }
+
+ config.localAccountType = localAccountType
+ config.localAccountName = localAccountName
+ }
+ }
+ }
+
private fun getOtherViewPagerItem(used: Int) = if (used == 1) 0 else 1
private fun initFragments() {
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..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.*
@@ -20,11 +25,12 @@ class SettingsActivity : SimpleActivity() {
setupCustomizeColors()
setupUseEnglish()
+ setupAvoidWhatsNew()
setupShowInfoBubble()
setupShowContactThumbnails()
setupShowPhoneNumbers()
- setupCallContactOnClick()
setupStartNameWithSurname()
+ setupOnContactClick()
updateTextColors(settings_holder)
}
@@ -44,6 +50,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 {
@@ -68,14 +82,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 {
@@ -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
new file mode 100644
index 00000000..c86ee0c6
--- /dev/null
+++ b/app/src/main/kotlin/com/simplemobiletools/contacts/activities/ViewContactActivity.kt
@@ -0,0 +1,255 @@
+package com.simplemobiletools.contacts.activities
+
+import android.content.Intent
+import android.graphics.drawable.ColorDrawable
+import android.os.Bundle
+import android.provider.ContactsContract
+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.simplemobiletools.commons.extensions.*
+import com.simplemobiletools.commons.helpers.PERMISSION_READ_CONTACTS
+import com.simplemobiletools.contacts.R
+import com.simplemobiletools.contacts.extensions.*
+import com.simplemobiletools.contacts.helpers.*
+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.*
+
+class ViewContactActivity : ContactActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_view_contact)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ tryInitContact()
+ }
+
+ 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(contact!!)
+ R.id.share -> shareContact()
+ R.id.delete -> deleteContact()
+ else -> return super.onOptionsItemSelected(item)
+ }
+ 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
+ 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(contact_photo)
+ } else {
+ updateContactPhoto(contact!!.photoUri, contact_photo)
+ }
+
+ 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 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 getStarDrawable(on: Boolean) = resources.getDrawable(if (on) R.drawable.ic_star_on_big else R.drawable.ic_star_off_big)
+}
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..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
@@ -51,7 +51,7 @@ class ContactsAdapter(activity: SimpleActivity, var contactItems: MutableList, 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/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)
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..d59ada5d 100644
--- a/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ExportContactsDialog.kt
+++ b/app/src/main/kotlin/com/simplemobiletools/contacts/dialogs/ExportContactsDialog.kt
@@ -8,17 +8,21 @@ 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 {
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() })
activity.runOnUiThread {
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 6a516e01..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,6 +22,7 @@ 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, selectedSources)
@@ -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()
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 0f1eeb83..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
@@ -51,10 +51,15 @@ 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))
+ var publicAccount = account
+ if (account == config.localAccountName) {
+ publicAccount = getString(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(R.string.phone_storage) else source
+
fun BaseSimpleActivity.shareContacts(contacts: ArrayList) {
val file = getTempFile()
if (file == null) {
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..9d5b9aa0 100644
--- a/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt
+++ b/app/src/main/kotlin/com/simplemobiletools/contacts/extensions/Context.kt
@@ -8,12 +8,13 @@ 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.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
@@ -21,7 +22,14 @@ import java.io.File
val Context.config: Config get() = Config.newInstance(applicationContext)
-fun Context.openContact(contact: Contact) {
+fun Context.viewContact(contact: Contact) {
+ Intent(applicationContext, ViewContactActivity::class.java).apply {
+ putExtra(CONTACT_ID, contact.id)
+ startActivity(this)
+ }
+}
+
+fun Context.editContact(contact: Contact) {
Intent(applicationContext, EditContactActivity::class.java).apply {
putExtra(CONTACT_ID, contact.id)
startActivity(this)
@@ -55,7 +63,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) {
+ return getContactUriRawId(uri)
+ }
}
return -1
}
@@ -94,9 +104,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 {
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..de0ff1ae 100644
--- a/app/src/main/kotlin/com/simplemobiletools/contacts/fragments/MyViewPagerFragment.kt
+++ b/app/src/main/kotlin/com/simplemobiletools/contacts/fragments/MyViewPagerFragment.kt
@@ -13,10 +13,10 @@ import com.simplemobiletools.contacts.activities.MainActivity
import com.simplemobiletools.contacts.activities.SimpleActivity
import com.simplemobiletools.contacts.adapters.ContactsAdapter
import com.simplemobiletools.contacts.extensions.config
-import com.simplemobiletools.contacts.extensions.openContact
+import com.simplemobiletools.contacts.extensions.editContact
import com.simplemobiletools.contacts.extensions.tryStartCall
-import com.simplemobiletools.contacts.helpers.Config
-import com.simplemobiletools.contacts.helpers.ContactsHelper
+import com.simplemobiletools.contacts.extensions.viewContact
+import com.simplemobiletools.contacts.helpers.*
import com.simplemobiletools.contacts.models.Contact
import kotlinx.android.synthetic.main.fragment_layout.view.*
@@ -119,15 +119,17 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
if (currAdapter == null || forceListRedraw) {
forceListRedraw = false
ContactsAdapter(activity as SimpleActivity, contacts, activity, this is FavoritesFragment, fragment_list, fragment_fastscroller) {
- if (config.callContact) {
- val contact = it as Contact
- if (contact.phoneNumbers.isNotEmpty()) {
- (activity as SimpleActivity).tryStartCall(it)
- } else {
- activity!!.toast(R.string.no_phone_number_found)
+ when (config.onContactClick) {
+ ON_CLICK_CALL_CONTACT -> {
+ 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)
@@ -166,7 +168,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) } ||
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..d34fbc68 100644
--- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Config.kt
+++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Config.kt
@@ -14,17 +14,13 @@ class Config(context: Context) : BaseConfig(context) {
get() = prefs.getInt(SORTING, SORT_BY_FIRST_NAME)
set(sorting) = prefs.edit().putInt(SORTING, sorting).apply()
- var callContact: Boolean
- get() = prefs.getBoolean(CALL_CONTACT_ON_CLICK, false)
- set(callContact) = prefs.edit().putBoolean(CALL_CONTACT_ON_CLICK, callContact).apply()
-
var displayContactSources: Set
get() = prefs.getStringSet(DISPLAY_CONTACT_SOURCES, hashSetOf("-1"))
set(displayContactSources) = prefs.edit().remove(DISPLAY_CONTACT_SOURCES).putStringSet(DISPLAY_CONTACT_SOURCES, displayContactSources).apply()
fun showAllContacts() = displayContactSources.size == 1 && displayContactSources.first() == "-1"
- var showContactThumbnails : Boolean
+ var showContactThumbnails: Boolean
get() = prefs.getBoolean(SHOW_CONTACT_THUMBNAILS, true)
set(showContactThumbnails) = prefs.edit().putBoolean(SHOW_CONTACT_THUMBNAILS, showContactThumbnails).apply()
@@ -43,4 +39,16 @@ 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 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()
+
+ 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 9bbcb459..c8dbce1b 100644
--- a/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt
+++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/Constants.kt
@@ -3,15 +3,18 @@ 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"
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 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
@@ -27,7 +30,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:"
@@ -50,3 +53,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/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/ContactsHelper.kt
index be32e742..d5d8de29 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 = LinkedHashSet()
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,14 +238,17 @@ class ContactsHelper(val activity: BaseSimpleActivity) {
if (cursor?.moveToFirst() == true) {
do {
val name = cursor.getStringValue(ContactsContract.RawContacts.ACCOUNT_NAME) ?: continue
- accounts.add(name)
+ val type = cursor.getStringValue(ContactsContract.RawContacts.ACCOUNT_TYPE) ?: continue
+ val contactSource = ContactSource(name, type)
+ sources.add(contactSource)
} while (cursor.moveToNext())
}
} finally {
cursor?.close()
}
- callback(ArrayList(accounts))
+ sources.add(ContactSource(activity.getString(R.string.phone_storage_hidden), SMT_PRIVATE))
+ callback(ArrayList(sources))
}.start()
}
@@ -302,6 +302,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)
@@ -434,100 +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
- if (contact.photoUri.isNotEmpty() && fullSizePhotoData != null) {
- val rawContactId = ContentUris.parseId(results[0].uri)
- addFullSizePhoto(rawContactId, 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())
+ }
- true
- } catch (e: Exception) {
- activity.showErrorToast(e)
- false
+ // 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
+ 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)
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..ce974b81
--- /dev/null
+++ b/app/src/main/kotlin/com/simplemobiletools/contacts/helpers/QuotedPrintable.kt
@@ -0,0 +1,64 @@
+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 {
+ 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 += 3
+ 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())
+ }
+
+ 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 6bf5d141..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${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,24 @@ class VcfExporter {
})
}
+ private fun getNames(contact: Contact): String {
+ var result = ""
+ 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)
+ result += ";CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE"
+ }
+
+ return "$result:$surName;$firstName;$middleName;;"
+ }
+
private fun getPhoneNumberLabel(type: Int) = when (type) {
CommonDataKinds.Phone.TYPE_MOBILE -> CELL
CommonDataKinds.Phone.TYPE_HOME -> HOME
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..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,12 +89,23 @@ class VcfImporter(val activity: SimpleActivity) {
}
}
- private fun parseNames(names: String) {
- val nameParts = names.split(";")
- curSurname = nameParts[0]
- curFirstName = nameParts[1]
+ private fun addNames(names: String) {
+ val parts = names.split(":")
+ 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 = nameParts[2]
+ curMiddleName = if (currentNameIsANSI) QuotedPrintable.decode(nameParts[2]) else nameParts[2]
}
}
@@ -198,5 +217,9 @@ class VcfImporter(val activity: SimpleActivity) {
isGettingPhoto = false
currentPhotoString = StringBuilder()
currentPhotoCompressionFormat = Bitmap.CompressFormat.JPEG
+
+ isGettingName = false
+ currentNameIsANSI = false
+ currentNameString = StringBuilder()
}
}
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)
diff --git a/app/src/main/res/layout/activity_edit_contact.xml b/app/src/main/res/layout/activity_edit_contact.xml
index 9d1477b4..6684ce6d 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">
+ android:src="@drawable/ic_star_off_big"/>
-
+
@@ -193,7 +195,7 @@
android:layout_toRightOf="@+id/contact_name_image"
android:orientation="vertical">
-
+
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
index c4415743..35f4ccf3 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">
+
+
+
+
+
+
+
+
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_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/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 @@
+
+
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index db5df3c6..1e54adbf 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
+ Gerätespeicher (nicht sichtbar für andere Apps)
Neuer Kontakt
Kontakt bearbeiten
@@ -20,13 +21,11 @@
Foto entfernen
- Kontakt bei Klick anrufen
Namen mit Nachnamen beginnen
Zeige Telefonnummern im Hauptmenü
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
new file mode 100644
index 00000000..323ce16a
--- /dev/null
+++ b/app/src/main/res/values-fr/strings.xml
@@ -0,0 +1,86 @@
+
+ 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
+
+
+ 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
+ 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
+
+
+
+
diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml
index 08c93d35..9db78c56 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)
새로운 연락처
연락처 수정
@@ -20,13 +21,11 @@
사진 삭제
- 클릭으로 전화걸기
성을 먼저 표시
메인 스크린에 전화번호 표시
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 4831a362..17b3cd75 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
@@ -20,13 +21,11 @@
Remove photo
- Call contact on click
Start name with surname
Show phone numbers on the main screen
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 58af51cf..cc0a7cc6 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -5,6 +5,7 @@
Добавление…
Обновление…
Память устройства
+ Память устройства (не видна другим приложениям)
Новый контакт
Редактировать контакт
@@ -20,13 +21,11 @@
Удалить фото
- Вызывать контакт при нажатии
Показывать сначала фамилию
Показывать номера телефонов на главном экране
Показывать фото контакта
При нажатии на контакт
Позвонить контакту
- Открыть редактор контактов
Просмотреть подробности о контакте
diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml
index a9fd79d1..00f2d6fb 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
@@ -20,13 +21,11 @@
Odstrániť foto
- Zavolať kontakt po kliknutí
Začať meno priezviskom
Zobraziť telefónne čísla na hlavnej obrazovke
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 aadd2363..73c90220 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
@@ -20,13 +21,11 @@
Ta bort foto
- Ring kontakter när jag trycker på dem
Visa efternamn först
Visa telefonnummer i huvudvyn
Show contact thumbnails
On contact click
Call contact
- Open contact editor
View contact details
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
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0a735653..1e05a942 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
@@ -20,13 +21,11 @@
Remove photo
- Call contact on click
Start name with surname
Show phone numbers on the main screen
Show contact thumbnails
On contact click
Call contact
- Open contact editor
View contact details