diff --git a/.editorconfig b/.editorconfig index 1606d61f..c79c990f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -17,7 +17,7 @@ insert_final_newline = true charset = utf-8 indent_style = space indent_size = 4 -continuation_indent_size = 8 +continuation_indent_size = 4 [*.xml] continuation_indent_size = 4 diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index bef56379..9bad22a9 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,3 +1,3 @@ github: [tibbi] patreon: tiborkaputa -custom: ["https://www.paypal.me/SimpleMobileTools", "https://www.simplemobiletools.com/donate"] +custom: ["https://www.paypal.com/paypalme/simplemobiletools", "https://www.simplemobiletools.com/donate"] diff --git a/CHANGELOG.md b/CHANGELOG.md index c6c63253..f34d65ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,28 @@ Changelog ========== +Version 6.14.1 *(2021-02-15)* +---------------------------- + + * Allow customizing the ringtone per contact (Ringtone has to be enabled as a customizable field in the app settings) + * Added a White theme with special handling + * Added some letter fastscroller related improvements + * Some performance, stability and translation related improvements + * Please rate the app if you like it :) + +Version 6.14.0 *(2021-01-10)* +---------------------------- + + * Always fetch the same contacts, no matter what sorting is set + * Fix an organization updating related issue + * Merge names into 1 line at the View Details screen + * Improve Threema contact handling + +Version 6.13.2 *(2021-01-02)* +---------------------------- + + * Added some translation, stability and UX improvements + Version 6.13.1 *(2020-10-27)* ---------------------------- diff --git a/README.md b/README.md index b8cd92e0..7549c8af 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ This app is just one piece of a bigger series of apps. You can find the rest of Get it on F-Droid
-App image -App image -App image +App image +App image +App image
diff --git a/app/build.gradle b/app/build.gradle index d5e6548a..64c4dde3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,8 +17,8 @@ android { applicationId "com.simplemobiletools.contacts.pro" minSdkVersion 21 targetSdkVersion 29 - versionCode 77 - versionName "6.13.1" + versionCode 80 + versionName "6.14.1" setProperty("archivesBaseName", "contacts") } @@ -57,13 +57,13 @@ android { } dependencies { - implementation 'com.simplemobiletools:commons:5.31.18' + implementation 'com.simplemobiletools:commons:5.33.30' implementation 'joda-time:joda-time:2.10.1' implementation 'com.googlecode.ez-vcard:ez-vcard:0.10.5' - implementation 'com.github.tibbi:IndicatorFastScroll:08f512858a' + implementation 'com.github.tibbi:IndicatorFastScroll:c3de1d040a' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' - kapt "androidx.room:room-compiler:2.2.5" - implementation "androidx.room:room-runtime:2.2.5" - annotationProcessor "androidx.room:room-compiler:2.2.5" + kapt "androidx.room:room-compiler:2.2.6" + implementation "androidx.room:room-runtime:2.2.6" + annotationProcessor "androidx.room:room-compiler:2.2.6" } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/ContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/ContactActivity.kt index 681458bd..c65bf4b8 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/ContactActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/ContactActivity.kt @@ -1,11 +1,13 @@ package com.simplemobiletools.contacts.pro.activities +import android.content.Intent import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.Paint import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.ColorDrawable import android.graphics.drawable.Drawable +import android.net.Uri import android.provider.ContactsContract.CommonDataKinds.* import android.widget.ImageView import android.widget.TextView @@ -24,16 +26,25 @@ import com.simplemobiletools.commons.helpers.letterBackgroundColors import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.extensions.sendEmailIntent -import com.simplemobiletools.contacts.pro.extensions.sendSMSIntent import com.simplemobiletools.contacts.pro.extensions.shareContacts import com.simplemobiletools.contacts.pro.helpers.ContactsHelper import com.simplemobiletools.contacts.pro.models.Contact import java.util.* abstract class ContactActivity : SimpleActivity() { + protected val PICK_RINGTONE_INTENT_ID = 1500 protected var contact: Contact? = null protected var currentContactPhotoPath = "" + override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) { + super.onActivityResult(requestCode, resultCode, resultData) + if (requestCode == PICK_RINGTONE_INTENT_ID && resultCode == RESULT_OK && resultData != null && resultData.dataString != null) { + customRingtoneSelected(Uri.decode(resultData.dataString!!)) + } + } + + abstract fun customRingtoneSelected(ringtonePath: String) + fun showPhotoPlaceholder(photoView: ImageView) { val placeholder = BitmapDrawable(resources, getBigLetterPlaceholder(contact?.getNameToDisplay() ?: "A")) photoView.setImageDrawable(placeholder) @@ -92,7 +103,7 @@ abstract class ContactActivity : SimpleActivity() { fun trySendSMS() { val numbers = contact!!.phoneNumbers if (numbers.size == 1) { - sendSMSIntent(numbers.first().value) + launchSendSMSIntent(numbers.first().value) } else if (numbers.size > 1) { val items = ArrayList() numbers.forEachIndexed { index, phoneNumber -> @@ -100,7 +111,7 @@ abstract class ContactActivity : SimpleActivity() { } RadioGroupDialog(this, items) { - sendSMSIntent(it as String) + launchSendSMSIntent(it as String) } } } @@ -189,6 +200,7 @@ abstract class ContactActivity : SimpleActivity() { isAntiAlias = true textAlign = Paint.Align.CENTER textSize = wantedTextSize + style = Paint.Style.FILL } canvas.drawPaint(circlePaint) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/EditContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/EditContactActivity.kt index 60be1956..b3f29e80 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/EditContactActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/EditContactActivity.kt @@ -5,8 +5,8 @@ import android.content.ClipData import android.content.ContentValues import android.content.Intent import android.graphics.Bitmap -import android.graphics.Color -import android.graphics.drawable.ColorDrawable +import android.media.AudioManager +import android.media.RingtoneManager import android.net.Uri import android.os.Bundle import android.provider.ContactsContract.CommonDataKinds @@ -20,6 +20,7 @@ import android.widget.ImageView import android.widget.RelativeLayout import android.widget.TextView import com.simplemobiletools.commons.dialogs.RadioGroupDialog +import com.simplemobiletools.commons.dialogs.SelectAlarmSoundDialog import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.models.RadioItem @@ -184,6 +185,7 @@ class EditContactActivity : ContactActivity() { } setupTypePickers() + setupRingtone() if (contact!!.photoUri.isEmpty() && contact!!.photo == null) { showPhotoPlaceholder(contact_photo) @@ -194,7 +196,7 @@ class EditContactActivity : ContactActivity() { val textColor = config.textColor arrayOf(contact_name_image, contact_numbers_image, contact_emails_image, contact_addresses_image, contact_ims_image, contact_events_image, - contact_notes_image, contact_organization_image, contact_websites_image, contact_groups_image, contact_source_image).forEach { + contact_notes_image, contact_ringtone_image, contact_organization_image, contact_websites_image, contact_groups_image, contact_source_image).forEach { it.applyColorFilter(textColor) } @@ -380,6 +382,10 @@ class EditContactActivity : ContactActivity() { val areNotesVisible = showFields and SHOW_NOTES_FIELD != 0 contact_notes.beVisibleIf(areNotesVisible) contact_notes_image.beVisibleIf(areNotesVisible) + + val isRingtoneVisible = showFields and SHOW_RINGTONE_FIELD != 0 + contact_ringtone.beVisibleIf(isRingtoneVisible) + contact_ringtone_image.beVisibleIf(isRingtoneVisible) } private fun setupEditContact() { @@ -480,6 +486,31 @@ class EditContactActivity : ContactActivity() { contact_notes.setText(contact!!.notes) } + private fun setupRingtone() { + contact_ringtone.setOnClickListener { + val currentRingtone = contact!!.ringtone ?: getDefaultAlarmSound(RingtoneManager.TYPE_RINGTONE).uri + SelectAlarmSoundDialog(this, currentRingtone, AudioManager.STREAM_RING, PICK_RINGTONE_INTENT_ID, RingtoneManager.TYPE_RINGTONE, true, + onAlarmPicked = { + contact!!.ringtone = it?.uri + contact_ringtone.text = it?.title + }, onAlarmSoundDeleted = {} + ) + } + + val ringtone = contact!!.ringtone + if (ringtone != null && ringtone.isNotEmpty()) { + if (ringtone == SILENT) { + contact_ringtone.text = getString(R.string.no_sound) + } else { + val contactRingtone = RingtoneManager.getRingtone(this, Uri.parse(ringtone)) + contact_ringtone.text = contactRingtone.getTitle(this) + } + } else { + val default = getDefaultAlarmSound(RingtoneManager.TYPE_RINGTONE) + contact_ringtone.text = default.title + } + } + private fun setupOrganization() { contact_organization_company.setText(contact!!.organization.company) contact_organization_job_position.setText(contact!!.organization.jobPosition) @@ -1211,6 +1242,11 @@ class EditContactActivity : ContactActivity() { } } + override fun customRingtoneSelected(ringtonePath: String) { + contact!!.ringtone = ringtonePath + contact_ringtone.text = ringtonePath.getFilenameFromPath() + } + private fun getPhoneNumberTypeId(value: String) = when (value) { getString(R.string.mobile) -> Phone.TYPE_MOBILE getString(R.string.home) -> Phone.TYPE_HOME diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/MainActivity.kt index 62df76f0..b1e93870 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/MainActivity.kt @@ -59,9 +59,6 @@ class MainActivity : SimpleActivity(), RefreshContactsListener { private var isGettingContacts = false private var ignoredExportContactSources = HashSet() - private var storedTextColor = 0 - private var storedBackgroundColor = 0 - private var storedPrimaryColor = 0 private var storedShowContactThumbnails = false private var storedShowPhoneNumbers = false private var storedStartNameWithSurname = false @@ -114,29 +111,14 @@ class MainActivity : SimpleActivity(), RefreshContactsListener { } } - val configTextColor = config.textColor - if (storedTextColor != configTextColor) { - getInactiveTabIndexes(viewpager.currentItem).forEach { - main_tabs_holder.getTabAt(it)?.icon?.applyColorFilter(configTextColor) - } - getAllFragments().forEach { - it?.textColorChanged(configTextColor) - } + val adjustedPrimaryColor = getAdjustedPrimaryColor() + main_tabs_holder.background = ColorDrawable(config.backgroundColor) + main_tabs_holder.setSelectedTabIndicatorColor(adjustedPrimaryColor) + getAllFragments().forEach { + it?.setupColors(config.textColor, adjustedPrimaryColor) } - val configBackgroundColor = config.backgroundColor - if (storedBackgroundColor != configBackgroundColor) { - main_tabs_holder.background = ColorDrawable(configBackgroundColor) - } - - val configPrimaryColor = config.primaryColor - if (storedPrimaryColor != configPrimaryColor) { - main_tabs_holder.setSelectedTabIndicatorColor(getAdjustedPrimaryColor()) - main_tabs_holder.getTabAt(viewpager.currentItem)?.icon?.applyColorFilter(getAdjustedPrimaryColor()) - getAllFragments().forEach { - it?.primaryColorChanged() - } - } + updateTabColors() val configStartNameWithSurname = config.startNameWithSurname if (storedStartNameWithSurname != configStartNameWithSurname) { @@ -156,17 +138,13 @@ class MainActivity : SimpleActivity(), RefreshContactsListener { initFragments() } else { refreshContacts(ALL_TABS_MASK) - - getAllFragments().forEach { - it?.onActivityResume() - } } } - val dialpadIcon = resources.getColoredDrawableWithColor(R.drawable.ic_dialpad_vector, getFABIconColor()) + val dialpadIcon = resources.getColoredDrawableWithColor(R.drawable.ic_dialpad_vector, adjustedPrimaryColor.getContrastColor()) main_dialpad_button.apply { setImageDrawable(dialpadIcon) - background.applyColorFilter(getAdjustedPrimaryColor()) + background.applyColorFilter(adjustedPrimaryColor) beVisibleIf(config.showDialpadButton) } @@ -233,9 +211,6 @@ class MainActivity : SimpleActivity(), RefreshContactsListener { private fun storeStateVariables() { config.apply { - storedTextColor = textColor - storedBackgroundColor = backgroundColor - storedPrimaryColor = primaryColor storedShowContactThumbnails = showContactThumbnails storedShowPhoneNumbers = showPhoneNumbers storedStartNameWithSurname = startNameWithSurname @@ -280,6 +255,13 @@ class MainActivity : SimpleActivity(), RefreshContactsListener { }) } + private fun updateTabColors() { + getInactiveTabIndexes(viewpager.currentItem).forEach { + main_tabs_holder.getTabAt(it)?.icon?.applyColorFilter(config.textColor) + } + main_tabs_holder.getTabAt(viewpager.currentItem)?.icon?.applyColorFilter(getAdjustedPrimaryColor()) + } + private fun getSearchString(): Int { return when (getCurrentFragment()) { favorites_fragment -> R.string.search_favorites @@ -528,7 +510,7 @@ class MainActivity : SimpleActivity(), RefreshContactsListener { } private fun exportContactsTo(ignoredContactSources: HashSet, outputStream: OutputStream?) { - ContactsHelper(this).getContacts(true, ignoredContactSources) { contacts -> + ContactsHelper(this).getContacts(true, false, ignoredContactSources) { contacts -> if (contacts.isEmpty()) { toast(R.string.no_entries_for_exporting) } else { @@ -567,6 +549,7 @@ class MainActivity : SimpleActivity(), RefreshContactsListener { if (viewpager.adapter == null) { viewpager.adapter = ViewPagerAdapter(this, tabsList, config.showTabs) viewpager.currentItem = getDefaultTab() + updateTabColors() } ContactsHelper(this).getContacts { contacts -> diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/ViewContactActivity.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/ViewContactActivity.kt index d3990529..9b133ccb 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/ViewContactActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/activities/ViewContactActivity.kt @@ -2,19 +2,18 @@ package com.simplemobiletools.contacts.pro.activities import android.content.ContentUris import android.content.Intent -import android.graphics.Color -import android.graphics.drawable.ColorDrawable +import android.media.AudioManager +import android.media.RingtoneManager +import android.net.Uri import android.os.Bundle import android.provider.ContactsContract import android.view.View import android.view.WindowManager import android.widget.RelativeLayout import com.simplemobiletools.commons.dialogs.ConfirmationDialog +import com.simplemobiletools.commons.dialogs.SelectAlarmSoundDialog import com.simplemobiletools.commons.extensions.* -import com.simplemobiletools.commons.helpers.CONTACT_ID -import com.simplemobiletools.commons.helpers.IS_PRIVATE -import com.simplemobiletools.commons.helpers.PERMISSION_READ_CONTACTS -import com.simplemobiletools.commons.helpers.ensureBackgroundThread +import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.dialogs.CallConfirmationDialog import com.simplemobiletools.contacts.pro.dialogs.ChooseSocialDialog @@ -175,7 +174,7 @@ class ViewContactActivity : ContactActivity() { val textColor = config.textColor arrayOf(contact_name_image, contact_numbers_image, contact_emails_image, contact_addresses_image, contact_events_image, contact_source_image, - contact_notes_image, contact_organization_image, contact_websites_image, contact_groups_image).forEach { + contact_notes_image, contact_ringtone_image, contact_organization_image, contact_websites_image, contact_groups_image).forEach { it.applyColorFilter(textColor) } @@ -217,6 +216,7 @@ class ViewContactActivity : ContactActivity() { setupGroups() setupContactSources() setupNotes() + setupRingtone() setupOrganization() updateTextColors(contact_scrollview) } @@ -255,36 +255,11 @@ class ViewContactActivity : ContactActivity() { } private fun setupNames() { - contact!!.apply { - contact_prefix.text = prefix - contact_prefix.beVisibleIf(prefix.isNotEmpty() && showFields and SHOW_PREFIX_FIELD != 0) - contact_prefix.copyOnLongClick(prefix) - - contact_first_name.text = firstName - contact_first_name.beVisibleIf(firstName.isNotEmpty() && showFields and SHOW_FIRST_NAME_FIELD != 0) - contact_first_name.copyOnLongClick(firstName) - - contact_middle_name.text = middleName - contact_middle_name.beVisibleIf(middleName.isNotEmpty() && showFields and SHOW_MIDDLE_NAME_FIELD != 0) - contact_middle_name.copyOnLongClick(middleName) - - contact_surname.text = surname - contact_surname.beVisibleIf(surname.isNotEmpty() && showFields and SHOW_SURNAME_FIELD != 0) - contact_surname.copyOnLongClick(surname) - - contact_suffix.text = suffix - contact_suffix.beVisibleIf(suffix.isNotEmpty() && showFields and SHOW_SUFFIX_FIELD != 0) - contact_suffix.copyOnLongClick(suffix) - - contact_nickname.text = nickname - contact_nickname.beVisibleIf(nickname.isNotEmpty() && showFields and SHOW_NICKNAME_FIELD != 0) - contact_nickname.copyOnLongClick(nickname) - - if (contact_prefix.isGone() && contact_first_name.isGone() && contact_middle_name.isGone() && contact_surname.isGone() && contact_suffix.isGone() - && contact_nickname.isGone()) { - contact_name_image.beInvisible() - } - } + val displayName = contact!!.getNameToDisplay() + contact_name.text = displayName + contact_name.copyOnLongClick(displayName) + contact_name.beVisibleIf(displayName.isNotEmpty() && !contact!!.isABusinessContact()) + contact_name_image.beInvisibleIf(contact_name.isGone()) } private fun setupPhoneNumbers() { @@ -564,6 +539,14 @@ class ViewContactActivity : ContactActivity() { showSocialActions(key.id) } } + + if (value.toLowerCase() == THREEMA) { + contact_source_image.setImageDrawable(getPackageDrawable(THREEMA_PACKAGE)) + contact_source_image.beVisible() + contact_source_image.setOnClickListener { + showSocialActions(key.id) + } + } } } @@ -588,6 +571,43 @@ class ViewContactActivity : ContactActivity() { } } + private fun setupRingtone() { + if (showFields and SHOW_RINGTONE_FIELD != 0) { + contact_ringtone_image.beVisible() + contact_ringtone.beVisible() + + val ringtone = contact!!.ringtone + if (ringtone != null && ringtone.isNotEmpty()) { + if (ringtone == SILENT) { + contact_ringtone.text = getString(R.string.no_sound) + } else { + val contactRingtone = RingtoneManager.getRingtone(this, Uri.parse(ringtone)) + val ringtoneTitle = contactRingtone.getTitle(this) + contact_ringtone.text = ringtoneTitle + } + } else { + contact_ringtone_image.beGone() + contact_ringtone.beGone() + return + } + + contact_ringtone.copyOnLongClick(contact_ringtone.text.toString()) + + contact_ringtone.setOnClickListener { + val currentRingtone = contact!!.ringtone ?: getDefaultAlarmSound(RingtoneManager.TYPE_RINGTONE).uri + SelectAlarmSoundDialog(this, currentRingtone, AudioManager.STREAM_RING, PICK_RINGTONE_INTENT_ID, RingtoneManager.TYPE_RINGTONE, true, + onAlarmPicked = { + contact_ringtone.text = it?.title + ringtoneUpdated(it?.uri) + }, onAlarmSoundDeleted = {} + ) + } + } else { + contact_ringtone_image.beGone() + contact_ringtone.beGone() + } + } + private fun setupOrganization() { val organization = contact!!.organization if (organization.isNotEmpty() && showFields and SHOW_ORGANIZATION_FIELD != 0) { @@ -625,6 +645,23 @@ class ViewContactActivity : ContactActivity() { } } + override fun customRingtoneSelected(ringtonePath: String) { + contact_ringtone.text = ringtonePath.getFilenameFromPath() + ringtoneUpdated(ringtonePath) + } + + private fun ringtoneUpdated(path: String?) { + contact!!.ringtone = path + + ensureBackgroundThread { + if (contact!!.isPrivate()) { + LocalContactsHelper(this).updateRingtone(contact!!.contactId, path ?: "") + } else { + ContactsHelper(this).updateRingtone(contact!!.contactId.toString(), path ?: "") + } + } + } + private fun getDuplicateContacts(callback: () -> Unit) { ContactsHelper(this).getDuplicatesOfContact(contact!!, false) { contacts -> ensureBackgroundThread { diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/adapters/ContactsAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/adapters/ContactsAdapter.kt index dae16557..fd01c50d 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/adapters/ContactsAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/adapters/ContactsAdapter.kt @@ -15,7 +15,10 @@ import com.bumptech.glide.signature.ObjectKey import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter import com.simplemobiletools.commons.dialogs.ConfirmationDialog import com.simplemobiletools.commons.dialogs.RadioGroupDialog -import com.simplemobiletools.commons.extensions.* +import com.simplemobiletools.commons.extensions.beVisibleIf +import com.simplemobiletools.commons.extensions.getTextSize +import com.simplemobiletools.commons.extensions.highlightTextFromNumbers +import com.simplemobiletools.commons.extensions.highlightTextPart import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.commons.views.FastScroller diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/adapters/ViewPagerAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/adapters/ViewPagerAdapter.kt index e4cb8d3e..f88c1566 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/adapters/ViewPagerAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/adapters/ViewPagerAdapter.kt @@ -3,11 +3,13 @@ package com.simplemobiletools.contacts.pro.adapters import android.view.View import android.view.ViewGroup import androidx.viewpager.widget.PagerAdapter +import com.simplemobiletools.commons.extensions.getAdjustedPrimaryColor import com.simplemobiletools.commons.helpers.TAB_CONTACTS import com.simplemobiletools.commons.helpers.TAB_FAVORITES import com.simplemobiletools.commons.helpers.TAB_GROUPS import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.activities.SimpleActivity +import com.simplemobiletools.contacts.pro.extensions.config import com.simplemobiletools.contacts.pro.fragments.MyViewPagerFragment class ViewPagerAdapter(val activity: SimpleActivity, val currTabsList: ArrayList, val showTabs: Int) : PagerAdapter() { @@ -19,6 +21,7 @@ class ViewPagerAdapter(val activity: SimpleActivity, val currTabsList: ArrayList (view as MyViewPagerFragment).apply { setupFragment(activity) + setupColors(activity.config.textColor, activity.getAdjustedPrimaryColor()) } return view diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/databases/ContactsDatabase.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/databases/ContactsDatabase.kt index 042ab5c0..b078c7e5 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/databases/ContactsDatabase.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/databases/ContactsDatabase.kt @@ -17,7 +17,7 @@ import com.simplemobiletools.contacts.pro.models.Group import com.simplemobiletools.contacts.pro.models.LocalContact import java.util.concurrent.Executors -@Database(entities = [LocalContact::class, Group::class], version = 2) +@Database(entities = [LocalContact::class, Group::class], version = 3) @TypeConverters(Converters::class) abstract class ContactsDatabase : RoomDatabase() { @@ -40,6 +40,7 @@ abstract class ContactsDatabase : RoomDatabase() { } }) .addMigrations(MIGRATION_1_2) + .addMigrations(MIGRATION_2_3) .build() } } @@ -77,5 +78,13 @@ abstract class ContactsDatabase : RoomDatabase() { } } } + + private val MIGRATION_2_3 = object : Migration(2, 3) { + override fun migrate(database: SupportSQLiteDatabase) { + database.apply { + execSQL("ALTER TABLE contacts ADD COLUMN ringtone TEXT DEFAULT ''") + } + } + } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/dialogs/ManageVisibleFieldsDialog.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/dialogs/ManageVisibleFieldsDialog.kt index d6444e1f..3bcb36e1 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/dialogs/ManageVisibleFieldsDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/dialogs/ManageVisibleFieldsDialog.kt @@ -30,6 +30,7 @@ class ManageVisibleFieldsDialog(val activity: BaseSimpleActivity) { put(SHOW_WEBSITES_FIELD, R.id.manage_visible_fields_websites) put(SHOW_GROUPS_FIELD, R.id.manage_visible_fields_groups) put(SHOW_CONTACT_SOURCE_FIELD, R.id.manage_visible_fields_contact_source) + put(SHOW_RINGTONE_FIELD, R.id.manage_ringtone) } val showContactFields = activity.config.showContactFields @@ -38,11 +39,11 @@ class ManageVisibleFieldsDialog(val activity: BaseSimpleActivity) { } AlertDialog.Builder(activity) - .setPositiveButton(R.string.ok) { dialog, which -> dialogConfirmed() } - .setNegativeButton(R.string.cancel, null) - .create().apply { - activity.setupDialogStuff(view, this) - } + .setPositiveButton(R.string.ok) { dialog, which -> dialogConfirmed() } + .setNegativeButton(R.string.cancel, null) + .create().apply { + activity.setupDialogStuff(view, this) + } } private fun dialogConfirmed() { diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/dialogs/SelectGroupsDialog.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/dialogs/SelectGroupsDialog.kt index 25e97f5b..0367c611 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/dialogs/SelectGroupsDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/dialogs/SelectGroupsDialog.kt @@ -2,6 +2,7 @@ package com.simplemobiletools.contacts.pro.dialogs import android.view.ViewGroup import androidx.appcompat.app.AlertDialog +import com.simplemobiletools.commons.extensions.getAdjustedPrimaryColor import com.simplemobiletools.commons.extensions.setupDialogStuff import com.simplemobiletools.commons.views.MyAppCompatCheckbox import com.simplemobiletools.contacts.pro.R @@ -51,11 +52,12 @@ class SelectGroupsDialog(val activity: SimpleActivity, val selectedGroups: Array item_checkbox_holder.setOnClickListener { item_checkbox.toggle() } + item_checkbox.apply { isChecked = selectedGroups.contains(group) text = group.title tag = group.id - setColors(config.textColor, config.primaryColor, config.backgroundColor) + setColors(config.textColor, activity.getAdjustedPrimaryColor(), config.backgroundColor) } view.dialog_groups_holder.addView(this) } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/extensions/Context.kt index 9ad033d4..91cef212 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/extensions/Context.kt @@ -36,7 +36,7 @@ fun Context.getEmptyContact(): Contact { val originalContactSource = if (hasContactPermissions()) config.lastUsedContactSource else SMT_PRIVATE val organization = Organization("", "") return Contact(0, "", "", "", "", "", "", "", ArrayList(), ArrayList(), ArrayList(), ArrayList(), originalContactSource, 0, 0, "", - null, "", ArrayList(), organization, ArrayList(), ArrayList()) + null, "", ArrayList(), organization, ArrayList(), ArrayList(), DEFAULT_MIMETYPE, null) } fun Context.viewContact(contact: Contact) { @@ -66,17 +66,6 @@ fun Context.sendEmailIntent(recipient: String) { } } -fun Context.sendSMSIntent(recipient: String) { - Intent(Intent.ACTION_SENDTO).apply { - data = Uri.fromParts("smsto", recipient, null) - if (resolveActivity(packageManager) != null) { - startActivity(this) - } else { - toast(R.string.no_app_found) - } - } -} - fun Context.sendAddressIntent(address: String) { val location = Uri.encode(address) val uri = Uri.parse("geo:0,0?q=$location") @@ -91,8 +80,14 @@ fun Context.sendAddressIntent(address: String) { } fun Context.openWebsiteIntent(url: String) { + val website = if (url.startsWith("http")) { + url + } else { + "https://$url" + } + Intent(Intent.ACTION_VIEW).apply { - data = Uri.parse(url) + data = Uri.parse(website) if (resolveActivity(packageManager) != null) { startActivity(this) } else { @@ -364,6 +359,10 @@ fun Context.getSocialActions(id: Int): ArrayList { "vnd.android.cursor.item/vnd.org.telegram.messenger.android.call" -> SOCIAL_VOICE_CALL "vnd.android.cursor.item/vnd.org.telegram.messenger.android.call.video" -> SOCIAL_VIDEO_CALL "vnd.android.cursor.item/vnd.org.telegram.messenger.android.profile" -> SOCIAL_MESSAGE + + // Threema + "vnd.android.cursor.item/vnd.ch.threema.app.profile" -> SOCIAL_MESSAGE + "vnd.android.cursor.item/vnd.ch.threema.app.call" -> SOCIAL_VOICE_CALL else -> return@queryCursor } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/fragments/MyViewPagerFragment.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/fragments/MyViewPagerFragment.kt index e526708b..ea1eb5a7 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/fragments/MyViewPagerFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/fragments/MyViewPagerFragment.kt @@ -61,7 +61,6 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet) } fragment_placeholder_2?.underlineText() - updateViewStuff() when { this is FavoritesFragment -> { @@ -76,22 +75,24 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet) } } - fun textColorChanged(color: Int) { + fun setupColors(textColor: Int, adjustedPrimaryColor: Int) { when { - this is GroupsFragment -> (fragment_list.adapter as GroupsAdapter).updateTextColor(color) + this is GroupsFragment -> (fragment_list.adapter as? GroupsAdapter)?.updateTextColor(textColor) else -> (fragment_list.adapter as? ContactsAdapter)?.apply { - updateTextColor(color) + updateTextColor(textColor) } } - letter_fastscroller?.textColor = color.getColorStateList() - } - - fun primaryColorChanged() { + context.updateTextColors(fragment_wrapper.parent as ViewGroup) fragment_fastscroller?.updatePrimaryColor() fragment_fastscroller?.updateBubblePrimaryColor() - letter_fastscroller_thumb?.thumbColor = config.primaryColor.getColorStateList() - letter_fastscroller_thumb?.textColor = config.primaryColor.getContrastColor() + fragment_placeholder_2?.setTextColor(adjustedPrimaryColor) + + letter_fastscroller?.textColor = textColor.getColorStateList() + letter_fastscroller?.pressedTextColor = adjustedPrimaryColor + letter_fastscroller_thumb?.fontSize = context.getTextSize() + letter_fastscroller_thumb?.textColor = adjustedPrimaryColor.getContrastColor() + letter_fastscroller_thumb?.thumbColor = adjustedPrimaryColor.getColorStateList() } fun startNameWithSurnameChanged(startNameWithSurname: Boolean) { @@ -143,11 +144,8 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet) } else { setupContactsFavoritesAdapter(contacts) contactsIgnoringSearch = (fragment_list?.adapter as? ContactsAdapter)?.contactItems ?: ArrayList() - - letter_fastscroller.textColor = config.textColor.getColorStateList() setupLetterFastscroller(contacts) letter_fastscroller_thumb.setupWithFastScroller(letter_fastscroller) - letter_fastscroller_thumb.textColor = config.primaryColor.getContrastColor() } } @@ -274,10 +272,6 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet) } } - fun onActivityResume() { - updateViewStuff() - } - fun finishActMode() { (fragment_list.adapter as? MyRecyclerViewAdapter)?.finishActMode() } @@ -288,18 +282,18 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet) val shouldNormalize = text.normalizeString() == text val filtered = contactsIgnoringSearch.filter { getProperText(it.getNameToDisplay(), shouldNormalize).contains(text, true) || - getProperText(it.nickname, shouldNormalize).contains(text, true) || - it.phoneNumbers.any { - text.normalizePhoneNumber().isNotEmpty() && (it.normalizedNumber - ?: it.value).contains(text.normalizePhoneNumber(), true) - } || - it.emails.any { it.value.contains(text, true) } || - it.addresses.any { getProperText(it.value, shouldNormalize).contains(text, true) } || - it.IMs.any { it.value.contains(text, true) } || - getProperText(it.notes, shouldNormalize).contains(text, true) || - getProperText(it.organization.company, shouldNormalize).contains(text, true) || - getProperText(it.organization.jobPosition, shouldNormalize).contains(text, true) || - it.websites.any { it.contains(text, true) } + getProperText(it.nickname, shouldNormalize).contains(text, true) || + it.phoneNumbers.any { + text.normalizePhoneNumber().isNotEmpty() && (it.normalizedNumber + ?: it.value).contains(text.normalizePhoneNumber(), true) + } || + it.emails.any { it.value.contains(text, true) } || + it.addresses.any { getProperText(it.value, shouldNormalize).contains(text, true) } || + it.IMs.any { it.value.contains(text, true) } || + getProperText(it.notes, shouldNormalize).contains(text, true) || + getProperText(it.organization.company, shouldNormalize).contains(text, true) || + getProperText(it.organization.jobPosition, shouldNormalize).contains(text, true) || + it.websites.any { it.contains(text, true) } } as ArrayList filtered.sortBy { @@ -348,13 +342,6 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet) } } - private fun updateViewStuff() { - context.updateTextColors(fragment_wrapper.parent as ViewGroup) - fragment_fastscroller?.updateBubbleColors() - fragment_placeholder_2?.setTextColor(context.getAdjustedPrimaryColor()) - letter_fastscroller_thumb?.fontSize = context.getTextSize() - } - private fun setupViewVisibility(hasItemsToShow: Boolean) { fragment_placeholder_2?.beVisibleIf(!hasItemsToShow) fragment_placeholder?.beVisibleIf(!hasItemsToShow) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/Constants.kt index ca6720f4..a52405fa 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/Constants.kt @@ -93,6 +93,7 @@ const val SHOW_CONTACT_SOURCE_FIELD = 4096 const val SHOW_WEBSITES_FIELD = 8192 const val SHOW_NICKNAME_FIELD = 16384 const val SHOW_IMS_FIELD = 32768 +const val SHOW_RINGTONE_FIELD = 65536 const val DEFAULT_EMAIL_TYPE = CommonDataKinds.Email.TYPE_HOME const val DEFAULT_PHONE_NUMBER_TYPE = CommonDataKinds.Phone.TYPE_MOBILE @@ -101,22 +102,25 @@ const val DEFAULT_EVENT_TYPE = CommonDataKinds.Event.TYPE_BIRTHDAY const val DEFAULT_ORGANIZATION_TYPE = CommonDataKinds.Organization.TYPE_WORK const val DEFAULT_WEBSITE_TYPE = CommonDataKinds.Website.TYPE_HOMEPAGE const val DEFAULT_IM_TYPE = CommonDataKinds.Im.PROTOCOL_SKYPE +const val DEFAULT_MIMETYPE = CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE // apps with special handling const val TELEGRAM_PACKAGE = "org.telegram.messenger" const val SIGNAL_PACKAGE = "org.thoughtcrime.securesms" const val WHATSAPP_PACKAGE = "com.whatsapp" const val VIBER_PACKAGE = "com.viber.voip" +const val THREEMA_PACKAGE = "ch.threema.app" const val WHATSAPP = "whatsapp" const val SIGNAL = "signal" const val VIBER = "viber" const val TELEGRAM = "telegram" +const val THREEMA = "threema" const val SOCIAL_VOICE_CALL = 0 const val SOCIAL_VIDEO_CALL = 1 const val SOCIAL_MESSAGE = 2 -fun getEmptyLocalContact() = LocalContact(0, "", "", "", "", "", "", null, "", ArrayList(), ArrayList(), ArrayList(), 0, ArrayList(), "", ArrayList(), "", "", ArrayList(), ArrayList()) +fun getEmptyLocalContact() = LocalContact(0, "", "", "", "", "", "", null, "", ArrayList(), ArrayList(), ArrayList(), 0, ArrayList(), "", ArrayList(), "", "", ArrayList(), ArrayList(), null) fun getProperText(text: String, shouldNormalize: Boolean) = if (shouldNormalize) text.normalizeString() else text diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/ContactsHelper.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/ContactsHelper.kt index b771c496..66482c12 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/ContactsHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/ContactsHelper.kt @@ -28,7 +28,7 @@ class ContactsHelper(val context: Context) { private val BATCH_SIZE = 50 private var displayContactSources = ArrayList() - fun getContacts(getAll: Boolean = false, ignoredContactSources: HashSet = HashSet(), callback: (ArrayList) -> Unit) { + fun getContacts(getAll: Boolean = false, gettingDuplicates: Boolean = false, ignoredContactSources: HashSet = HashSet(), callback: (ArrayList) -> Unit) { ensureBackgroundThread { val contacts = SparseArray() displayContactSources = context.getVisibleContactSources() @@ -43,7 +43,7 @@ class ContactsHelper(val context: Context) { } } - getDeviceContacts(contacts, ignoredContactSources) + getDeviceContacts(contacts, ignoredContactSources, gettingDuplicates) if (displayContactSources.contains(SMT_PRIVATE)) { LocalContactsHelper(context).getAllContacts().forEach { @@ -125,7 +125,7 @@ class ContactsHelper(val context: Context) { } } - private fun getDeviceContacts(contacts: SparseArray, ignoredContactSources: HashSet?) { + private fun getDeviceContacts(contacts: SparseArray, ignoredContactSources: HashSet?, gettingDuplicates: Boolean) { if (!context.hasContactPermissions()) { return } @@ -134,55 +134,87 @@ class ContactsHelper(val context: Context) { val uri = Data.CONTENT_URI val projection = getContactProjection() - val selection = "${Data.MIMETYPE} = ? OR ${Data.MIMETYPE} = ?" - val selectionArgs = arrayOf(StructuredName.CONTENT_ITEM_TYPE, CommonDataKinds.Organization.CONTENT_ITEM_TYPE) - val sortOrder = getSortString() + arrayOf(CommonDataKinds.Organization.CONTENT_ITEM_TYPE, StructuredName.CONTENT_ITEM_TYPE).forEach { mimetype -> + val selection = "${Data.MIMETYPE} = ?" + val selectionArgs = arrayOf(mimetype) + val sortOrder = getSortString() - context.queryCursor(uri, projection, selection, selectionArgs, sortOrder, true) { cursor -> - val accountName = cursor.getStringValue(RawContacts.ACCOUNT_NAME) ?: "" - val accountType = cursor.getStringValue(RawContacts.ACCOUNT_TYPE) ?: "" - if (ignoredSources.contains("$accountName:$accountType")) { - return@queryCursor + context.queryCursor(uri, projection, selection, selectionArgs, sortOrder, true) { cursor -> + val accountName = cursor.getStringValue(RawContacts.ACCOUNT_NAME) ?: "" + val accountType = cursor.getStringValue(RawContacts.ACCOUNT_TYPE) ?: "" + + if (ignoredSources.contains("$accountName:$accountType")) { + return@queryCursor + } + + val id = cursor.getIntValue(Data.RAW_CONTACT_ID) + var prefix = "" + var firstName = "" + var middleName = "" + var surname = "" + var suffix = "" + + // ignore names at Organization type contacts + if (mimetype == StructuredName.CONTENT_ITEM_TYPE) { + prefix = cursor.getStringValue(StructuredName.PREFIX) ?: "" + firstName = cursor.getStringValue(StructuredName.GIVEN_NAME) ?: "" + middleName = cursor.getStringValue(StructuredName.MIDDLE_NAME) ?: "" + surname = cursor.getStringValue(StructuredName.FAMILY_NAME) ?: "" + suffix = cursor.getStringValue(StructuredName.SUFFIX) ?: "" + } + + var photoUri = "" + var starred = 0 + var contactId = 0 + var thumbnailUri = "" + var ringtone: String? = null + + if (!gettingDuplicates) { + photoUri = cursor.getStringValue(StructuredName.PHOTO_URI) ?: "" + starred = cursor.getIntValue(StructuredName.STARRED) + contactId = cursor.getIntValue(Data.CONTACT_ID) + thumbnailUri = cursor.getStringValue(StructuredName.PHOTO_THUMBNAIL_URI) ?: "" + ringtone = cursor.getStringValue(StructuredName.CUSTOM_RINGTONE) + } + + val nickname = "" + val numbers = ArrayList() // proper value is obtained below + val emails = ArrayList() + val addresses = ArrayList
() + val events = ArrayList() + val notes = "" + val groups = ArrayList() + val organization = Organization("", "") + val websites = ArrayList() + val ims = ArrayList() + val contact = Contact(id, prefix, firstName, middleName, surname, suffix, nickname, photoUri, numbers, emails, addresses, + events, accountName, starred, contactId, thumbnailUri, null, notes, groups, organization, websites, ims, mimetype, ringtone) + + contacts.put(id, contact) } + } - val id = cursor.getIntValue(Data.RAW_CONTACT_ID) - var prefix = "" - var firstName = "" - var middleName = "" - var surname = "" - var suffix = "" + val emails = getEmails() + var size = emails.size() + for (i in 0 until size) { + val key = emails.keyAt(i) + contacts[key]?.emails = emails.valueAt(i) + } - // ignore names at Organization type contacts - if (cursor.getStringValue(Data.MIMETYPE) == StructuredName.CONTENT_ITEM_TYPE) { - prefix = cursor.getStringValue(StructuredName.PREFIX) ?: "" - firstName = cursor.getStringValue(StructuredName.GIVEN_NAME) ?: "" - middleName = cursor.getStringValue(StructuredName.MIDDLE_NAME) ?: "" - surname = cursor.getStringValue(StructuredName.FAMILY_NAME) ?: "" - suffix = cursor.getStringValue(StructuredName.SUFFIX) ?: "" - } + val organizations = getOrganizations() + size = organizations.size() + for (i in 0 until size) { + val key = organizations.keyAt(i) + contacts[key]?.organization = organizations.valueAt(i) + } - val nickname = "" - val photoUri = cursor.getStringValue(StructuredName.PHOTO_URI) ?: "" - val numbers = ArrayList() // proper value is obtained below - val emails = ArrayList() - val addresses = ArrayList
() - val events = ArrayList() - val starred = cursor.getIntValue(StructuredName.STARRED) - val contactId = cursor.getIntValue(Data.CONTACT_ID) - val thumbnailUri = cursor.getStringValue(StructuredName.PHOTO_THUMBNAIL_URI) ?: "" - val notes = "" - val groups = ArrayList() - val organization = Organization("", "") - val websites = ArrayList() - val ims = ArrayList() - val contact = Contact(id, prefix, firstName, middleName, surname, suffix, nickname, photoUri, numbers, emails, addresses, - events, accountName, starred, contactId, thumbnailUri, null, notes, groups, organization, websites, ims) - - contacts.put(id, contact) + // no need to fetch some fields if we are only getting duplicates of the current contact + if (gettingDuplicates) { + return } val phoneNumbers = getPhoneNumbers(null) - var size = phoneNumbers.size() + size = phoneNumbers.size() for (i in 0 until size) { val key = phoneNumbers.keyAt(i) if (contacts[key] != null) { @@ -191,20 +223,6 @@ class ContactsHelper(val context: Context) { } } - val nicknames = getNicknames() - size = nicknames.size() - for (i in 0 until size) { - val key = nicknames.keyAt(i) - contacts[key]?.nickname = nicknames.valueAt(i) - } - - val emails = getEmails() - size = emails.size() - for (i in 0 until size) { - val key = emails.keyAt(i) - contacts[key]?.emails = emails.valueAt(i) - } - val addresses = getAddresses() size = addresses.size() for (i in 0 until size) { @@ -233,13 +251,6 @@ class ContactsHelper(val context: Context) { contacts[key]?.notes = notes.valueAt(i) } - val organizations = getOrganizations() - size = organizations.size() - for (i in 0 until size) { - val key = organizations.keyAt(i) - contacts[key]?.organization = organizations.valueAt(i) - } - val websites = getWebsites() size = websites.size() for (i in 0 until size) { @@ -695,9 +706,10 @@ class ContactsHelper(val context: Context) { var middleName = "" var surname = "" var suffix = "" + val mimetype = cursor.getStringValue(Data.MIMETYPE) // ignore names at Organization type contacts - if (cursor.getStringValue(Data.MIMETYPE) == StructuredName.CONTENT_ITEM_TYPE) { + if (mimetype == StructuredName.CONTENT_ITEM_TYPE) { prefix = cursor.getStringValue(StructuredName.PREFIX) ?: "" firstName = cursor.getStringValue(StructuredName.GIVEN_NAME) ?: "" middleName = cursor.getStringValue(StructuredName.MIDDLE_NAME) ?: "" @@ -714,6 +726,7 @@ class ContactsHelper(val context: Context) { val notes = getNotes(id)[id] ?: "" val accountName = cursor.getStringValue(RawContacts.ACCOUNT_NAME) ?: "" val starred = cursor.getIntValue(StructuredName.STARRED) + val ringtone = cursor.getStringValue(StructuredName.CUSTOM_RINGTONE) val contactId = cursor.getIntValue(Data.CONTACT_ID) val groups = getContactGroups(storedGroups, contactId)[contactId] ?: ArrayList() val thumbnailUri = cursor.getStringValue(StructuredName.PHOTO_THUMBNAIL_URI) ?: "" @@ -721,7 +734,7 @@ class ContactsHelper(val context: Context) { val websites = getWebsites(id)[id] ?: ArrayList() val ims = getIMs(id)[id] ?: ArrayList() return Contact(id, prefix, firstName, middleName, surname, suffix, nickname, photoUri, number, emails, addresses, events, - accountName, starred, contactId, thumbnailUri, null, notes, groups, organization, websites, ims) + accountName, starred, contactId, thumbnailUri, null, notes, groups, organization, websites, ims, mimetype, ringtone) } } @@ -745,7 +758,8 @@ class ContactsHelper(val context: Context) { val ignoredTypes = arrayListOf( SIGNAL_PACKAGE, TELEGRAM_PACKAGE, - WHATSAPP_PACKAGE + WHATSAPP_PACKAGE, + THREEMA_PACKAGE ) val contactSources = getContactSourcesSync() @@ -819,6 +833,7 @@ class ContactsHelper(val context: Context) { StructuredName.PHOTO_URI, StructuredName.PHOTO_THUMBNAIL_URI, StructuredName.STARRED, + StructuredName.CUSTOM_RINGTONE, RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE ) @@ -858,8 +873,8 @@ class ContactsHelper(val context: Context) { try { val operations = ArrayList() ContentProviderOperation.newUpdate(Data.CONTENT_URI).apply { - val selection = "${Data.RAW_CONTACT_ID} = ? AND (${Data.MIMETYPE} = ? OR ${Data.MIMETYPE} = ?)" - val selectionArgs = arrayOf(contact.id.toString(), StructuredName.CONTENT_ITEM_TYPE, CommonDataKinds.Organization.CONTENT_ITEM_TYPE) + val selection = "${Data.RAW_CONTACT_ID} = ? AND ${Data.MIMETYPE} = ?" + val selectionArgs = arrayOf(contact.id.toString(), contact.mimetype) withSelection(selection, selectionArgs) withValue(StructuredName.PREFIX, contact.prefix) withValue(StructuredName.GIVEN_NAME, contact.firstName) @@ -1010,14 +1025,16 @@ class ContactsHelper(val context: Context) { } // add organization - ContentProviderOperation.newInsert(Data.CONTENT_URI).apply { - withValue(Data.RAW_CONTACT_ID, contact.id) - withValue(Data.MIMETYPE, CommonDataKinds.Organization.CONTENT_ITEM_TYPE) - withValue(CommonDataKinds.Organization.COMPANY, contact.organization.company) - withValue(CommonDataKinds.Organization.TYPE, DEFAULT_ORGANIZATION_TYPE) - withValue(CommonDataKinds.Organization.TITLE, contact.organization.jobPosition) - withValue(CommonDataKinds.Organization.TYPE, DEFAULT_ORGANIZATION_TYPE) - operations.add(build()) + if (contact.organization.isNotEmpty()) { + ContentProviderOperation.newInsert(Data.CONTENT_URI).apply { + withValue(Data.RAW_CONTACT_ID, contact.id) + withValue(Data.MIMETYPE, CommonDataKinds.Organization.CONTENT_ITEM_TYPE) + withValue(CommonDataKinds.Organization.COMPANY, contact.organization.company) + withValue(CommonDataKinds.Organization.TYPE, DEFAULT_ORGANIZATION_TYPE) + withValue(CommonDataKinds.Organization.TITLE, contact.organization.jobPosition) + withValue(CommonDataKinds.Organization.TYPE, DEFAULT_ORGANIZATION_TYPE) + operations.add(build()) + } } // delete websites @@ -1061,11 +1078,12 @@ class ContactsHelper(val context: Context) { } } - // favorite + // favorite, ringtone try { val uri = Uri.withAppendedPath(Contacts.CONTENT_URI, contact.contactId.toString()) - val contentValues = ContentValues(1) + val contentValues = ContentValues(2) contentValues.put(Contacts.STARRED, contact.starred) + contentValues.put(Contacts.CUSTOM_RINGTONE, contact.ringtone) context.contentResolver.update(uri, contentValues, null, null) } catch (e: Exception) { context.showErrorToast(e) @@ -1327,12 +1345,13 @@ class ContactsHelper(val context: Context) { addFullSizePhoto(rawId, fullSizePhotoData) } - // favorite + // favorite, ringtone val userId = getRealContactId(rawId) - if (userId != 0 && contact.starred == 1) { + if (userId != 0) { val uri = Uri.withAppendedPath(Contacts.CONTENT_URI, userId.toString()) - val contentValues = ContentValues(1) + val contentValues = ContentValues(2) contentValues.put(Contacts.STARRED, contact.starred) + contentValues.put(Contacts.CUSTOM_RINGTONE, contact.ringtone) context.contentResolver.update(uri, contentValues, null, null) } @@ -1413,6 +1432,21 @@ class ContactsHelper(val context: Context) { LocalContactsHelper(context).toggleFavorites(localContacts, addToFavorites) } + fun updateRingtone(contactId: String, newUri: String) { + try { + val operations = ArrayList() + val uri = Uri.withAppendedPath(Contacts.CONTENT_URI, contactId) + ContentProviderOperation.newUpdate(uri).apply { + withValue(Contacts.CUSTOM_RINGTONE, newUri) + operations.add(build()) + } + + context.contentResolver.applyBatch(AUTHORITY, operations) + } catch (e: Exception) { + context.showErrorToast(e) + } + } + fun deleteContact(originalContact: Contact, deleteClones: Boolean = false, callback: (success: Boolean) -> Unit) { ensureBackgroundThread { if (deleteClones) { @@ -1463,7 +1497,7 @@ class ContactsHelper(val context: Context) { fun getDuplicatesOfContact(contact: Contact, addOriginal: Boolean, callback: (ArrayList) -> Unit) { ensureBackgroundThread { - getContacts(true) { contacts -> + getContacts(true, true) { contacts -> val duplicates = contacts.filter { it.id != contact.id && it.getHashToCompare() == contact.getHashToCompare() }.toMutableList() as ArrayList if (addOriginal) { duplicates.add(contact) diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/LocalContactsHelper.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/LocalContactsHelper.kt index cb415e7a..b3fbeb61 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/LocalContactsHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/LocalContactsHelper.kt @@ -6,7 +6,6 @@ import android.graphics.BitmapFactory import android.net.Uri import android.provider.ContactsContract.CommonDataKinds.Event import android.provider.MediaStore -import com.simplemobiletools.commons.extensions.getChoppedList import com.simplemobiletools.commons.models.SimpleContact import com.simplemobiletools.contacts.pro.extensions.contactsDB import com.simplemobiletools.contacts.pro.extensions.getByteArray @@ -56,7 +55,7 @@ class LocalContactsHelper(val context: Context) { } fun deleteContactIds(ids: MutableList) { - ids.getChoppedList().forEach { + ids.chunked(30).forEach { context.contactsDB.deleteContactIds(it) } } @@ -68,6 +67,10 @@ class LocalContactsHelper(val context: Context) { } } + fun updateRingtone(id: Int, ringtone: String) { + context.contactsDB.updateRingtone(ringtone, id) + } + private fun getPhotoByteArray(uri: String): ByteArray { if (uri.isEmpty()) { return ByteArray(0) @@ -83,7 +86,7 @@ class LocalContactsHelper(val context: Context) { return scaledSizePhotoData } - fun convertLocalContactToContact(localContact: LocalContact?, storedGroups: ArrayList): Contact? { + private fun convertLocalContactToContact(localContact: LocalContact?, storedGroups: ArrayList): Contact? { if (localContact == null) { return null } @@ -121,6 +124,7 @@ class LocalContactsHelper(val context: Context) { organization = Organization(localContact.company, localContact.jobPosition) websites = localContact.websites IMs = localContact.IMs + ringtone = localContact.ringtone } } @@ -151,6 +155,7 @@ class LocalContactsHelper(val context: Context) { jobPosition = contact.organization.jobPosition websites = contact.websites IMs = contact.IMs + ringtone = contact.ringtone } } diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/VcfImporter.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/VcfImporter.kt index db2ce7a4..f7b7bab6 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/VcfImporter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/helpers/VcfImporter.kt @@ -115,6 +115,7 @@ class VcfImporter(val activity: SimpleActivity) { val photoData = ezContact.photos.firstOrNull()?.data val photo = null val thumbnailUri = savePhoto(photoData) + val ringtone = null val IMs = ArrayList() ezContact.impps.forEach { @@ -138,11 +139,16 @@ class VcfImporter(val activity: SimpleActivity) { } val contact = Contact(0, prefix, firstName, middleName, surname, suffix, nickname, photoUri, phoneNumbers, emails, addresses, events, - targetContactSource, starred, contactId, thumbnailUri, photo, notes, groups, organization, websites, IMs) + targetContactSource, starred, contactId, thumbnailUri, photo, notes, groups, organization, websites, IMs, DEFAULT_MIMETYPE, ringtone) // if there is no N and ORG fields at the given contact, only FN, treat it as an organization if (contact.getNameToDisplay().isEmpty() && contact.organization.isEmpty() && ezContact.formattedName?.value?.isNotEmpty() == true) { contact.organization.company = ezContact.formattedName.value + contact.mimetype = CommonDataKinds.Organization.CONTENT_ITEM_TYPE + } + + if (contact.isABusinessContact()) { + contact.mimetype = CommonDataKinds.Organization.CONTENT_ITEM_TYPE } if (ContactsHelper(activity).insertContact(contact)) { diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/interfaces/ContactsDao.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/interfaces/ContactsDao.kt index e419e78b..b4a7bda9 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/interfaces/ContactsDao.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/interfaces/ContactsDao.kt @@ -23,6 +23,9 @@ interface ContactsDao { @Query("UPDATE contacts SET starred = :isStarred WHERE id = :id") fun updateStarred(isStarred: Int, id: Int) + @Query("UPDATE contacts SET ringtone = :ringtone WHERE id = :id") + fun updateRingtone(ringtone: String, id: Int) + @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertOrUpdate(contact: LocalContact): Long diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/models/Contact.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/models/Contact.kt index 83e0ff17..2a20f174 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/models/Contact.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/models/Contact.kt @@ -13,8 +13,9 @@ import com.simplemobiletools.contacts.pro.helpers.SMT_PRIVATE data class Contact(var id: Int, var prefix: String, var firstName: String, var middleName: String, var surname: String, var suffix: String, var nickname: String, var photoUri: String, var phoneNumbers: ArrayList, var emails: ArrayList, var addresses: ArrayList
, var events: ArrayList, var source: String, var starred: Int, var contactId: Int, var thumbnailUri: String, var photo: Bitmap?, var notes: String, - var groups: ArrayList, var organization: Organization, var websites: ArrayList, var IMs: ArrayList) : - Comparable { + var groups: ArrayList, var organization: Organization, var websites: ArrayList, var IMs: ArrayList, var mimetype: String, + var ringtone: String?) : + Comparable { companion object { var sorting = 0 var startWithSurname = false @@ -71,7 +72,7 @@ data class Contact(var id: Int, var prefix: String, var firstName: String, var m } else if (firstString.isNotEmpty() && secondString.isEmpty()) { -1 } else { - if (firstString.toLowerCase() == secondString.toLowerCase()) { + if (firstString.equals(secondString, ignoreCase = true)) { getNameToDisplay().compareTo(other.getNameToDisplay(), true) } else { firstString.compareTo(secondString, true) @@ -112,7 +113,7 @@ data class Contact(var id: Int, var prefix: String, var firstName: String, var m fun getStringToCompare(): String { return copy(id = 0, prefix = "", firstName = getNameToDisplay().toLowerCase(), middleName = "", surname = "", suffix = "", nickname = "", photoUri = "", phoneNumbers = ArrayList(), emails = ArrayList(), events = ArrayList(), source = "", addresses = ArrayList(), starred = 0, contactId = 0, - thumbnailUri = "", notes = "", groups = ArrayList(), websites = ArrayList(), organization = Organization("", ""), IMs = ArrayList()).toString() + thumbnailUri = "", notes = "", groups = ArrayList(), websites = ArrayList(), organization = Organization("", ""), IMs = ArrayList(), ringtone = "").toString() } fun getHashToCompare() = getStringToCompare().hashCode() @@ -130,9 +131,9 @@ data class Contact(var id: Int, var prefix: String, var firstName: String, var m val normalizedText = if (convertLetters) text.normalizePhoneNumber() else text phoneNumbers.any { PhoneNumberUtils.compare(it.normalizedNumber, normalizedText) || - it.value.contains(text) || - it.normalizedNumber?.contains(normalizedText) == true || - it.value.normalizePhoneNumber().contains(normalizedText) + it.value.contains(text) || + it.normalizedNumber?.contains(normalizedText) == true || + it.value.normalizePhoneNumber().contains(normalizedText) } } else { false diff --git a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/models/LocalContact.kt b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/models/LocalContact.kt index 53f96fcd..b34f9b86 100644 --- a/app/src/main/kotlin/com/simplemobiletools/contacts/pro/models/LocalContact.kt +++ b/app/src/main/kotlin/com/simplemobiletools/contacts/pro/models/LocalContact.kt @@ -7,26 +7,27 @@ import androidx.room.PrimaryKey @Entity(tableName = "contacts", indices = [(Index(value = ["id"], unique = true))]) data class LocalContact( - @PrimaryKey(autoGenerate = true) var id: Int?, - @ColumnInfo(name = "prefix") var prefix: String, - @ColumnInfo(name = "first_name") var firstName: String, - @ColumnInfo(name = "middle_name") var middleName: String, - @ColumnInfo(name = "surname") var surname: String, - @ColumnInfo(name = "suffix") var suffix: String, - @ColumnInfo(name = "nickname") var nickname: String, - @ColumnInfo(name = "photo", typeAffinity = ColumnInfo.BLOB) var photo: ByteArray?, - @ColumnInfo(name = "photo_uri") var photoUri: String, - @ColumnInfo(name = "phone_numbers") var phoneNumbers: ArrayList, - @ColumnInfo(name = "emails") var emails: ArrayList, - @ColumnInfo(name = "events") var events: ArrayList, - @ColumnInfo(name = "starred") var starred: Int, - @ColumnInfo(name = "addresses") var addresses: ArrayList
, - @ColumnInfo(name = "notes") var notes: String, - @ColumnInfo(name = "groups") var groups: ArrayList, - @ColumnInfo(name = "company") var company: String, - @ColumnInfo(name = "job_position") var jobPosition: String, - @ColumnInfo(name = "websites") var websites: ArrayList, - @ColumnInfo(name = "ims") var IMs: ArrayList) { + @PrimaryKey(autoGenerate = true) var id: Int?, + @ColumnInfo(name = "prefix") var prefix: String, + @ColumnInfo(name = "first_name") var firstName: String, + @ColumnInfo(name = "middle_name") var middleName: String, + @ColumnInfo(name = "surname") var surname: String, + @ColumnInfo(name = "suffix") var suffix: String, + @ColumnInfo(name = "nickname") var nickname: String, + @ColumnInfo(name = "photo", typeAffinity = ColumnInfo.BLOB) var photo: ByteArray?, + @ColumnInfo(name = "photo_uri") var photoUri: String, + @ColumnInfo(name = "phone_numbers") var phoneNumbers: ArrayList, + @ColumnInfo(name = "emails") var emails: ArrayList, + @ColumnInfo(name = "events") var events: ArrayList, + @ColumnInfo(name = "starred") var starred: Int, + @ColumnInfo(name = "addresses") var addresses: ArrayList
, + @ColumnInfo(name = "notes") var notes: String, + @ColumnInfo(name = "groups") var groups: ArrayList, + @ColumnInfo(name = "company") var company: String, + @ColumnInfo(name = "job_position") var jobPosition: String, + @ColumnInfo(name = "websites") var websites: ArrayList, + @ColumnInfo(name = "ims") var IMs: ArrayList, + @ColumnInfo(name = "ringtone") var ringtone: String?) { override fun equals(other: Any?) = id == (other as? LocalContact?)?.id diff --git a/app/src/main/res/layout/activity_edit_contact.xml b/app/src/main/res/layout/activity_edit_contact.xml index eabe713f..e67be2cd 100644 --- a/app/src/main/res/layout/activity_edit_contact.xml +++ b/app/src/main/res/layout/activity_edit_contact.xml @@ -384,6 +384,31 @@ android:textCursorDrawable="@null" android:textSize="@dimen/bigger_text_size" /> + + + + + + + + + + + + + - - - - - - - - diff --git a/app/src/main/res/layout/activity_view_contact.xml b/app/src/main/res/layout/activity_view_contact.xml index b7a3e0fd..f6ca310f 100644 --- a/app/src/main/res/layout/activity_view_contact.xml +++ b/app/src/main/res/layout/activity_view_contact.xml @@ -104,7 +104,7 @@ android:src="@drawable/ic_person_vector" /> - - - - - - - - - - + android:textSize="@dimen/bigger_text_size" + android:tooltipText="John Doe" /> + + @@ -413,11 +341,26 @@ android:visibility="gone" /> + + - @@ -11,8 +10,8 @@ android:layout_height="wrap_content" android:orientation="vertical" android:paddingStart="@dimen/activity_margin" - android:paddingEnd="@dimen/activity_margin" - android:paddingTop="@dimen/activity_margin"> + android:paddingTop="@dimen/activity_margin" + android:paddingEnd="@dimen/activity_margin"> + android:paddingBottom="@dimen/medium_margin" + android:text="@string/first_name" /> + android:paddingBottom="@dimen/medium_margin" + android:text="@string/middle_name" /> + android:paddingBottom="@dimen/medium_margin" + android:text="@string/surname" /> + android:paddingBottom="@dimen/medium_margin" + android:text="@string/full_name" /> - + + android:paddingBottom="@dimen/medium_margin" + android:text="@string/ascending" /> + android:paddingBottom="@dimen/medium_margin" + android:text="@string/descending" /> diff --git a/app/src/main/res/layout/dialog_manage_visible_fields.xml b/app/src/main/res/layout/dialog_manage_visible_fields.xml index acf214b2..4998e348 100644 --- a/app/src/main/res/layout/dialog_manage_visible_fields.xml +++ b/app/src/main/res/layout/dialog_manage_visible_fields.xml @@ -1,6 +1,5 @@ - @@ -11,136 +10,144 @@ android:layout_height="wrap_content" android:orientation="vertical" android:paddingStart="@dimen/activity_margin" - android:paddingEnd="@dimen/activity_margin" - android:paddingTop="@dimen/activity_margin"> + android:paddingTop="@dimen/activity_margin" + android:paddingEnd="@dimen/activity_margin"> + android:paddingBottom="@dimen/activity_margin" + android:text="@string/prefix" /> + android:paddingBottom="@dimen/activity_margin" + android:text="@string/first_name" /> + android:paddingBottom="@dimen/activity_margin" + android:text="@string/middle_name" /> + android:paddingBottom="@dimen/activity_margin" + android:text="@string/surname" /> + android:paddingBottom="@dimen/activity_margin" + android:text="@string/suffix" /> + android:paddingBottom="@dimen/activity_margin" + android:text="@string/nickname" /> + android:paddingBottom="@dimen/activity_margin" + android:text="@string/phone_numbers" /> + android:paddingBottom="@dimen/activity_margin" + android:text="@string/emails" /> + android:paddingBottom="@dimen/activity_margin" + android:text="@string/addresses" /> + android:paddingBottom="@dimen/activity_margin" + android:text="@string/instant_messaging" /> + android:paddingBottom="@dimen/activity_margin" + android:text="@string/events" /> + android:paddingBottom="@dimen/activity_margin" + android:text="@string/notes" /> + + + android:paddingBottom="@dimen/activity_margin" + android:text="@string/organization" /> + android:paddingBottom="@dimen/activity_margin" + android:text="@string/websites" /> + android:paddingBottom="@dimen/activity_margin" + android:text="@string/groups" /> + android:paddingBottom="@dimen/activity_margin" + android:text="@string/contact_source" /> diff --git a/app/src/main/res/layout/item_view_contact_source.xml b/app/src/main/res/layout/item_view_contact_source.xml index f32cc87b..53eed9be 100644 --- a/app/src/main/res/layout/item_view_contact_source.xml +++ b/app/src/main/res/layout/item_view_contact_source.xml @@ -32,6 +32,7 @@ android:layout_marginEnd="@dimen/normal_margin" android:background="?attr/selectableItemBackgroundBorderless" android:padding="@dimen/small_margin" + android:visibility="gone" tools:src="@drawable/ic_phone_vector" /> diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 86048aec..e79a2bd3 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -105,6 +105,7 @@ مجموعات مصدر الاتصال المراسلة الفورية (IM) + Ringtone The contact will be removed from all contact sources. diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index 329b2c51..f37ceb11 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -105,6 +105,7 @@ Qruplar Kontakt kökü Instant messaging (IM) + Ringtone The contact will be removed from all contact sources. diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 88c7b64c..a141450b 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -105,6 +105,7 @@ Skupiny Zdroje kontaktů Rychlé zprávy (IM) + Ringtone Kontakt bude vymazán ze všech zdrojů kontaktů. diff --git a/app/src/main/res/values-cy/strings.xml b/app/src/main/res/values-cy/strings.xml index 7c5cce09..402964ee 100644 --- a/app/src/main/res/values-cy/strings.xml +++ b/app/src/main/res/values-cy/strings.xml @@ -105,6 +105,7 @@ Grwpiau Ffynhonnell gyswllt Negesu ar unwaith (IM) + Ringtone The contact will be removed from all contact sources. diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 19785552..2c307eb6 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -105,6 +105,7 @@ Groupper Kontaktkilde Instant messaging (IM) + Ringtone The contact will be removed from all contact sources. diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index e7d10151..9dcaf9f6 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -105,6 +105,7 @@ Gruppen Kontaktquelle Instant messaging (IM) + Ringtone Der Kontakt wird von allen Kontaktquellen entfernt. @@ -124,38 +125,38 @@ Verwalten Sie Ihre Kontakte professionell, schnell und sicher mit dieser App - A lightweight app for managing your contacts loved by millions of people. The contacts can be stored on your device only, but also synchronized via Google, or other accounts. + Eine simple App um deine Kontakte zu verwalten, die von Millionen Menschen geliebt wird. Die Kontakte können entweder lokal auf dem Gerät gespeichert oder via Google und anderen Accounts synchronisiert werden. - You can use it for managing user emails and events too. It has the ability to sort/filter by multiple parameters, optionally display surname as the first name. + Sie können die App auch nutzen, um Emails und Events der Kontakte zu speichern. Die App hat die Fähigkeit, mit verschiedenen Parametern zu suchen und zu sortieren und kann wahlweise den Vornamen an erster Stelle anzeigen. - You can display your favorite contacts or groups on a separate list. Groups can be used for sending out batch emails or SMS, to save you some time, you can rename them easily. + Ihre Lieblingskontakte oder -gruppen können in einer seperaten Liste angezeigt werden. Gruppen können dafür genutzt werden, um einen Stapel an Emails oder SMS zu versenden, was Ihnen Zeit erspart. Zudem können Sie diese einfach umbennen. - It contains handy buttons for calling, or texting your contacts. All visible fields can be customized as you wish, you can easily hide the unused ones. The search function will search the given string at every visible contact field, to make you find your desired contact easily. + Es sind nützliche Buttons verfügbar, um Ihre Kontakte anzurufen oder ihnen zu schreiben. Alle angezeigten Felder können nach Ihren Wünschen angepasst werden, alle ungenutzen Felder können ausgeblendet werden. Die Suchfunktion wird den angegebenen String in jedem sichtbaren Kontaktfeld suchen, sodass Sie Ihren gewüschten Kontakt einfach finden können. - There is a lightweight dialpad at your service too, with smart contact suggestions. + Es gibt ein einfaches Wählfeld, mit intelligenten Kontaktvervollständigungen. - It supports exporting/importing contacts in vCard format to .vcf files, for easy migrations or backing up your data. + Kontakte können im vCard-Format als .vcf Dateien exportiert und importiert werden, um einfach zu migrieren oder ein Backup zu erstellen. - With this modern and stable contacts manager you can protect your contacts by not sharing them with other apps, so you can keep your contacts private. + Mit diesem modernen und stabilen Kontakte Manager können Sie Ihre Kontakte schützen, indem diese nicht mit andern Apps geteilt werden, sodass Ihre Kontakte privat bleiben. - Like the contact source, you can also easily change the contact name, email, phone number, address, organization, groups and many other customizable fields. You can use it for storing contact events too, like birthdays, anniversaries, or any other custom ones. + Genauso wie die Kontaktquelle, können Sie ebnso einfach den Kontaktnamen, dessen Email, Telefonnummer, Addresse, Organisation, Gruppe und viele andere Felder anpassen. Sie können auch Events wie Geburtstage, Feiern oder benutzerdefinierte Events angeben. - This simple contact editor has many handy settings like showing phone numbers on the main screen, toggle contact thumbnail visibility, showing only contacts with phone numbers, showing a call confirmation dialog before initiating a call. It comes with a quick dialer that also makes use of letters. + Dieser einfache Kontakte-Editor hat viele nützliche Einstellungen - zum Beispiel kann es die Telefonnummer im Hauptbildschirm anzeigen, das Kontake-Vorschaubild ein- und ausblenden, nur Kontakte mit Telefonnummern anzeigen und eine Anrufsbestätigung anzeigen, bevor der Anruf gestartet wird. Das schnelle Wahlfeld unterstützt auch Buchstaben. - To further improve the user experience, you can customize what happens at clicking on a contact. You can either initiate a call, go to the View Details screen, or edit the selected contact. + Um die Nutzererfahrung noch mehr zu verbessern, können Sie anpassen, was passiert, wenn Sie auf den Kontakt drücken. Entweder kann ein Anruf gestartet, der Kontakt angepasst (editiert) oder Details angeigt werden. - You can easily block phone numbers to avoid unwanted incoming calls. + Um ungewollte Anrufe zu vermeiden, können Anrufe einfach blockiert werden. + + Um zu verhindern, dass potentiell ungewollte Kontakte angezeigt werden, führt die App Duplikate automatisch zusammen. - To avoid showing potentially unwanted contacts, it has a powerful built in duplicate contact merger. - - It comes with material design and dark theme by default, provides great user experience for easy usage. The lack of internet access gives you more privacy, security and stability than other apps. + Die App beinhaltet standardmäßig material design und Dunkelmodus, um großartige Nutzererfahrungen und einfache Nutzung zu ermöglichen. Da die App keine Internetverbindung besitzt, bietet die App Ihnen mehr Datenschutz, Sicherheit und Stabilität als andere Apps. Enthält keine Werbung oder unnötige Berechtigungen. Vollständig quelloffen. Die Farben sind anpassbar. - Check out the full suite of Simple Tools here: + Entdecke die gesamte Serie an schlichten Apps hier: https://www.simplemobiletools.com - Standalone website of Simple Contacts Pro: + Standalone Webseite von Simple Contacts Pro: https://www.simplemobiletools.com/contacts Facebook: diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 5e770876..a442d1ed 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -87,11 +87,11 @@ Εξαγωγή επαφών σε .vcf αρχείο Προορισμός πηγής επαφής Συμπερίληψη πηγών επαφών - Όνομα αρχείου (χωρίς .vcf) + Όνομα αρχείου (εκτός .vcf) Πληκτρολόγιο - Προσθήκη επαφής σε αριθμό + Προσθήκη αριθμού σε επαφή Πρόθεμα @@ -105,6 +105,7 @@ Ομάδες Προέλευση επαφής Αμεσο μήνυμα (IM) + Ήχος κλήσης Η επαφή θα καταργηθεί από όλες τις πηγές επαφών. diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index be2e1d2b..867df01c 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -53,7 +53,7 @@ Contactos Mostrar un cuadro de confirmación antes de iniciar una llamada Solo mostrar contactos con números telefónicos - Show private contacts to Simple Dialer, Simple SMS Messenger and Simple Calendar Pro + Mostrar contactos privados a Marcador Simple, Mensajería SMS Simple y Calendario Simple Pro Casa @@ -105,6 +105,7 @@ Grupos Orígenes de contacto Mensaje instantáneo (IM) + Ringtone El contacto será eliminado de todos los orígenes de contactos. @@ -115,7 +116,7 @@ - Quiero cambiar qué acmpos son visibles en loos contactos. ¿Puedo hacerlo? + Quiero cambiar qué campos son visibles en los contactos. ¿Puedo hacerlo? Sí, todo lo que tienes que hacer es ir a Ajustes -> Administrar campos del contacto mostrados. Ahí puedes seleccionar que campos deberían ser visibles. Algunos de ellos están desactivados por defecto, así que podrías encontrar algunos nuevos ahí. @@ -124,35 +125,35 @@ La mejor app de gestión de contactos con soporte de la función de grupos - A lightweight app for managing your contacts loved by millions of people. The contacts can be stored on your device only, but also synchronized via Google, or other accounts. + Una ligera aplicación para administrar tus contactos amada por millones. Los contactos pueden ser almacenados únicamente en tu dispositivo, per otambién sincronizarlos vía Google u otras cuentas. - You can use it for managing user emails and events too. It has the ability to sort/filter by multiple parameters, optionally display surname as the first name. + Puedes usarla para administrar correos electrónicos de usuarios y eventos también. Tiene la habilidad de ordenar/filtrar por múltiples parámetros y, opcionalmente, mostrar el apellido como el nombre. - You can display your favorite contacts or groups on a separate list. Groups can be used for sending out batch emails or SMS, to save you some time, you can rename them easily. + Puedes mostrar tus contáctos favoritos o grupos en listas separadas. Los grupos pueden ser usados para enviar correos electrónicos o SMS por lotes, para ahorrate algo de tiempo, y puedes renombrarlos fácilmente. - It contains handy buttons for calling, or texting your contacts. All visible fields can be customized as you wish, you can easily hide the unused ones. The search function will search the given string at every visible contact field, to make you find your desired contact easily. + Contiene prácticos botones para llamar o mensajear a tus contactos. Todos los campos visibles pueden ser personalizados a tu gusto, y fácilmente puedes ocultar los que no uses. La función de búsqueda buscará el texto dado en cada campo de contacto visible, para hacer más fácil encontrar el contacto deseado. - There is a lightweight dialpad at your service too, with smart contact suggestions. + También tiene un ligero teclado de marcado a tu servicio, con sugerencias de contactos inteligentes. - It supports exporting/importing contacts in vCard format to .vcf files, for easy migrations or backing up your data. + Soporta exportar/importar contactos en formato vCard a archivos .vcf, para fácil migración o respaldo de tu información. - With this modern and stable contacts manager you can protect your contacts by not sharing them with other apps, so you can keep your contacts private. + Con este moderno y estable gestor de contactos puedes proteger tus contactos no compartiéndolos con otras aplicaciones, así puedes mantener tus contactos privados. - Like the contact source, you can also easily change the contact name, email, phone number, address, organization, groups and many other customizable fields. You can use it for storing contact events too, like birthdays, anniversaries, or any other custom ones. + Como el origen del contacto, fácilmente también puedes cambiar el nombre del contacto, correo electrónico, número de teléfono, dirección, organización, grupos y muchos otros campos personalizables. Puedes usarlo para almacenar eventos de contactos también, como cumpleaños, aniversarios, o cualqueir otro personalizado. - This simple contact editor has many handy settings like showing phone numbers on the main screen, toggle contact thumbnail visibility, showing only contacts with phone numbers, showing a call confirmation dialog before initiating a call. It comes with a quick dialer that also makes use of letters. + Este simple editor de contactos tiene varios ajustes prácticos como mostrar números de teléfono en la pantalla principal, alternar entre mostrar la miniatura del contacto, mostrar sólamente contactos con números de teléfono, mostrar un diálogo de confirmar llamada antes de iniciarla. Incluye un marcador rápido que también hace uso de las letras. - To further improve the user experience, you can customize what happens at clicking on a contact. You can either initiate a call, go to the View Details screen, or edit the selected contact. + Para mejorar la experiencia de usuario aún más, puedes personalizar lo que pasa al tocar un contacto. Puedes iniciar una llamada, ir a la Vista de detalles o editar el contacto seleccionado. - You can easily block phone numbers to avoid unwanted incoming calls. + Puedes bloquear números de teléfono fácilmente para evitar llamadas indeseadas. - To avoid showing potentially unwanted contacts, it has a powerful built in duplicate contact merger. + Para evitar mosrar contactos potencialmente indeseados, tiene un poderoso fusionador de contactos duplicados. - It comes with material design and dark theme by default, provides great user experience for easy usage. The lack of internet access gives you more privacy, security and stability than other apps. + Incluye diseño material y tema obscuro por defecto, provee una gran experiencia de usuario para uso sencillo. La falta del acceso a internet te da más privacidad, seguridad y estabilidad que otras aplicaciones. - No contiene anuncios o permisos innecesarios. Es complétamente de código abierto, provee colores personalziables. + No contiene anuncios o permisos innecesarios. Es completamente de código abierto, provee colores personalizables. - Check out the full suite of Simple Tools here: + Mira la suite completa de herramientas Simples aquí: https://www.simplemobiletools.com Standalone website of Simple Contacts Pro: diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 35204c41..3489b55a 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -105,6 +105,7 @@ Taldeak Kontaktu jatorria Instant messaging (IM) + Ringtone The contact will be removed from all contact sources. diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 5ffa76e3..05df6c49 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -2,17 +2,17 @@ Simple Contacts Yhteystiedot Osoite - Sijoitetaan - Päivitetään - Puhelimen muisti piilotettu + Sijoitetaan... + Päivitetään... + Puhelimen muisti (piilotettu muilta sovelluksilta) Yritys Ammatti - Internet-sivu + Verkkosivu Lähetä tekstiviesti yhteystiedoille Lähetä sähköposti yhteystiedoille Lähetä tekstiviesti ryhmälle Lähetä sähköposti ryhmälle - Soita + Soita %s Luo uusi yhteystieto Lisää olemassa olevaan yhteystietoon @@ -30,8 +30,8 @@ Luo uusi ryhmä Poista ryhmästä Ryhmä on tyhjä - Lisää yhteystietoja - Ryhmää ei luotu + Lisää yhteystietoihin + Laitteessa ei ole yhteistietoryhmiä Luo ryhmä Lisää ryhmään Luo ryhmä tilille @@ -42,16 +42,16 @@ Poista kuva - Näytä puhelinnumerot + Näytä puhelinnumerot päänäytöllä Näytä yhteystietojen kuvakkeet - Näytä soittimen painike - Yhteystietoa painaessa… + Näytä numeronvalitsin-painike päänäytöllä + Yhteystietoa painaessa Soita Näytä yhteystieto Valitse, mitkä yhteystietojen kentät näytetään Valitse sovelluksen välilehdet Yhteystiedot - Näytä puhelun vahvistusruutu + Näytä soiton vahvistusruutu ennen soittoa Näytä ainoastaan numerolliset yhteystiedot Näytä yksityiset yhteystiedot sovelluksissa Simple Dialer, Simple SMS Messenger ja Simple Calendar Pro @@ -62,9 +62,9 @@ Matkapuhelin - Päänumero - Työfaxi - Kotifaxi + Oletus + Faksi (työ) + Faksi (koti) Hakulaite Puhelinnumeroa ei löytynyt @@ -73,7 +73,7 @@ Vuosipäivä - Ei suosikkeja + Näyttää siltä, että et ole vielä lisännyt suosikkiyhteystietoja. Etsi yhteystietoja @@ -83,46 +83,47 @@ Tuo yhteystietoja Vie yhteystietoja - Tuo .vcf yhteystietoja - Vie .vcf yhteystietoja - Kohdenna yhteystiedon lähde + Tuo yhteystietoja .vcf-tiedostosta + Vie yhteystietoja .vcf-tiedostoon + Yhteystietojen lähde Sisällytä yhteystiedon lähteet - Tiedostonimi ilman .vcf-päätettä + Tiedostonimi (ilman .vcf-päätettä) - Näppäimistö + Numeronvalitsin Lisää numero yhteystietoihin - Alku - Pääte - Puhelinnumero + Etuliite + Jälkiliite + Puhelinnumerot Sähköpostit Osoitteet - Tapahtumat - Organisaatio - Internetsivut + Tapahtumat (syntymäpäivät, vuosipäivät) + Yritys + Verkkosivut Ryhmät Yhteystiedon lähde Pikaviestin + Soittoääni Yhteystieto poistetaan kaikista lähteistä. - %d ryhmä + %d ryhmän %d ryhmää - Voinko valita, mitkä täytettävät kentät näytetään yhteystiedon ominaisuuksissa? - Kyllä. Mene asetuksiin -> Valitse täytettävät kentät. Voit valita, mitkä kentät näytetään. Osa kentistä on oletuksena piilotettuna, , joten saatat löytää joitain uusia. + Voinko valita, mitkä täytettävät kentät näytetään yhteystiedon ominaisuuksissa? + Kyllä. Mene asetuksiin -> Valitse täytettävät kentät. Voit valita, mitkä kentät näytetään. Osa kentistä on oletuksena piilotettuna, joten saatat löytää joitain uusia. - Simple Contacts Pro - Manage your contacts easily + Simple Contacts Pro - Yhteystietojen hallinta - Easy and quick contact management with no ads, handles groups and favorites too. + Helppo ja nopea yhteystietojen hallinta ilman mainoksia. Hallitsee myös ryhmät ja suosikit. A lightweight app for managing your contacts loved by millions of people. The contacts can be stored on your device only, but also synchronized via Google, or other accounts. diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 081fe49f..c09bbb23 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -103,6 +103,7 @@ Groupe Source du contact Messagerie instantanée (MI) + Ringtone Le contact sera supprimé de toutes les sources de contacts. diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 472de9c3..4f813d53 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -105,6 +105,7 @@ Grupe Izvori kontakata Brzo slanje poruka (IM) + Ringtone The contact will be removed from all contact sources. diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 208eb685..ad093db1 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -105,6 +105,7 @@ Csoportok Névjegy account Instant messaging (IM) + Ringtone The contact will be removed from all contact sources. diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index b83035cb..bebecc6a 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -105,6 +105,7 @@ Grup Sumber kontak Pesan singkat (IM) + Ringtone Kontak akan dihapus dari semua sumber kontak. diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index b83035cb..bebecc6a 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -105,6 +105,7 @@ Grup Sumber kontak Pesan singkat (IM) + Ringtone Kontak akan dihapus dari semua sumber kontak. diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 23518958..4f63a7a3 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -105,6 +105,7 @@ Gruppi Provenienza del contatto Messaggistica istantanea (IM) + Ringtone The contact will be removed from all contact sources. diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 19240a9b..894e501c 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -1,5 +1,5 @@ - Simple Contacts + Simpleコンタクト 連絡先 住所 挿入中… @@ -12,7 +12,7 @@ 連絡先にメールを送信 グループにSMSを送信 グループにメールを送信 - Call %s + %sに発信 新しい連絡先を作成 既存の連絡先に追加 @@ -53,7 +53,7 @@ 連絡先 発信する前に確認ダイアログを表示する 電話番号が登録された連絡先のみ表示する - Show private contacts to Simple Dialer, Simple SMS Messenger and Simple Calendar Pro + Simpleダイヤラー、Simpleショートメール、SimpleカレンダーProに個人の連絡先を表示 自宅 @@ -62,7 +62,7 @@ 携帯 - Main + メイン 職場FAX 自宅FAX ポケベル @@ -78,15 +78,15 @@ 連絡先を検索 お気に入りを検索 - Search groups + グループを検索 連絡先をインポート 連絡先をエクスポート .vcfファイルから連絡先をインポート 連絡先を.vcfファイルにエクスポート - Target contact source - Include contact sources + 対象となる連絡先のソース + 連絡先のソースを含める ファイル名 (.vcfを含めない) @@ -104,14 +104,15 @@ ウェブサイト グループ インポート元 - Instant messaging (IM) + インスタントメッセージ(IM) + Ringtone - The contact will be removed from all contact sources. + 全ての連絡先ソースから連絡先を消去します - %d group - %d groups + %d件のグループ + %d件のグループ diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index ddbe3720..4f73d699 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -105,6 +105,7 @@ Groups Contact source Instant messaging (IM) + Ringtone The contact will be removed from all contact sources. diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 082f2ee6..e005659b 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -105,6 +105,7 @@ Grupės Kontakto šaltinis Instant messaging (IM) + Ringtone The contact will be removed from all contact sources. diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml index b4a7910a..d8b9fb1d 100644 --- a/app/src/main/res/values-ml/strings.xml +++ b/app/src/main/res/values-ml/strings.xml @@ -105,6 +105,7 @@ ഗ്രൂപ്പുകൾ കോൺ‌ടാക്റ്റ് ഉറവിടം തത്സമയ സന്ദേശം അയക്കൽ + Ringtone എല്ലാ കോൺ‌ടാക്റ്റ് ഉറവിടങ്ങളിൽ‌ നിന്നും ഈ കോൺ‌ടാക്റ്റ് നീക്കംചെയ്യും. diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 5015502f..3e1cf44c 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -65,7 +65,7 @@ Standaard Fax Werk Fax Thuis - Pager + Pieper Geen telefoonnummers gevonden @@ -105,6 +105,7 @@ Groepen Account Instant messaging (IM) + Ringtone De contactpersoon zal worden verwijderd uit alle accounts. diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index fc65632b..08882179 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -105,6 +105,7 @@ Grupy Miejsce przechowywania kontaktu Komunikator + Ringtone The contact will be removed from all contact sources. diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index e0385213..a77eb898 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -105,6 +105,7 @@ Grupos Origem do contato Mensageiro instantâneo (MI) + Ringtone O contato será removido de todas removido de todas as fontes de contato. diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index a309c527..fe1bbc63 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -105,6 +105,7 @@ Grupos Origem do contacto Mensagem instantânea (IM) + Ringtone O contacto será apagado de todas as origens. diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index d9460fd7..730a71c1 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -105,6 +105,7 @@ Группы Источник контакта Мессенджеры + Ringtone Контакт будет удалён из всех источников контактов. diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 7768b1ab..98a31b04 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -105,6 +105,7 @@ Skupiny Zdroje kontaktov Rýchle správy (IM) + Zvonenie Kontakt bude vymazaný zo všetkých zdrojov kontaktov. diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index e95df35f..858798db 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -105,6 +105,7 @@ Grupper Kontaktkälla Snabbmeddelanden (IM) + Ringtone Kontakten kommer att tas bort från alla kontaktkällor. diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 86616fc0..5d1b453b 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -105,6 +105,7 @@ Gruplar Kişi kaynağı Anlık mesajlaşma (IM) + Zil sesi Kişi tüm kişi kaynaklarından kaldırılacak. diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 62f701c0..a31d5ab6 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -105,6 +105,7 @@ Групи Походження контакту Мессенджери + Ringtone The contact will be removed from all contact sources. diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index c2f885da..995fbd6a 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -105,6 +105,7 @@ 群组 联系人来源 即时通讯 (IM) + Ringtone 该联系人将会被从所有联系人来源移除。 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index e739f373..08cf9aa9 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -105,6 +105,7 @@ 群組 聯絡人來源 即時通訊 (IM) + Ringtone 這聯絡人將從全部通訊錄來源移除。 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 209bf69c..9f72e262 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -105,6 +105,7 @@ Groups Contact source Instant messaging (IM) + Ringtone The contact will be removed from all contact sources. diff --git a/build.gradle b/build.gradle index 9e841957..d4107b09 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.4.10' + ext.kotlin_version = '1.4.30' repositories { google() @@ -9,7 +9,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.0.2' + classpath 'com.android.tools.build:gradle:4.1.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong diff --git a/fastlane/metadata/android/en-US/changelogs/78.txt b/fastlane/metadata/android/en-US/changelogs/78.txt new file mode 100644 index 00000000..4beec155 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/78.txt @@ -0,0 +1 @@ + * Added some translation, stability and UX improvements diff --git a/fastlane/metadata/android/en-US/changelogs/79.txt b/fastlane/metadata/android/en-US/changelogs/79.txt new file mode 100644 index 00000000..1be5a1ae --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/79.txt @@ -0,0 +1,4 @@ + * Always fetch the same contacts, no matter what sorting is set + * Fix an organization updating related issue + * Merge names into 1 line at the View Details screen + * Improve Threema contact handling diff --git a/fastlane/metadata/android/en-US/changelogs/80.txt b/fastlane/metadata/android/en-US/changelogs/80.txt new file mode 100644 index 00000000..45d85bfc --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/80.txt @@ -0,0 +1,4 @@ + * Allow customizing the ringtone per contact (Ringtone has to be enabled as a customizable field in the app settings) + * Added a White theme with special handling + * Added some letter fastscroller related improvements + * Some performance, stability and translation related improvements diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_1.jpg b/fastlane/metadata/android/en-US/images/phoneScreenshots/app_1.jpg deleted file mode 100644 index eddad087..00000000 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_1.jpg and /dev/null differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_2.jpg b/fastlane/metadata/android/en-US/images/phoneScreenshots/app_2.jpg deleted file mode 100644 index e9602d8b..00000000 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_2.jpg and /dev/null differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_3.jpg b/fastlane/metadata/android/en-US/images/phoneScreenshots/app_3.jpg deleted file mode 100644 index a3a5fdc6..00000000 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_3.jpg and /dev/null differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_4.jpg b/fastlane/metadata/android/en-US/images/phoneScreenshots/app_4.jpg deleted file mode 100644 index 109fbcea..00000000 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/app_4.jpg and /dev/null differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/english/1.jpg b/fastlane/metadata/android/en-US/images/phoneScreenshots/english/1.jpg new file mode 100644 index 00000000..526832ef Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/english/1.jpg differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/english/2.jpg b/fastlane/metadata/android/en-US/images/phoneScreenshots/english/2.jpg new file mode 100644 index 00000000..5f3510a2 Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/english/2.jpg differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/english/3.jpg b/fastlane/metadata/android/en-US/images/phoneScreenshots/english/3.jpg new file mode 100644 index 00000000..64ef52f6 Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/english/3.jpg differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/english/4.jpg b/fastlane/metadata/android/en-US/images/phoneScreenshots/english/4.jpg new file mode 100644 index 00000000..c9e39b50 Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/english/4.jpg differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 272e8b44..dc129daa 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Jun 18 23:08:40 CEST 2020 +#Tue Nov 03 22:18:17 CET 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip