51
CHANGELOG.md
@ -1,6 +1,57 @@
|
||||
Changelog
|
||||
==========
|
||||
|
||||
Version 4.2.2 *(2018-08-13)*
|
||||
----------------------------
|
||||
|
||||
* Added an optional Nickname field
|
||||
* Improved searching and sorting UTF8 characters
|
||||
* Fixed updating Notes and Organization fields
|
||||
|
||||
Version 4.2.1 *(2018-08-05)*
|
||||
----------------------------
|
||||
|
||||
* Added some stability and light theme UX fixes
|
||||
|
||||
Version 4.2.0 *(2018-08-04)*
|
||||
----------------------------
|
||||
|
||||
* Added a Recent Calls tab
|
||||
* Allow customizing which tabs are visible
|
||||
* Added an optional call confirmation dialog
|
||||
* Fixed some glitches related to company contacts
|
||||
* Some other performance and stability improvements
|
||||
|
||||
Version 4.1.0 *(2018-07-16)*
|
||||
----------------------------
|
||||
|
||||
* Fixed a couple issues related to importing contacts from .vcf files
|
||||
* Couple other UX and stability improvements
|
||||
|
||||
Version 4.0.5 *(2018-07-05)*
|
||||
----------------------------
|
||||
|
||||
* Make duplicate contact filtering more agressive
|
||||
* Couple UX and stability improvements
|
||||
|
||||
Version 4.0.4 *(2018-06-19)*
|
||||
----------------------------
|
||||
|
||||
* Make "Try filtering out duplicate contacts" more agressive
|
||||
* Ignore hidden contact fields, do not wipe them
|
||||
* Prefer the contacts Mobile number at sending batch SMS
|
||||
* Added a couple stability improvements
|
||||
|
||||
Version 4.0.3 *(2018-05-13)*
|
||||
----------------------------
|
||||
|
||||
* Show a couple additional contact sources
|
||||
|
||||
Version 4.0.2 *(2018-05-12)*
|
||||
----------------------------
|
||||
|
||||
* Make sure all relevant contact sources are visible
|
||||
|
||||
Version 4.0.1 *(2018-05-09)*
|
||||
----------------------------
|
||||
|
||||
|
@ -3,15 +3,15 @@ apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion "27.0.3"
|
||||
compileSdkVersion 28
|
||||
buildToolsVersion "28.0.2"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.simplemobiletools.contacts"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 27
|
||||
versionCode 21
|
||||
versionName "4.0.1"
|
||||
targetSdkVersion 28
|
||||
versionCode 29
|
||||
versionName "4.2.2"
|
||||
setProperty("archivesBaseName", "contacts")
|
||||
}
|
||||
|
||||
@ -45,9 +45,11 @@ ext {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.simplemobiletools:commons:4.0.0'
|
||||
implementation 'com.simplemobiletools:commons:4.6.15'
|
||||
implementation 'joda-time:joda-time:2.9.9'
|
||||
implementation 'com.facebook.stetho:stetho:1.5.0'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
||||
compile 'com.googlecode.ez-vcard:ez-vcard:0.10.4'
|
||||
|
||||
debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanaryVersion"
|
||||
releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$leakCanaryVersion"
|
||||
|
5
app/proguard-rules.pro
vendored
@ -0,0 +1,5 @@
|
||||
# ez-vcard
|
||||
-keep,includedescriptorclasses class ezvcard.property.** { *; }
|
||||
-keep enum ezvcard.VCardVersion { *; }
|
||||
-dontwarn ezvcard.io.json.**
|
||||
-dontwarn freemarker.**
|
@ -11,6 +11,8 @@
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
|
||||
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
|
||||
<uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
|
||||
|
||||
<uses-permission
|
||||
android:name="android.permission.USE_FINGERPRINT"
|
||||
@ -26,11 +28,7 @@
|
||||
|
||||
<activity
|
||||
android:name=".activities.SplashActivity"
|
||||
android:theme="@style/SplashTheme">
|
||||
<intent-filter>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
android:theme="@style/SplashTheme"/>
|
||||
|
||||
<activity
|
||||
android:name=".activities.MainActivity">
|
||||
@ -191,19 +189,6 @@
|
||||
android:resource="@xml/provider_paths"/>
|
||||
</provider>
|
||||
|
||||
<!-- Do not append ".Orange" to the default alias "name", it would remove the old homescreen launcher of users at upgrade -->
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity"
|
||||
android:enabled="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Red"
|
||||
android:enabled="false"
|
||||
@ -386,6 +371,18 @@
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Orange"
|
||||
android:enabled="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:targetActivity=".activities.SplashActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.SplashActivity.Deep_orange"
|
||||
android:enabled="false"
|
||||
|
@ -4,7 +4,6 @@ import android.graphics.Bitmap
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.provider.ContactsContract
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.DataSource
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
@ -17,7 +16,6 @@ import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||
import com.simplemobiletools.commons.extensions.getColoredBitmap
|
||||
import com.simplemobiletools.commons.extensions.getContrastColor
|
||||
import com.simplemobiletools.commons.helpers.getDateFormats
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import com.simplemobiletools.contacts.R
|
||||
import com.simplemobiletools.contacts.extensions.config
|
||||
@ -26,16 +24,11 @@ import com.simplemobiletools.contacts.extensions.sendSMSIntent
|
||||
import com.simplemobiletools.contacts.extensions.shareContacts
|
||||
import com.simplemobiletools.contacts.helpers.ContactsHelper
|
||||
import com.simplemobiletools.contacts.models.Contact
|
||||
import org.joda.time.DateTime
|
||||
import org.joda.time.format.DateTimeFormat
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
abstract class ContactActivity : SimpleActivity() {
|
||||
protected var contact: Contact? = null
|
||||
protected var currentContactPhotoPath = ""
|
||||
protected var showFields = 0
|
||||
|
||||
fun showPhotoPlaceholder(photoView: ImageView) {
|
||||
val placeholder = resources.getColoredBitmap(R.drawable.ic_person, config.primaryColor.getContrastColor())
|
||||
@ -69,31 +62,6 @@ abstract class ContactActivity : SimpleActivity() {
|
||||
}).into(photoView)
|
||||
}
|
||||
|
||||
fun getDateTime(dateString: String, viewToUpdate: TextView? = null): DateTime {
|
||||
val dateFormats = getDateFormats()
|
||||
var date = DateTime()
|
||||
for (format in dateFormats) {
|
||||
try {
|
||||
date = DateTime.parse(dateString, DateTimeFormat.forPattern(format))
|
||||
|
||||
val formatter = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault())
|
||||
var localPattern = (formatter as SimpleDateFormat).toLocalizedPattern()
|
||||
|
||||
val hasYear = format.contains("y")
|
||||
if (!hasYear) {
|
||||
localPattern = localPattern.replace("y", "").trim()
|
||||
date = date.withYear(DateTime().year)
|
||||
}
|
||||
|
||||
val formattedString = date.toString(localPattern)
|
||||
viewToUpdate?.text = formattedString
|
||||
break
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
fun deleteContact() {
|
||||
ConfirmationDialog(this) {
|
||||
if (contact != null) {
|
||||
@ -104,9 +72,7 @@ abstract class ContactActivity : SimpleActivity() {
|
||||
}
|
||||
|
||||
fun shareContact() {
|
||||
if (contact != null) {
|
||||
shareContacts(arrayListOf(contact!!))
|
||||
}
|
||||
shareContacts(arrayListOf(contact!!))
|
||||
}
|
||||
|
||||
fun trySendSMS() {
|
||||
|
@ -45,9 +45,6 @@ class EditContactActivity : ContactActivity() {
|
||||
private val CHOOSE_PHOTO = 2
|
||||
private val REMOVE_PHOTO = 3
|
||||
|
||||
private val KEY_PHONE = "phone"
|
||||
private val KEY_NAME = "name"
|
||||
|
||||
private var wasActivityInitialized = false
|
||||
private var lastPhotoIntentUri: Uri? = null
|
||||
private var isSaving = false
|
||||
@ -58,11 +55,11 @@ class EditContactActivity : ContactActivity() {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_edit_contact)
|
||||
supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_cross)
|
||||
showFields = config.showContactFields
|
||||
|
||||
val action = intent.action
|
||||
isThirdPartyIntent = action == Intent.ACTION_EDIT || action == Intent.ACTION_INSERT_OR_EDIT || action == Intent.ACTION_INSERT
|
||||
if (isThirdPartyIntent) {
|
||||
val isFromSimpleContacts = intent.getBooleanExtra(IS_FROM_SIMPLE_CONTACTS, false)
|
||||
if (isThirdPartyIntent && !isFromSimpleContacts) {
|
||||
handlePermission(PERMISSION_READ_CONTACTS) {
|
||||
if (it) {
|
||||
handlePermission(PERMISSION_WRITE_CONTACTS) {
|
||||
@ -94,6 +91,10 @@ class EditContactActivity : ContactActivity() {
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (contact == null) {
|
||||
return true
|
||||
}
|
||||
|
||||
when (item.itemId) {
|
||||
R.id.save -> saveContact()
|
||||
R.id.share -> shareContact()
|
||||
@ -232,7 +233,11 @@ class EditContactActivity : ContactActivity() {
|
||||
Intent().apply {
|
||||
action = Intent.ACTION_EDIT
|
||||
data = getContactPublicUri(contact!!)
|
||||
startActivity(this)
|
||||
if (resolveActivity(packageManager) != null) {
|
||||
startActivity(this)
|
||||
} else {
|
||||
toast(R.string.no_app_found)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,6 +269,7 @@ class EditContactActivity : ContactActivity() {
|
||||
}
|
||||
|
||||
private fun setupFieldVisibility() {
|
||||
val showFields = config.showContactFields
|
||||
if (showFields and (SHOW_PREFIX_FIELD or SHOW_FIRST_NAME_FIELD or SHOW_MIDDLE_NAME_FIELD or SHOW_SURNAME_FIELD or SHOW_SUFFIX_FIELD) == 0) {
|
||||
contact_name_image.beInvisible()
|
||||
}
|
||||
@ -273,6 +279,7 @@ class EditContactActivity : ContactActivity() {
|
||||
contact_middle_name.beVisibleIf(showFields and SHOW_MIDDLE_NAME_FIELD != 0)
|
||||
contact_surname.beVisibleIf(showFields and SHOW_SURNAME_FIELD != 0)
|
||||
contact_suffix.beVisibleIf(showFields and SHOW_SUFFIX_FIELD != 0)
|
||||
contact_nickname.beVisibleIf(showFields and SHOW_NICKNAME_FIELD != 0)
|
||||
|
||||
contact_source.beVisibleIf(showFields and SHOW_CONTACT_SOURCE_FIELD != 0)
|
||||
contact_source_image.beVisibleIf(showFields and SHOW_CONTACT_SOURCE_FIELD != 0)
|
||||
@ -340,112 +347,99 @@ class EditContactActivity : ContactActivity() {
|
||||
contact_middle_name.setText(middleName)
|
||||
contact_surname.setText(surname)
|
||||
contact_suffix.setText(suffix)
|
||||
contact_nickname.setText(nickname)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupPhoneNumbers() {
|
||||
if (showFields and SHOW_PHONE_NUMBERS_FIELD != 0) {
|
||||
contact!!.phoneNumbers.forEachIndexed { index, number ->
|
||||
var numberHolder = contact_numbers_holder.getChildAt(index)
|
||||
if (numberHolder == null) {
|
||||
numberHolder = layoutInflater.inflate(R.layout.item_edit_phone_number, contact_numbers_holder, false)
|
||||
contact_numbers_holder.addView(numberHolder)
|
||||
}
|
||||
contact!!.phoneNumbers.forEachIndexed { index, number ->
|
||||
var numberHolder = contact_numbers_holder.getChildAt(index)
|
||||
if (numberHolder == null) {
|
||||
numberHolder = layoutInflater.inflate(R.layout.item_edit_phone_number, contact_numbers_holder, false)
|
||||
contact_numbers_holder.addView(numberHolder)
|
||||
}
|
||||
|
||||
numberHolder!!.apply {
|
||||
contact_number.setText(number.value)
|
||||
setupPhoneNumberTypePicker(contact_number_type, number.type)
|
||||
}
|
||||
numberHolder!!.apply {
|
||||
contact_number.setText(number.value)
|
||||
setupPhoneNumberTypePicker(contact_number_type, number.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupEmails() {
|
||||
if (showFields and SHOW_EMAILS_FIELD != 0) {
|
||||
contact!!.emails.forEachIndexed { index, email ->
|
||||
var emailHolder = contact_emails_holder.getChildAt(index)
|
||||
if (emailHolder == null) {
|
||||
emailHolder = layoutInflater.inflate(R.layout.item_edit_email, contact_emails_holder, false)
|
||||
contact_emails_holder.addView(emailHolder)
|
||||
}
|
||||
contact!!.emails.forEachIndexed { index, email ->
|
||||
var emailHolder = contact_emails_holder.getChildAt(index)
|
||||
if (emailHolder == null) {
|
||||
emailHolder = layoutInflater.inflate(R.layout.item_edit_email, contact_emails_holder, false)
|
||||
contact_emails_holder.addView(emailHolder)
|
||||
}
|
||||
|
||||
emailHolder!!.apply {
|
||||
contact_email.setText(email.value)
|
||||
setupEmailTypePicker(contact_email_type, email.type)
|
||||
}
|
||||
emailHolder!!.apply {
|
||||
contact_email.setText(email.value)
|
||||
setupEmailTypePicker(contact_email_type, email.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupAddresses() {
|
||||
if (showFields and SHOW_ADDRESSES_FIELD != 0) {
|
||||
contact!!.addresses.forEachIndexed { index, address ->
|
||||
var addressHolder = contact_addresses_holder.getChildAt(index)
|
||||
if (addressHolder == null) {
|
||||
addressHolder = layoutInflater.inflate(R.layout.item_edit_address, contact_addresses_holder, false)
|
||||
contact_addresses_holder.addView(addressHolder)
|
||||
}
|
||||
contact!!.addresses.forEachIndexed { index, address ->
|
||||
var addressHolder = contact_addresses_holder.getChildAt(index)
|
||||
if (addressHolder == null) {
|
||||
addressHolder = layoutInflater.inflate(R.layout.item_edit_address, contact_addresses_holder, false)
|
||||
contact_addresses_holder.addView(addressHolder)
|
||||
}
|
||||
|
||||
addressHolder!!.apply {
|
||||
contact_address.setText(address.value)
|
||||
setupAddressTypePicker(contact_address_type, address.type)
|
||||
}
|
||||
addressHolder!!.apply {
|
||||
contact_address.setText(address.value)
|
||||
setupAddressTypePicker(contact_address_type, address.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupNotes() {
|
||||
if (showFields and SHOW_NOTES_FIELD != 0) {
|
||||
contact_notes.setText(contact!!.notes)
|
||||
}
|
||||
contact_notes.setText(contact!!.notes)
|
||||
}
|
||||
|
||||
private fun setupOrganization() {
|
||||
if (showFields and SHOW_ORGANIZATION_FIELD != 0) {
|
||||
contact_organization_company.setText(contact!!.organization.company)
|
||||
contact_organization_job_position.setText(contact!!.organization.jobPosition)
|
||||
}
|
||||
contact_organization_company.setText(contact!!.organization.company)
|
||||
contact_organization_job_position.setText(contact!!.organization.jobPosition)
|
||||
}
|
||||
|
||||
private fun setupWebsites() {
|
||||
if (showFields and SHOW_WEBSITES_FIELD != 0) {
|
||||
contact!!.websites.forEachIndexed { index, website ->
|
||||
var websitesHolder = contact_websites_holder.getChildAt(index)
|
||||
if (websitesHolder == null) {
|
||||
websitesHolder = layoutInflater.inflate(R.layout.item_edit_website, contact_websites_holder, false)
|
||||
contact_websites_holder.addView(websitesHolder)
|
||||
}
|
||||
|
||||
websitesHolder!!.contact_website.setText(website)
|
||||
contact!!.websites.forEachIndexed { index, website ->
|
||||
var websitesHolder = contact_websites_holder.getChildAt(index)
|
||||
if (websitesHolder == null) {
|
||||
websitesHolder = layoutInflater.inflate(R.layout.item_edit_website, contact_websites_holder, false)
|
||||
contact_websites_holder.addView(websitesHolder)
|
||||
}
|
||||
|
||||
websitesHolder!!.contact_website.setText(website)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupEvents() {
|
||||
if (showFields and SHOW_EVENTS_FIELD != 0) {
|
||||
contact!!.events.forEachIndexed { index, event ->
|
||||
var eventHolder = contact_events_holder.getChildAt(index)
|
||||
if (eventHolder == null) {
|
||||
eventHolder = layoutInflater.inflate(R.layout.item_event, contact_events_holder, false)
|
||||
contact_events_holder.addView(eventHolder)
|
||||
contact!!.events.forEachIndexed { index, event ->
|
||||
var eventHolder = contact_events_holder.getChildAt(index)
|
||||
if (eventHolder == null) {
|
||||
eventHolder = layoutInflater.inflate(R.layout.item_event, contact_events_holder, false)
|
||||
contact_events_holder.addView(eventHolder)
|
||||
}
|
||||
|
||||
(eventHolder as ViewGroup).apply {
|
||||
val contactEvent = contact_event.apply {
|
||||
event.value.getDateTimeFromDateString(this)
|
||||
tag = event.value
|
||||
alpha = 1f
|
||||
}
|
||||
|
||||
(eventHolder as ViewGroup).apply {
|
||||
val contactEvent = contact_event.apply {
|
||||
getDateTime(event.value, this)
|
||||
tag = event.value
|
||||
alpha = 1f
|
||||
}
|
||||
setupEventTypePicker(this, event.type)
|
||||
|
||||
setupEventTypePicker(this, event.type)
|
||||
|
||||
contact_event_remove.apply {
|
||||
beVisible()
|
||||
applyColorFilter(getAdjustedPrimaryColor())
|
||||
background.applyColorFilter(config.textColor)
|
||||
setOnClickListener {
|
||||
resetContactEvent(contactEvent, this)
|
||||
}
|
||||
contact_event_remove.apply {
|
||||
beVisible()
|
||||
applyColorFilter(getAdjustedPrimaryColor())
|
||||
background.applyColorFilter(config.textColor)
|
||||
setOnClickListener {
|
||||
resetContactEvent(contactEvent, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -453,52 +447,50 @@ class EditContactActivity : ContactActivity() {
|
||||
}
|
||||
|
||||
private fun setupGroups() {
|
||||
if (showFields and SHOW_GROUPS_FIELD != 0) {
|
||||
contact_groups_holder.removeAllViews()
|
||||
val groups = contact!!.groups
|
||||
groups.forEachIndexed { index, group ->
|
||||
var groupHolder = contact_groups_holder.getChildAt(index)
|
||||
if (groupHolder == null) {
|
||||
groupHolder = layoutInflater.inflate(R.layout.item_edit_group, contact_groups_holder, false)
|
||||
contact_groups_holder.addView(groupHolder)
|
||||
contact_groups_holder.removeAllViews()
|
||||
val groups = contact!!.groups
|
||||
groups.forEachIndexed { index, group ->
|
||||
var groupHolder = contact_groups_holder.getChildAt(index)
|
||||
if (groupHolder == null) {
|
||||
groupHolder = layoutInflater.inflate(R.layout.item_edit_group, contact_groups_holder, false)
|
||||
contact_groups_holder.addView(groupHolder)
|
||||
}
|
||||
|
||||
(groupHolder as ViewGroup).apply {
|
||||
contact_group.apply {
|
||||
text = group.title
|
||||
setTextColor(config.textColor)
|
||||
tag = group.id
|
||||
alpha = 1f
|
||||
}
|
||||
|
||||
(groupHolder as ViewGroup).apply {
|
||||
contact_group.apply {
|
||||
text = group.title
|
||||
setTextColor(config.textColor)
|
||||
tag = group.id
|
||||
alpha = 1f
|
||||
}
|
||||
setOnClickListener {
|
||||
showSelectGroupsDialog()
|
||||
}
|
||||
|
||||
contact_group_remove.apply {
|
||||
beVisible()
|
||||
applyColorFilter(getAdjustedPrimaryColor())
|
||||
background.applyColorFilter(config.textColor)
|
||||
setOnClickListener {
|
||||
showSelectGroupsDialog()
|
||||
}
|
||||
|
||||
contact_group_remove.apply {
|
||||
beVisible()
|
||||
applyColorFilter(getAdjustedPrimaryColor())
|
||||
background.applyColorFilter(config.textColor)
|
||||
setOnClickListener {
|
||||
removeGroup(group.id)
|
||||
}
|
||||
removeGroup(group.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (groups.isEmpty()) {
|
||||
layoutInflater.inflate(R.layout.item_edit_group, contact_groups_holder, false).apply {
|
||||
contact_group.apply {
|
||||
alpha = 0.5f
|
||||
text = getString(R.string.no_groups)
|
||||
setTextColor(config.textColor)
|
||||
}
|
||||
if (groups.isEmpty()) {
|
||||
layoutInflater.inflate(R.layout.item_edit_group, contact_groups_holder, false).apply {
|
||||
contact_group.apply {
|
||||
alpha = 0.5f
|
||||
text = getString(R.string.no_groups)
|
||||
setTextColor(config.textColor)
|
||||
}
|
||||
|
||||
contact_groups_holder.addView(this)
|
||||
contact_group_remove.beGone()
|
||||
setOnClickListener {
|
||||
showSelectGroupsDialog()
|
||||
}
|
||||
contact_groups_holder.addView(this)
|
||||
contact_group_remove.beGone()
|
||||
setOnClickListener {
|
||||
showSelectGroupsDialog()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -513,8 +505,8 @@ class EditContactActivity : ContactActivity() {
|
||||
supportActionBar?.title = resources.getString(R.string.new_contact)
|
||||
originalContactSource = if (hasContactPermissions()) config.lastUsedContactSource else SMT_PRIVATE
|
||||
val organization = Organization("", "")
|
||||
contact = Contact(0, "", "", "", "", "", "", ArrayList(), ArrayList(), ArrayList(), ArrayList(), originalContactSource, 0, 0, "", null, "",
|
||||
ArrayList(), organization, ArrayList())
|
||||
contact = Contact(0, "", "", "", "", "", "", "", ArrayList(), ArrayList(), ArrayList(), ArrayList(), originalContactSource, 0, 0, "",
|
||||
null, "", ArrayList(), organization, ArrayList())
|
||||
contact_source.text = getPublicContactSource(contact!!.source)
|
||||
}
|
||||
|
||||
@ -603,7 +595,7 @@ class EditContactActivity : ContactActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
val date = getDateTime(eventField.tag?.toString() ?: "")
|
||||
val date = (eventField.tag?.toString() ?: "").getDateTimeFromDateString()
|
||||
DatePickerDialog(this, getDialogTheme(), setDateListener, date.year, date.monthOfYear - 1, date.dayOfMonth).show()
|
||||
}
|
||||
|
||||
@ -713,7 +705,7 @@ class EditContactActivity : ContactActivity() {
|
||||
}
|
||||
|
||||
private fun saveContact() {
|
||||
if (isSaving || contact == null) {
|
||||
if (isSaving) {
|
||||
return
|
||||
}
|
||||
|
||||
@ -725,6 +717,7 @@ class EditContactActivity : ContactActivity() {
|
||||
middleName = contact_middle_name.value
|
||||
surname = contact_surname.value
|
||||
suffix = contact_suffix.value
|
||||
nickname = contact_nickname.value
|
||||
photoUri = currentContactPhotoPath
|
||||
phoneNumbers = getFilledPhoneNumbers()
|
||||
emails = getFilledEmails()
|
||||
|
@ -3,12 +3,17 @@ package com.simplemobiletools.contacts.activities
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.extensions.beVisibleIf
|
||||
import com.simplemobiletools.commons.extensions.getAdjustedPrimaryColor
|
||||
import com.simplemobiletools.commons.extensions.underlineText
|
||||
import com.simplemobiletools.commons.extensions.updateTextColors
|
||||
import com.simplemobiletools.contacts.R
|
||||
import com.simplemobiletools.contacts.adapters.ContactsAdapter
|
||||
import com.simplemobiletools.contacts.dialogs.SelectContactsDialog
|
||||
import com.simplemobiletools.contacts.extensions.*
|
||||
import com.simplemobiletools.contacts.helpers.*
|
||||
import com.simplemobiletools.contacts.helpers.ContactsHelper
|
||||
import com.simplemobiletools.contacts.helpers.GROUP
|
||||
import com.simplemobiletools.contacts.helpers.LOCATION_GROUP_CONTACTS
|
||||
import com.simplemobiletools.contacts.interfaces.RefreshContactsListener
|
||||
import com.simplemobiletools.contacts.interfaces.RemoveFromGroupListener
|
||||
import com.simplemobiletools.contacts.models.Contact
|
||||
@ -102,24 +107,13 @@ class GroupContactsActivity : SimpleActivity(), RemoveFromGroupListener, Refresh
|
||||
val currAdapter = group_contacts_list.adapter
|
||||
if (currAdapter == null) {
|
||||
ContactsAdapter(this, contacts, this, LOCATION_GROUP_CONTACTS, this, group_contacts_list, group_contacts_fastscroller) {
|
||||
when (config.onContactClick) {
|
||||
ON_CLICK_CALL_CONTACT -> {
|
||||
val contact = it as Contact
|
||||
if (contact.phoneNumbers.isNotEmpty()) {
|
||||
tryStartCall(it)
|
||||
} else {
|
||||
toast(R.string.no_phone_number_found)
|
||||
}
|
||||
}
|
||||
ON_CLICK_VIEW_CONTACT -> viewContact(it as Contact)
|
||||
ON_CLICK_EDIT_CONTACT -> editContact(it as Contact)
|
||||
}
|
||||
contactClicked(it as Contact)
|
||||
}.apply {
|
||||
addVerticalDividers(true)
|
||||
group_contacts_list.adapter = this
|
||||
}
|
||||
|
||||
group_contacts_fastscroller.setScrollTo(0)
|
||||
group_contacts_fastscroller.setScrollToY(0)
|
||||
group_contacts_fastscroller.setViews(group_contacts_list) {
|
||||
val item = (group_contacts_list.adapter as ContactsAdapter).contactItems.getOrNull(it)
|
||||
group_contacts_fastscroller.updateBubbleText(item?.getBubbleText() ?: "")
|
||||
|
@ -1,15 +1,13 @@
|
||||
package com.simplemobiletools.contacts.activities
|
||||
|
||||
import android.Manifest
|
||||
import android.app.SearchManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.ActivityCompat
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.os.Handler
|
||||
import android.support.v4.view.MenuItemCompat
|
||||
import android.support.v4.view.ViewPager
|
||||
import android.support.v7.widget.SearchView
|
||||
@ -30,6 +28,7 @@ import com.simplemobiletools.contacts.dialogs.ImportContactsDialog
|
||||
import com.simplemobiletools.contacts.extensions.config
|
||||
import com.simplemobiletools.contacts.extensions.dbHelper
|
||||
import com.simplemobiletools.contacts.extensions.getTempFile
|
||||
import com.simplemobiletools.contacts.fragments.MyViewPagerFragment
|
||||
import com.simplemobiletools.contacts.helpers.*
|
||||
import com.simplemobiletools.contacts.interfaces.RefreshContactsListener
|
||||
import com.simplemobiletools.contacts.models.Contact
|
||||
@ -37,6 +36,7 @@ import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.fragment_contacts.*
|
||||
import kotlinx.android.synthetic.main.fragment_favorites.*
|
||||
import kotlinx.android.synthetic.main.fragment_groups.*
|
||||
import kotlinx.android.synthetic.main.fragment_recents.*
|
||||
import java.io.FileOutputStream
|
||||
|
||||
class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
@ -45,6 +45,7 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
private var werePermissionsHandled = false
|
||||
private var isFirstResume = true
|
||||
private var isGettingContacts = false
|
||||
private var handledShowTabs = 0
|
||||
|
||||
private var storedTextColor = 0
|
||||
private var storedBackgroundColor = 0
|
||||
@ -53,6 +54,7 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
private var storedShowPhoneNumbers = false
|
||||
private var storedStartNameWithSurname = false
|
||||
private var storedFilterDuplicates = true
|
||||
private var storedShowTabs = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -63,26 +65,36 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
// just get a reference to the database to make sure it is created properly
|
||||
dbHelper
|
||||
|
||||
handlePermission(PERMISSION_READ_CALL_LOG) {
|
||||
if (it) {
|
||||
handlePermission(PERMISSION_WRITE_CALL_LOG) {
|
||||
checkContactPermissions()
|
||||
}
|
||||
} else {
|
||||
checkContactPermissions()
|
||||
}
|
||||
}
|
||||
|
||||
storeStateVariables()
|
||||
checkWhatsNewDialog()
|
||||
}
|
||||
|
||||
private fun checkContactPermissions() {
|
||||
handlePermission(PERMISSION_READ_CONTACTS) {
|
||||
werePermissionsHandled = true
|
||||
if (it) {
|
||||
handlePermission(PERMISSION_WRITE_CONTACTS) {
|
||||
// workaround for upgrading from version 3.x to 4.x as we added a new permission from an already granted permissions group
|
||||
val hasGetAccountsPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.GET_ACCOUNTS) == PackageManager.PERMISSION_GRANTED
|
||||
if (!hasGetAccountsPermission) {
|
||||
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.GET_ACCOUNTS), 34)
|
||||
handlePermission(PERMISSION_GET_ACCOUNTS) {
|
||||
storeLocalAccountData()
|
||||
initFragments()
|
||||
}
|
||||
|
||||
storeLocalAccountData()
|
||||
initFragments()
|
||||
}
|
||||
} else {
|
||||
storeLocalAccountData()
|
||||
initFragments()
|
||||
}
|
||||
}
|
||||
storeStateVariables()
|
||||
checkWhatsNewDialog()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
@ -92,6 +104,12 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
return
|
||||
}
|
||||
|
||||
if (storedShowTabs != config.showTabs) {
|
||||
config.lastUsedViewPagerPage = 0
|
||||
System.exit(0)
|
||||
return
|
||||
}
|
||||
|
||||
val configShowContactThumbnails = config.showContactThumbnails
|
||||
if (storedShowContactThumbnails != configShowContactThumbnails) {
|
||||
getAllFragments().forEach {
|
||||
@ -138,10 +156,10 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
initFragments()
|
||||
} else {
|
||||
refreshContacts(ALL_TABS_MASK)
|
||||
}
|
||||
|
||||
getAllFragments().forEach {
|
||||
it?.onActivityResume()
|
||||
getAllFragments().forEach {
|
||||
it?.onActivityResume()
|
||||
}
|
||||
}
|
||||
}
|
||||
isFirstResume = false
|
||||
@ -159,11 +177,12 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.menu, menu)
|
||||
val currentPage = viewpager?.currentItem
|
||||
val currentFragment = getCurrentFragment()
|
||||
|
||||
menu.apply {
|
||||
findItem(R.id.search).isVisible = currentPage != LOCATION_GROUPS_TAB
|
||||
findItem(R.id.sort).isVisible = currentPage != LOCATION_GROUPS_TAB
|
||||
findItem(R.id.filter).isVisible = currentPage != LOCATION_GROUPS_TAB
|
||||
findItem(R.id.search).isVisible = currentFragment != groups_fragment && currentFragment != recents_fragment
|
||||
findItem(R.id.sort).isVisible = currentFragment != groups_fragment && currentFragment != recents_fragment
|
||||
findItem(R.id.filter).isVisible = currentFragment != groups_fragment
|
||||
}
|
||||
setupSearch(menu)
|
||||
return true
|
||||
@ -191,6 +210,7 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
storedShowPhoneNumbers = showPhoneNumbers
|
||||
storedStartNameWithSurname = startNameWithSurname
|
||||
storedFilterDuplicates = filterDuplicates
|
||||
storedShowTabs = showTabs
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,7 +220,7 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
(searchMenuItem!!.actionView as SearchView).apply {
|
||||
setSearchableInfo(searchManager.getSearchableInfo(componentName))
|
||||
isSubmitButtonEnabled = false
|
||||
queryHint = getString(if (viewpager.currentItem == 0) R.string.search_contacts else R.string.search_favorites)
|
||||
queryHint = getString(if (getCurrentFragment() == contacts_fragment) R.string.search_contacts else R.string.search_favorites)
|
||||
setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||
override fun onQueryTextSubmit(query: String) = false
|
||||
|
||||
@ -228,13 +248,30 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
})
|
||||
}
|
||||
|
||||
private fun getCurrentFragment() = when (viewpager.currentItem) {
|
||||
0 -> contacts_fragment
|
||||
1 -> favorites_fragment
|
||||
else -> groups_fragment
|
||||
private fun getCurrentFragment(): MyViewPagerFragment? {
|
||||
val showTabs = config.showTabs
|
||||
val fragments = arrayListOf<MyViewPagerFragment>()
|
||||
if (showTabs and CONTACTS_TAB_MASK != 0) {
|
||||
fragments.add(contacts_fragment)
|
||||
}
|
||||
|
||||
if (showTabs and FAVORITES_TAB_MASK != 0) {
|
||||
fragments.add(favorites_fragment)
|
||||
}
|
||||
|
||||
if (showTabs and RECENTS_TAB_MASK != 0) {
|
||||
fragments.add(recents_fragment)
|
||||
}
|
||||
|
||||
if (showTabs and GROUPS_TAB_MASK != 0) {
|
||||
fragments.add(groups_fragment)
|
||||
}
|
||||
|
||||
return fragments[viewpager.currentItem]
|
||||
}
|
||||
|
||||
private fun setupTabColors() {
|
||||
handledShowTabs = config.showTabs
|
||||
val lastUsedPage = config.lastUsedViewPagerPage
|
||||
main_tabs_holder.apply {
|
||||
background = ColorDrawable(config.backgroundColor)
|
||||
@ -250,10 +287,10 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
|
||||
private fun storeLocalAccountData() {
|
||||
if (config.localAccountType == "-1") {
|
||||
ContactsHelper(this).getContactSources {
|
||||
ContactsHelper(this).getContactSources { sources ->
|
||||
var localAccountType = ""
|
||||
var localAccountName = ""
|
||||
it.forEach {
|
||||
sources.forEach {
|
||||
if (localAccountTypes.contains(it.type)) {
|
||||
localAccountType = it.type
|
||||
localAccountName = it.name
|
||||
@ -266,11 +303,10 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getInactiveTabIndexes(activeIndex: Int) = arrayListOf(0, 1, 2).filter { it != activeIndex }
|
||||
private fun getInactiveTabIndexes(activeIndex: Int) = arrayListOf(0, 1, 2, 3).filter { it != activeIndex }
|
||||
|
||||
private fun initFragments() {
|
||||
refreshContacts(ALL_TABS_MASK)
|
||||
viewpager.offscreenPageLimit = 2
|
||||
viewpager.offscreenPageLimit = 3
|
||||
viewpager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
if (isSearchOpen) {
|
||||
@ -291,11 +327,19 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
}
|
||||
})
|
||||
|
||||
viewpager.onGlobalLayout {
|
||||
refreshContacts(ALL_TABS_MASK)
|
||||
}
|
||||
|
||||
main_tabs_holder.onTabSelectionChanged(
|
||||
tabUnselectedAction = {
|
||||
it.icon?.applyColorFilter(config.textColor)
|
||||
},
|
||||
tabSelectedAction = {
|
||||
if (isSearchOpen) {
|
||||
getCurrentFragment()?.onSearchQueryChanged("")
|
||||
searchMenuItem?.collapseActionView()
|
||||
}
|
||||
viewpager.currentItem = it.position
|
||||
it.icon?.applyColorFilter(getAdjustedPrimaryColor())
|
||||
}
|
||||
@ -305,6 +349,37 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
tryImportContactsFromFile(intent.data)
|
||||
intent.data = null
|
||||
}
|
||||
|
||||
main_tabs_holder.removeAllTabs()
|
||||
var skippedTabs = 0
|
||||
tabsList.forEachIndexed { index, value ->
|
||||
if (config.showTabs and value == 0) {
|
||||
skippedTabs++
|
||||
} else {
|
||||
main_tabs_holder.addTab(main_tabs_holder.newTab().setIcon(getTabIcon(index)), index - skippedTabs, config.lastUsedViewPagerPage == index - skippedTabs)
|
||||
}
|
||||
}
|
||||
|
||||
// selecting the proper tab sometimes glitches, add an extra selector to make sure we have it right
|
||||
main_tabs_holder.onGlobalLayout {
|
||||
Handler().postDelayed({
|
||||
main_tabs_holder.getTabAt(config.lastUsedViewPagerPage)?.select()
|
||||
invalidateOptionsMenu()
|
||||
}, 100L)
|
||||
}
|
||||
|
||||
main_tabs_holder.beVisibleIf(skippedTabs < 3)
|
||||
}
|
||||
|
||||
private fun getTabIcon(position: Int): Drawable {
|
||||
val drawableId = when (position) {
|
||||
LOCATION_CONTACTS_TAB -> R.drawable.ic_person
|
||||
LOCATION_FAVORITES_TAB -> R.drawable.ic_star_on
|
||||
LOCATION_RECENTS_TAB -> R.drawable.ic_clock
|
||||
else -> R.drawable.ic_group
|
||||
}
|
||||
|
||||
return resources.getColoredDrawableWithColor(drawableId, config.textColor)
|
||||
}
|
||||
|
||||
private fun showSortingDialog() {
|
||||
@ -354,10 +429,14 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
return
|
||||
}
|
||||
|
||||
val inputStream = contentResolver.openInputStream(uri)
|
||||
val out = FileOutputStream(tempFile)
|
||||
inputStream.copyTo(out)
|
||||
showImportContactsDialog(tempFile.absolutePath)
|
||||
try {
|
||||
val inputStream = contentResolver.openInputStream(uri)
|
||||
val out = FileOutputStream(tempFile)
|
||||
inputStream.copyTo(out)
|
||||
showImportContactsDialog(tempFile.absolutePath)
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
}
|
||||
}
|
||||
else -> toast(R.string.invalid_file_format)
|
||||
}
|
||||
@ -375,13 +454,13 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
FilePickerDialog(this, pickFile = false, showFAB = true) {
|
||||
ExportContactsDialog(this, it) { file, contactSources ->
|
||||
Thread {
|
||||
ContactsHelper(this).getContacts {
|
||||
val contacts = it.filter { contactSources.contains(it.source) }
|
||||
ContactsHelper(this).getContacts { allContacts ->
|
||||
val contacts = allContacts.filter { contactSources.contains(it.source) }
|
||||
if (contacts.isEmpty()) {
|
||||
toast(R.string.no_entries_for_exporting)
|
||||
} else {
|
||||
VcfExporter().exportContacts(this, file, contacts as ArrayList<Contact>, true) {
|
||||
toast(when (it) {
|
||||
VcfExporter().exportContacts(this, file, contacts as ArrayList<Contact>, true) { result ->
|
||||
toast(when (result) {
|
||||
VcfExporter.ExportResult.EXPORT_OK -> R.string.exporting_successful
|
||||
VcfExporter.ExportResult.EXPORT_PARTIAL -> R.string.exporting_some_entries_failed
|
||||
else -> R.string.exporting_failed
|
||||
@ -395,32 +474,33 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
}
|
||||
|
||||
private fun launchAbout() {
|
||||
val licenses = LICENSE_MULTISELECT or LICENSE_JODA or LICENSE_GLIDE or LICENSE_GSON or LICENSE_STETHO
|
||||
|
||||
val faqItems = arrayListOf(
|
||||
FAQItem(R.string.faq_1_title, R.string.faq_1_text),
|
||||
FAQItem(R.string.faq_2_title_commons, R.string.faq_2_text_commons)
|
||||
)
|
||||
|
||||
startAboutActivity(R.string.app_name, LICENSE_MULTISELECT or LICENSE_JODA or LICENSE_GLIDE or LICENSE_GSON or LICENSE_STETHO,
|
||||
BuildConfig.VERSION_NAME, faqItems)
|
||||
startAboutActivity(R.string.app_name, licenses, BuildConfig.VERSION_NAME, faqItems, true)
|
||||
}
|
||||
|
||||
override fun refreshContacts(refreshTabsMask: Int) {
|
||||
if (isActivityDestroyed() || isGettingContacts) {
|
||||
return
|
||||
}
|
||||
|
||||
isGettingContacts = true
|
||||
|
||||
if (viewpager.adapter == null) {
|
||||
viewpager.adapter = ViewPagerAdapter(this)
|
||||
viewpager.currentItem = config.lastUsedViewPagerPage
|
||||
}
|
||||
|
||||
ContactsHelper(this).getContacts {
|
||||
isGettingContacts = false
|
||||
if (isActivityDestroyed()) {
|
||||
return@getContacts
|
||||
}
|
||||
|
||||
if (viewpager.adapter == null) {
|
||||
viewpager.adapter = ViewPagerAdapter(this, it)
|
||||
viewpager.currentItem = config.lastUsedViewPagerPage
|
||||
}
|
||||
|
||||
if (refreshTabsMask and CONTACTS_TAB_MASK != 0) {
|
||||
contacts_fragment?.refreshContacts(it)
|
||||
}
|
||||
@ -429,6 +509,10 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
favorites_fragment?.refreshContacts(it)
|
||||
}
|
||||
|
||||
if (refreshTabsMask and RECENTS_TAB_MASK != 0) {
|
||||
recents_fragment?.refreshContacts(it)
|
||||
}
|
||||
|
||||
if (refreshTabsMask and GROUPS_TAB_MASK != 0) {
|
||||
if (refreshTabsMask == GROUPS_TAB_MASK) {
|
||||
groups_fragment.skipHashComparing = true
|
||||
@ -436,15 +520,25 @@ class MainActivity : SimpleActivity(), RefreshContactsListener {
|
||||
groups_fragment?.refreshContacts(it)
|
||||
}
|
||||
}
|
||||
|
||||
if (refreshTabsMask and RECENTS_TAB_MASK != 0) {
|
||||
ContactsHelper(this).getRecents {
|
||||
runOnUiThread {
|
||||
recents_fragment?.updateRecentCalls(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAllFragments() = arrayListOf(contacts_fragment, favorites_fragment, groups_fragment)
|
||||
private fun getAllFragments() = arrayListOf(contacts_fragment, favorites_fragment, recents_fragment, groups_fragment)
|
||||
|
||||
private fun checkWhatsNewDialog() {
|
||||
arrayListOf<Release>().apply {
|
||||
add(Release(10, R.string.release_10))
|
||||
add(Release(11, R.string.release_11))
|
||||
add(Release(16, R.string.release_16))
|
||||
add(Release(27, R.string.release_27))
|
||||
add(Release(29, R.string.release_29))
|
||||
checkWhatsNew(this, BuildConfig.VERSION_CODE)
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,13 @@ package com.simplemobiletools.contacts.activities
|
||||
import android.os.Bundle
|
||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||
import com.simplemobiletools.commons.extensions.beVisibleIf
|
||||
import com.simplemobiletools.commons.extensions.isThankYouInstalled
|
||||
import com.simplemobiletools.commons.extensions.launchPurchaseThankYouIntent
|
||||
import com.simplemobiletools.commons.extensions.updateTextColors
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import com.simplemobiletools.contacts.R
|
||||
import com.simplemobiletools.contacts.dialogs.ManageVisibleFieldsDialog
|
||||
import com.simplemobiletools.contacts.dialogs.ManageVisibleTabsDialog
|
||||
import com.simplemobiletools.contacts.extensions.config
|
||||
import com.simplemobiletools.contacts.helpers.ON_CLICK_CALL_CONTACT
|
||||
import com.simplemobiletools.contacts.helpers.ON_CLICK_EDIT_CONTACT
|
||||
@ -23,8 +26,10 @@ class SettingsActivity : SimpleActivity() {
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
setupPurchaseThankYou()
|
||||
setupCustomizeColors()
|
||||
setupManageShownContactFields()
|
||||
setupManageShownTabs()
|
||||
setupUseEnglish()
|
||||
setupAvoidWhatsNew()
|
||||
setupShowInfoBubble()
|
||||
@ -32,10 +37,18 @@ class SettingsActivity : SimpleActivity() {
|
||||
setupShowPhoneNumbers()
|
||||
setupStartNameWithSurname()
|
||||
setupFilterDuplicates()
|
||||
setupShowCallConfirmation()
|
||||
setupOnContactClick()
|
||||
updateTextColors(settings_holder)
|
||||
}
|
||||
|
||||
private fun setupPurchaseThankYou() {
|
||||
settings_purchase_thank_you_holder.beVisibleIf(config.appRunCount > 10 && !isThankYouInstalled())
|
||||
settings_purchase_thank_you_holder.setOnClickListener {
|
||||
launchPurchaseThankYouIntent()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCustomizeColors() {
|
||||
settings_customize_colors_holder.setOnClickListener {
|
||||
startCustomizationActivity()
|
||||
@ -48,6 +61,12 @@ class SettingsActivity : SimpleActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupManageShownTabs() {
|
||||
settings_manage_tabs_holder.setOnClickListener {
|
||||
ManageVisibleTabsDialog(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupUseEnglish() {
|
||||
settings_use_english_holder.beVisibleIf(config.wasUseEnglishToggled || Locale.getDefault().language != "en")
|
||||
settings_use_english.isChecked = config.useEnglish
|
||||
@ -126,4 +145,12 @@ class SettingsActivity : SimpleActivity() {
|
||||
ON_CLICK_VIEW_CONTACT -> R.string.view_contact
|
||||
else -> R.string.edit_contact
|
||||
})
|
||||
|
||||
private fun setupShowCallConfirmation() {
|
||||
settings_show_call_confirmation.isChecked = config.showCallConfirmation
|
||||
settings_show_call_confirmation_holder.setOnClickListener {
|
||||
settings_show_call_confirmation.toggle()
|
||||
config.showCallConfirmation = settings_show_call_confirmation.isChecked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import kotlinx.android.synthetic.main.item_website.view.*
|
||||
|
||||
class ViewContactActivity : ContactActivity() {
|
||||
private var isViewIntent = false
|
||||
private var showFields = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -57,6 +58,10 @@ class ViewContactActivity : ContactActivity() {
|
||||
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (contact == null) {
|
||||
return true
|
||||
}
|
||||
|
||||
when (item.itemId) {
|
||||
R.id.edit -> editContact(contact!!)
|
||||
R.id.share -> shareContact()
|
||||
@ -160,7 +165,11 @@ class ViewContactActivity : ContactActivity() {
|
||||
Intent().apply {
|
||||
action = ContactsContract.QuickContact.ACTION_QUICK_CONTACT
|
||||
data = getContactPublicUri(contact!!)
|
||||
startActivity(this)
|
||||
if (resolveActivity(packageManager) != null) {
|
||||
startActivity(this)
|
||||
} else {
|
||||
toast(R.string.no_app_found)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,7 +202,11 @@ class ViewContactActivity : ContactActivity() {
|
||||
contact_suffix.text = suffix
|
||||
contact_suffix.beVisibleIf(suffix.isNotEmpty() && showFields and SHOW_SUFFIX_FIELD != 0)
|
||||
|
||||
if (contact_prefix.isGone() && contact_first_name.isGone() && contact_middle_name.isGone() && contact_surname.isGone() && contact_suffix.isGone()) {
|
||||
contact_nickname.text = nickname
|
||||
contact_nickname.beVisibleIf(nickname.isNotEmpty() && showFields and SHOW_NICKNAME_FIELD != 0)
|
||||
|
||||
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()
|
||||
(contact_photo.layoutParams as RelativeLayout.LayoutParams).bottomMargin = resources.getDimension(R.dimen.medium_margin).toInt()
|
||||
}
|
||||
@ -280,7 +293,7 @@ class ViewContactActivity : ContactActivity() {
|
||||
layoutInflater.inflate(R.layout.item_event, contact_events_holder, false).apply {
|
||||
contact_events_holder.addView(this)
|
||||
contact_event.alpha = 1f
|
||||
getDateTime(it.value, contact_event)
|
||||
it.value.getDateTimeFromDateString(contact_event)
|
||||
contact_event_type.setText(getEventTextId(it.type))
|
||||
contact_event_remove.beGone()
|
||||
}
|
||||
|
@ -70,10 +70,10 @@ class ContactsAdapter(activity: SimpleActivity, var contactItems: ArrayList<Cont
|
||||
}
|
||||
}
|
||||
|
||||
override fun prepareItemSelection(view: View) {}
|
||||
override fun prepareItemSelection(viewHolder: ViewHolder) {}
|
||||
|
||||
override fun markItemSelection(select: Boolean, view: View?) {
|
||||
view?.contact_frame?.isSelected = select
|
||||
override fun markViewHolderSelection(select: Boolean, viewHolder: ViewHolder?) {
|
||||
viewHolder?.itemView?.contact_frame?.isSelected = select
|
||||
}
|
||||
|
||||
override fun actionItemPressed(id: Int) {
|
||||
@ -96,6 +96,8 @@ class ContactsAdapter(activity: SimpleActivity, var contactItems: ArrayList<Cont
|
||||
|
||||
override fun getSelectableItemCount() = contactItems.size
|
||||
|
||||
override fun getIsItemSelectable(position: Int) = true
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val layout = if (showPhoneNumbers) R.layout.item_contact_with_number else R.layout.item_contact_without_number
|
||||
return createViewHolder(layout, parent)
|
||||
@ -103,7 +105,7 @@ class ContactsAdapter(activity: SimpleActivity, var contactItems: ArrayList<Cont
|
||||
|
||||
override fun onBindViewHolder(holder: MyRecyclerViewAdapter.ViewHolder, position: Int) {
|
||||
val contact = contactItems[position]
|
||||
val view = holder.bindView(contact, true) { itemView, layoutPosition ->
|
||||
val view = holder.bindView(contact, true, true) { itemView, layoutPosition ->
|
||||
setupView(itemView, contact)
|
||||
}
|
||||
bindViewHolder(holder, position, view)
|
||||
@ -145,7 +147,10 @@ class ContactsAdapter(activity: SimpleActivity, var contactItems: ArrayList<Cont
|
||||
|
||||
val contactsToRemove = ArrayList<Contact>()
|
||||
selectedPositions.sortedDescending().forEach {
|
||||
contactsToRemove.add(contactItems[it])
|
||||
val contact = contactItems.getOrNull(it)
|
||||
if (contact != null) {
|
||||
contactsToRemove.add(contact)
|
||||
}
|
||||
}
|
||||
contactItems.removeAll(contactsToRemove)
|
||||
|
||||
@ -155,7 +160,7 @@ class ContactsAdapter(activity: SimpleActivity, var contactItems: ArrayList<Cont
|
||||
finishActMode()
|
||||
} else {
|
||||
removeSelectedItems()
|
||||
refreshListener?.refreshContacts(FAVORITES_TAB_MASK)
|
||||
refreshListener?.refreshContacts(CONTACTS_TAB_MASK or FAVORITES_TAB_MASK)
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,8 +255,7 @@ class ContactsAdapter(activity: SimpleActivity, var contactItems: ArrayList<Cont
|
||||
private fun setupView(view: View, contact: Contact) {
|
||||
view.apply {
|
||||
val fullName = contact.getFullName()
|
||||
val nameText = if (textToHighlight.isEmpty()) fullName else fullName.highlightTextPart(textToHighlight, adjustedPrimaryColor)
|
||||
contact_name.text = nameText
|
||||
contact_name.text = if (textToHighlight.isEmpty()) fullName else fullName.highlightTextPart(textToHighlight, adjustedPrimaryColor)
|
||||
contact_name.setTextColor(textColor)
|
||||
contact_name.setPadding(if (showContactThumbnails) smallPadding else bigPadding, smallPadding, smallPadding, 0)
|
||||
|
||||
|
@ -37,14 +37,14 @@ class GroupsAdapter(activity: SimpleActivity, var groups: ArrayList<Group>, val
|
||||
|
||||
override fun prepareActionMode(menu: Menu) {
|
||||
menu.apply {
|
||||
findItem(R.id.cab_edit).isVisible = isOneItemSelected()
|
||||
findItem(R.id.cab_rename).isVisible = isOneItemSelected()
|
||||
}
|
||||
}
|
||||
|
||||
override fun prepareItemSelection(view: View) {}
|
||||
override fun prepareItemSelection(viewHolder: ViewHolder) {}
|
||||
|
||||
override fun markItemSelection(select: Boolean, view: View?) {
|
||||
view?.group_frame?.isSelected = select
|
||||
override fun markViewHolderSelection(select: Boolean, viewHolder: ViewHolder?) {
|
||||
viewHolder?.itemView?.group_frame?.isSelected = select
|
||||
}
|
||||
|
||||
override fun actionItemPressed(id: Int) {
|
||||
@ -53,7 +53,7 @@ class GroupsAdapter(activity: SimpleActivity, var groups: ArrayList<Group>, val
|
||||
}
|
||||
|
||||
when (id) {
|
||||
R.id.cab_edit -> editGroup()
|
||||
R.id.cab_rename -> renameGroup()
|
||||
R.id.cab_select_all -> selectAll()
|
||||
R.id.cab_delete -> askConfirmDelete()
|
||||
}
|
||||
@ -61,11 +61,13 @@ class GroupsAdapter(activity: SimpleActivity, var groups: ArrayList<Group>, val
|
||||
|
||||
override fun getSelectableItemCount() = groups.size
|
||||
|
||||
override fun getIsItemSelectable(position: Int) = true
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_group, parent)
|
||||
|
||||
override fun onBindViewHolder(holder: MyRecyclerViewAdapter.ViewHolder, position: Int) {
|
||||
val group = groups[position]
|
||||
val view = holder.bindView(group, true) { itemView, layoutPosition ->
|
||||
val view = holder.bindView(group, true, true) { itemView, layoutPosition ->
|
||||
setupView(itemView, group)
|
||||
}
|
||||
bindViewHolder(holder, position, view)
|
||||
@ -80,7 +82,7 @@ class GroupsAdapter(activity: SimpleActivity, var groups: ArrayList<Group>, val
|
||||
fastScroller?.measureRecyclerView()
|
||||
}
|
||||
|
||||
private fun editGroup() {
|
||||
private fun renameGroup() {
|
||||
RenameGroupDialog(activity, groups[selectedPositions.first()]) {
|
||||
finishActMode()
|
||||
refreshListener?.refreshContacts(GROUPS_TAB_MASK)
|
||||
@ -89,11 +91,11 @@ class GroupsAdapter(activity: SimpleActivity, var groups: ArrayList<Group>, val
|
||||
|
||||
private fun askConfirmDelete() {
|
||||
ConfirmationDialog(activity) {
|
||||
deleteContacts()
|
||||
deleteGroups()
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteContacts() {
|
||||
private fun deleteGroups() {
|
||||
if (selectedPositions.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
@ -0,0 +1,119 @@
|
||||
package com.simplemobiletools.contacts.adapters
|
||||
|
||||
import android.view.Menu
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
|
||||
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
||||
import com.simplemobiletools.commons.extensions.beVisibleIf
|
||||
import com.simplemobiletools.commons.views.FastScroller
|
||||
import com.simplemobiletools.commons.views.MyRecyclerView
|
||||
import com.simplemobiletools.contacts.R
|
||||
import com.simplemobiletools.contacts.activities.SimpleActivity
|
||||
import com.simplemobiletools.contacts.extensions.config
|
||||
import com.simplemobiletools.contacts.helpers.ContactsHelper
|
||||
import com.simplemobiletools.contacts.helpers.RECENTS_TAB_MASK
|
||||
import com.simplemobiletools.contacts.interfaces.RefreshContactsListener
|
||||
import com.simplemobiletools.contacts.models.RecentCall
|
||||
import kotlinx.android.synthetic.main.item_recent_call.view.*
|
||||
import java.util.*
|
||||
|
||||
class RecentCallsAdapter(activity: SimpleActivity, var recentCalls: ArrayList<RecentCall>, val refreshListener: RefreshContactsListener?, recyclerView: MyRecyclerView,
|
||||
fastScroller: FastScroller, itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) {
|
||||
private val showPhoneNumbers = activity.config.showPhoneNumbers
|
||||
|
||||
init {
|
||||
setupDragListener(true)
|
||||
}
|
||||
|
||||
override fun getActionMenuId() = R.menu.cab_recent_calls
|
||||
|
||||
override fun prepareActionMode(menu: Menu) {}
|
||||
|
||||
override fun prepareItemSelection(viewHolder: ViewHolder) {}
|
||||
|
||||
override fun markViewHolderSelection(select: Boolean, viewHolder: ViewHolder?) {
|
||||
viewHolder?.itemView?.recent_call_frame?.isSelected = select
|
||||
}
|
||||
|
||||
override fun actionItemPressed(id: Int) {
|
||||
if (selectedPositions.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
when (id) {
|
||||
R.id.cab_select_all -> selectAll()
|
||||
R.id.cab_delete -> askConfirmDelete()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSelectableItemCount() = recentCalls.size
|
||||
|
||||
override fun getIsItemSelectable(position: Int) = true
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_recent_call, parent)
|
||||
|
||||
override fun onBindViewHolder(holder: MyRecyclerViewAdapter.ViewHolder, position: Int) {
|
||||
val recentCall = recentCalls[position]
|
||||
val view = holder.bindView(recentCall, true, true) { itemView, layoutPosition ->
|
||||
setupView(itemView, recentCall)
|
||||
}
|
||||
bindViewHolder(holder, position, view)
|
||||
}
|
||||
|
||||
override fun getItemCount() = recentCalls.size
|
||||
|
||||
fun updateItems(newItems: ArrayList<RecentCall>) {
|
||||
recentCalls = newItems
|
||||
notifyDataSetChanged()
|
||||
finishActMode()
|
||||
fastScroller?.measureRecyclerView()
|
||||
}
|
||||
|
||||
private fun askConfirmDelete() {
|
||||
ConfirmationDialog(activity) {
|
||||
deleteRecentCalls()
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteRecentCalls() {
|
||||
if (selectedPositions.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
val callsToRemove = ArrayList<RecentCall>()
|
||||
selectedPositions.sortedDescending().forEach {
|
||||
val call = recentCalls[it]
|
||||
callsToRemove.add(call)
|
||||
}
|
||||
ContactsHelper(activity).removeRecentCalls(callsToRemove.map { it.id } as ArrayList<Int>)
|
||||
recentCalls.removeAll(callsToRemove)
|
||||
|
||||
if (recentCalls.isEmpty()) {
|
||||
refreshListener?.refreshContacts(RECENTS_TAB_MASK)
|
||||
finishActMode()
|
||||
} else {
|
||||
removeSelectedItems()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupView(view: View, recentCall: RecentCall) {
|
||||
view.apply {
|
||||
recent_call_name.apply {
|
||||
text = recentCall.name ?: recentCall.number
|
||||
setTextColor(textColor)
|
||||
}
|
||||
|
||||
recent_call_number.apply {
|
||||
beVisibleIf(showPhoneNumbers && recentCall.name != null)
|
||||
text = recentCall.number
|
||||
setTextColor(textColor)
|
||||
}
|
||||
|
||||
recent_call_date_time.apply {
|
||||
text = recentCall.dateTime
|
||||
setTextColor(textColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -5,19 +5,22 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.simplemobiletools.contacts.R
|
||||
import com.simplemobiletools.contacts.activities.MainActivity
|
||||
import com.simplemobiletools.contacts.extensions.config
|
||||
import com.simplemobiletools.contacts.fragments.MyViewPagerFragment
|
||||
import com.simplemobiletools.contacts.models.Contact
|
||||
import com.simplemobiletools.contacts.helpers.*
|
||||
|
||||
class ViewPagerAdapter(val activity: MainActivity, val contacts: ArrayList<Contact>) : PagerAdapter() {
|
||||
class ViewPagerAdapter(val activity: MainActivity) : PagerAdapter() {
|
||||
private val showTabs = activity.config.showTabs
|
||||
|
||||
override fun instantiateItem(container: ViewGroup, position: Int): Any {
|
||||
val layout = getFragment(position)
|
||||
val view = activity.layoutInflater.inflate(layout, container, false)
|
||||
container.addView(view)
|
||||
|
||||
(view as MyViewPagerFragment).apply {
|
||||
setupFragment(activity)
|
||||
refreshContacts(contacts)
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
@ -25,12 +28,28 @@ class ViewPagerAdapter(val activity: MainActivity, val contacts: ArrayList<Conta
|
||||
container.removeView(item as View)
|
||||
}
|
||||
|
||||
override fun getCount() = 3
|
||||
override fun getCount() = tabsList.filter { it and showTabs != 0 }.size
|
||||
|
||||
override fun isViewFromObject(view: View, item: Any) = view == item
|
||||
|
||||
private fun getFragment(position: Int) = when (position) {
|
||||
0 -> R.layout.fragment_contacts
|
||||
1 -> R.layout.fragment_favorites
|
||||
else -> R.layout.fragment_groups
|
||||
private fun getFragment(position: Int): Int {
|
||||
val fragments = arrayListOf<Int>()
|
||||
if (showTabs and CONTACTS_TAB_MASK != 0) {
|
||||
fragments.add(R.layout.fragment_contacts)
|
||||
}
|
||||
|
||||
if (showTabs and FAVORITES_TAB_MASK != 0) {
|
||||
fragments.add(R.layout.fragment_favorites)
|
||||
}
|
||||
|
||||
if (showTabs and RECENTS_TAB_MASK != 0) {
|
||||
fragments.add(R.layout.fragment_recents)
|
||||
}
|
||||
|
||||
if (showTabs and GROUPS_TAB_MASK != 0) {
|
||||
fragments.add(R.layout.fragment_groups)
|
||||
}
|
||||
|
||||
return fragments[position]
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
package com.simplemobiletools.contacts.dialogs
|
||||
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.view.animation.AnimationUtils
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.applyColorFilter
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import com.simplemobiletools.contacts.R
|
||||
import com.simplemobiletools.contacts.extensions.config
|
||||
import com.simplemobiletools.contacts.models.Contact
|
||||
import kotlinx.android.synthetic.main.dialog_call_confirmation.view.*
|
||||
|
||||
class CallConfirmationDialog(val activity: BaseSimpleActivity, val contact: Contact, private val callback: () -> Unit) {
|
||||
private var view = activity.layoutInflater.inflate(R.layout.dialog_call_confirmation, null)
|
||||
|
||||
init {
|
||||
view.call_confirm_phone.applyColorFilter(activity.config.textColor)
|
||||
AlertDialog.Builder(activity)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
val title = String.format(activity.getString(R.string.call_person), contact.getFullName())
|
||||
activity.setupDialogStuff(view, this, titleText = title) {
|
||||
view.call_confirm_phone.apply {
|
||||
startAnimation(AnimationUtils.loadAnimation(activity, R.anim.pulsing_animation))
|
||||
setOnClickListener {
|
||||
callback.invoke()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ class ManageVisibleFieldsDialog(val activity: BaseSimpleActivity) {
|
||||
put(SHOW_MIDDLE_NAME_FIELD, R.id.manage_visible_fields_middle_name)
|
||||
put(SHOW_SURNAME_FIELD, R.id.manage_visible_fields_surname)
|
||||
put(SHOW_SUFFIX_FIELD, R.id.manage_visible_fields_suffix)
|
||||
put(SHOW_NICKNAME_FIELD, R.id.manage_visible_fields_nickname)
|
||||
put(SHOW_PHONE_NUMBERS_FIELD, R.id.manage_visible_fields_phone_numbers)
|
||||
put(SHOW_EMAILS_FIELD, R.id.manage_visible_fields_emails)
|
||||
put(SHOW_ADDRESSES_FIELD, R.id.manage_visible_fields_addresses)
|
||||
@ -36,7 +37,7 @@ class ManageVisibleFieldsDialog(val activity: BaseSimpleActivity) {
|
||||
}
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.ok, { dialog, which -> dialogConfirmed() })
|
||||
.setPositiveButton(R.string.ok) { dialog, which -> dialogConfirmed() }
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
activity.setupDialogStuff(view, this)
|
||||
|
@ -0,0 +1,50 @@
|
||||
package com.simplemobiletools.contacts.dialogs
|
||||
|
||||
import android.support.v7.app.AlertDialog
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
import com.simplemobiletools.contacts.R
|
||||
import com.simplemobiletools.contacts.extensions.config
|
||||
import com.simplemobiletools.contacts.helpers.*
|
||||
|
||||
class ManageVisibleTabsDialog(val activity: BaseSimpleActivity) {
|
||||
private var view = activity.layoutInflater.inflate(R.layout.dialog_manage_visible_tabs, null)
|
||||
private val tabs = LinkedHashMap<Int, Int>()
|
||||
|
||||
init {
|
||||
tabs.apply {
|
||||
put(CONTACTS_TAB_MASK, R.id.manage_visible_tabs_contacts)
|
||||
put(FAVORITES_TAB_MASK, R.id.manage_visible_tabs_favorites)
|
||||
put(RECENTS_TAB_MASK, R.id.manage_visible_tabs_recents)
|
||||
put(GROUPS_TAB_MASK, R.id.manage_visible_tabs_groups)
|
||||
}
|
||||
|
||||
val showTabs = activity.config.showTabs
|
||||
for ((key, value) in tabs) {
|
||||
view.findViewById<MyAppCompatCheckbox>(value).isChecked = showTabs and key != 0
|
||||
}
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
.setPositiveButton(R.string.ok) { dialog, which -> dialogConfirmed() }
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create().apply {
|
||||
activity.setupDialogStuff(view, this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun dialogConfirmed() {
|
||||
var result = 0
|
||||
for ((key, value) in tabs) {
|
||||
if (view.findViewById<MyAppCompatCheckbox>(value).isChecked) {
|
||||
result += key
|
||||
}
|
||||
}
|
||||
|
||||
if (result == 0) {
|
||||
result = ALL_TABS_MASK
|
||||
}
|
||||
|
||||
activity.config.showTabs = result
|
||||
}
|
||||
}
|
@ -14,9 +14,8 @@ import com.simplemobiletools.commons.models.RadioItem
|
||||
import com.simplemobiletools.contacts.BuildConfig
|
||||
import com.simplemobiletools.contacts.R
|
||||
import com.simplemobiletools.contacts.activities.SimpleActivity
|
||||
import com.simplemobiletools.contacts.helpers.ContactsHelper
|
||||
import com.simplemobiletools.contacts.helpers.SMT_PRIVATE
|
||||
import com.simplemobiletools.contacts.helpers.VcfExporter
|
||||
import com.simplemobiletools.contacts.dialogs.CallConfirmationDialog
|
||||
import com.simplemobiletools.contacts.helpers.*
|
||||
import com.simplemobiletools.contacts.models.Contact
|
||||
import com.simplemobiletools.contacts.models.ContactSource
|
||||
import java.io.File
|
||||
@ -36,6 +35,16 @@ fun SimpleActivity.startCallIntent(recipient: String) {
|
||||
}
|
||||
|
||||
fun SimpleActivity.tryStartCall(contact: Contact) {
|
||||
if (config.showCallConfirmation) {
|
||||
CallConfirmationDialog(this, contact) {
|
||||
startCall(contact)
|
||||
}
|
||||
} else {
|
||||
startCall(contact)
|
||||
}
|
||||
}
|
||||
|
||||
fun SimpleActivity.startCall(contact: Contact) {
|
||||
val numbers = contact.phoneNumbers
|
||||
if (numbers.size == 1) {
|
||||
startCallIntent(numbers.first().value)
|
||||
@ -105,10 +114,10 @@ fun BaseSimpleActivity.shareContacts(contacts: ArrayList<Contact>) {
|
||||
fun BaseSimpleActivity.sendSMSToContacts(contacts: ArrayList<Contact>) {
|
||||
val numbers = StringBuilder()
|
||||
contacts.forEach {
|
||||
it.phoneNumbers.forEach {
|
||||
if (it.value.isNotEmpty()) {
|
||||
numbers.append("${it.value};")
|
||||
}
|
||||
val number = it.phoneNumbers.firstOrNull { it.type == ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE }
|
||||
?: it.phoneNumbers.firstOrNull()
|
||||
if (number != null) {
|
||||
numbers.append("${number.value};")
|
||||
}
|
||||
|
||||
val uriString = "smsto:${numbers.toString().trimEnd(';')}"
|
||||
@ -191,3 +200,17 @@ fun Activity.getVisibleContactSources(): ArrayList<String> {
|
||||
sourceNames.removeAll(config.ignoredContactSources)
|
||||
return sourceNames
|
||||
}
|
||||
|
||||
fun SimpleActivity.contactClicked(contact: Contact) {
|
||||
when (config.onContactClick) {
|
||||
ON_CLICK_CALL_CONTACT -> {
|
||||
if (contact.phoneNumbers.isNotEmpty()) {
|
||||
tryStartCall(contact)
|
||||
} else {
|
||||
toast(R.string.no_phone_number_found)
|
||||
}
|
||||
}
|
||||
ON_CLICK_VIEW_CONTACT -> viewContact(contact)
|
||||
ON_CLICK_EDIT_CONTACT -> editContact(contact)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
package com.simplemobiletools.contacts.extensions
|
||||
|
||||
import android.widget.TextView
|
||||
import com.simplemobiletools.commons.helpers.getDateFormats
|
||||
import org.joda.time.DateTime
|
||||
import org.joda.time.format.DateTimeFormat
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
fun String.getDateTimeFromDateString(viewToUpdate: TextView? = null): DateTime {
|
||||
val dateFormats = getDateFormats()
|
||||
var date = DateTime()
|
||||
for (format in dateFormats) {
|
||||
try {
|
||||
date = DateTime.parse(this, DateTimeFormat.forPattern(format))
|
||||
|
||||
val formatter = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault())
|
||||
var localPattern = (formatter as SimpleDateFormat).toLocalizedPattern()
|
||||
|
||||
val hasYear = format.contains("y")
|
||||
if (!hasYear) {
|
||||
localPattern = localPattern.replace("y", "").trim()
|
||||
date = date.withYear(DateTime().year)
|
||||
}
|
||||
|
||||
val formattedString = date.toString(localPattern)
|
||||
viewToUpdate?.text = formattedString
|
||||
break
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
}
|
||||
return date
|
||||
}
|
@ -15,7 +15,10 @@ import com.simplemobiletools.contacts.activities.MainActivity
|
||||
import com.simplemobiletools.contacts.activities.SimpleActivity
|
||||
import com.simplemobiletools.contacts.adapters.ContactsAdapter
|
||||
import com.simplemobiletools.contacts.adapters.GroupsAdapter
|
||||
import com.simplemobiletools.contacts.extensions.*
|
||||
import com.simplemobiletools.contacts.adapters.RecentCallsAdapter
|
||||
import com.simplemobiletools.contacts.extensions.config
|
||||
import com.simplemobiletools.contacts.extensions.contactClicked
|
||||
import com.simplemobiletools.contacts.extensions.getVisibleContactSources
|
||||
import com.simplemobiletools.contacts.helpers.*
|
||||
import com.simplemobiletools.contacts.models.Contact
|
||||
import com.simplemobiletools.contacts.models.Group
|
||||
@ -47,21 +50,28 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
|
||||
fragment_placeholder_2.underlineText()
|
||||
updateViewStuff()
|
||||
|
||||
if (this is FavoritesFragment) {
|
||||
fragment_placeholder.text = activity.getString(R.string.no_favorites)
|
||||
fragment_placeholder_2.text = activity.getString(R.string.add_favorites)
|
||||
} else if (this is GroupsFragment) {
|
||||
fragment_placeholder.text = activity.getString(R.string.no_group_created)
|
||||
fragment_placeholder_2.text = activity.getString(R.string.create_group)
|
||||
when {
|
||||
this is FavoritesFragment -> {
|
||||
fragment_placeholder.text = activity.getString(R.string.no_favorites)
|
||||
fragment_placeholder_2.text = activity.getString(R.string.add_favorites)
|
||||
}
|
||||
this is GroupsFragment -> {
|
||||
fragment_placeholder.text = activity.getString(R.string.no_group_created)
|
||||
fragment_placeholder_2.text = activity.getString(R.string.create_group)
|
||||
}
|
||||
this is RecentsFragment -> {
|
||||
fragment_fab.beGone()
|
||||
fragment_placeholder_2.text = activity.getString(R.string.request_the_required_permissions)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun textColorChanged(color: Int) {
|
||||
if (this is GroupsFragment) {
|
||||
(fragment_list.adapter as GroupsAdapter).updateTextColor(color)
|
||||
} else {
|
||||
(fragment_list.adapter as ContactsAdapter).apply {
|
||||
when {
|
||||
this is GroupsFragment -> (fragment_list.adapter as GroupsAdapter).updateTextColor(color)
|
||||
this is RecentsFragment -> (fragment_list.adapter as RecentCallsAdapter).updateTextColor(color)
|
||||
else -> (fragment_list.adapter as ContactsAdapter).apply {
|
||||
updateTextColor(color)
|
||||
initDrawables()
|
||||
}
|
||||
@ -77,7 +87,7 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
|
||||
}
|
||||
|
||||
fun startNameWithSurnameChanged(startNameWithSurname: Boolean) {
|
||||
if (this !is GroupsFragment) {
|
||||
if (this !is GroupsFragment && this !is RecentsFragment) {
|
||||
(fragment_list.adapter as ContactsAdapter).apply {
|
||||
config.sorting = if (startNameWithSurname) SORT_BY_SURNAME else SORT_BY_FIRST_NAME
|
||||
this@MyViewPagerFragment.activity!!.refreshContacts(CONTACTS_TAB_MASK or FAVORITES_TAB_MASK)
|
||||
@ -86,6 +96,13 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
|
||||
}
|
||||
|
||||
fun refreshContacts(contacts: ArrayList<Contact>) {
|
||||
if ((config.showTabs and CONTACTS_TAB_MASK == 0 && this is ContactsFragment) ||
|
||||
(config.showTabs and FAVORITES_TAB_MASK == 0 && this is FavoritesFragment) ||
|
||||
(config.showTabs and RECENTS_TAB_MASK == 0 && this is RecentsFragment) ||
|
||||
(config.showTabs and GROUPS_TAB_MASK == 0 && this is GroupsFragment)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (config.lastUsedContactSource.isEmpty()) {
|
||||
val grouped = contacts.groupBy { it.source }.maxWith(compareBy { it.value.size })
|
||||
config.lastUsedContactSource = grouped?.key ?: ""
|
||||
@ -99,6 +116,7 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
|
||||
val filtered = when {
|
||||
this is GroupsFragment -> contacts
|
||||
this is FavoritesFragment -> contacts.filter { it.starred == 1 } as ArrayList<Contact>
|
||||
this is RecentsFragment -> ArrayList()
|
||||
else -> {
|
||||
val contactSources = activity!!.getVisibleContactSources()
|
||||
contacts.filter { contactSources.contains(it.source) } as ArrayList<Contact>
|
||||
@ -117,9 +135,13 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
|
||||
private fun setupContacts(contacts: ArrayList<Contact>) {
|
||||
if (this is GroupsFragment) {
|
||||
setupGroupsAdapter(contacts)
|
||||
} else {
|
||||
} else if (this !is RecentsFragment) {
|
||||
setupContactsFavoritesAdapter(contacts)
|
||||
}
|
||||
|
||||
if (this is ContactsFragment || this is FavoritesFragment) {
|
||||
contactsIgnoringSearch = (fragment_list?.adapter as? ContactsAdapter)?.contactItems ?: ArrayList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupGroupsAdapter(contacts: ArrayList<Contact>) {
|
||||
@ -150,7 +172,7 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
|
||||
fragment_list.adapter = this
|
||||
}
|
||||
|
||||
fragment_fastscroller.setScrollTo(0)
|
||||
fragment_fastscroller.setScrollToY(0)
|
||||
fragment_fastscroller.setViews(fragment_list) {
|
||||
val item = (fragment_list.adapter as GroupsAdapter).groups.getOrNull(it)
|
||||
fragment_fastscroller.updateBubbleText(item?.getBubbleText() ?: "")
|
||||
@ -164,33 +186,19 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
|
||||
}
|
||||
|
||||
private fun setupContactsFavoritesAdapter(contacts: ArrayList<Contact>) {
|
||||
fragment_placeholder_2.beVisibleIf(contacts.isEmpty())
|
||||
fragment_placeholder.beVisibleIf(contacts.isEmpty())
|
||||
fragment_list.beVisibleIf(contacts.isNotEmpty())
|
||||
|
||||
setupViewVisibility(contacts)
|
||||
val currAdapter = fragment_list.adapter
|
||||
if (currAdapter == null || forceListRedraw) {
|
||||
forceListRedraw = false
|
||||
val location = if (this is FavoritesFragment) LOCATION_FAVORITES_TAB else LOCATION_CONTACTS_TAB
|
||||
ContactsAdapter(activity as SimpleActivity, contacts, activity, location, null, fragment_list, fragment_fastscroller) {
|
||||
when (config.onContactClick) {
|
||||
ON_CLICK_CALL_CONTACT -> {
|
||||
val contact = it as Contact
|
||||
if (contact.phoneNumbers.isNotEmpty()) {
|
||||
(activity as SimpleActivity).tryStartCall(it)
|
||||
} else {
|
||||
activity!!.toast(R.string.no_phone_number_found)
|
||||
}
|
||||
}
|
||||
ON_CLICK_VIEW_CONTACT -> context!!.viewContact(it as Contact)
|
||||
ON_CLICK_EDIT_CONTACT -> context!!.editContact(it as Contact)
|
||||
}
|
||||
activity?.contactClicked(it as Contact)
|
||||
}.apply {
|
||||
addVerticalDividers(true)
|
||||
fragment_list.adapter = this
|
||||
}
|
||||
|
||||
fragment_fastscroller.setScrollTo(0)
|
||||
fragment_fastscroller.setScrollToY(0)
|
||||
fragment_fastscroller.setViews(fragment_list) {
|
||||
val item = (fragment_list.adapter as ContactsAdapter).contactItems.getOrNull(it)
|
||||
fragment_fastscroller.updateBubbleText(item?.getBubbleText() ?: "")
|
||||
@ -211,7 +219,7 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
|
||||
showContactThumbnails = showThumbnails
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
} else {
|
||||
} else if (this !is RecentsFragment) {
|
||||
(fragment_list.adapter as? ContactsAdapter)?.apply {
|
||||
showContactThumbnails = showThumbnails
|
||||
notifyDataSetChanged()
|
||||
@ -228,38 +236,44 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
|
||||
}
|
||||
|
||||
fun onSearchQueryChanged(text: String) {
|
||||
val shouldNormalize = text.normalizeString() == text
|
||||
(fragment_list.adapter as? ContactsAdapter)?.apply {
|
||||
val filtered = contactsIgnoringSearch.filter {
|
||||
it.getFullName().contains(text, true) ||
|
||||
getProperText(it.getFullName(), shouldNormalize).contains(text, true) ||
|
||||
getProperText(it.nickname, shouldNormalize).contains(text, true) ||
|
||||
it.phoneNumbers.any { it.value.contains(text, true) } ||
|
||||
it.emails.any { it.value.contains(text, true) } ||
|
||||
it.addresses.any { it.value.contains(text, true) } ||
|
||||
it.notes.contains(text, true) ||
|
||||
it.organization.company.contains(text, true) ||
|
||||
it.organization.jobPosition.contains(text, true) ||
|
||||
it.addresses.any { getProperText(it.value, shouldNormalize).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
|
||||
|
||||
Contact.sorting = config.sorting
|
||||
Contact.startWithSurname = config.startNameWithSurname
|
||||
filtered.sort()
|
||||
filtered.sortBy { !it.getFullName().startsWith(text, true) }
|
||||
filtered.sortBy { !getProperText(it.getFullName(), shouldNormalize).startsWith(text, true) }
|
||||
|
||||
if (filtered.isEmpty() && this@MyViewPagerFragment is FavoritesFragment) {
|
||||
fragment_placeholder.text = activity.getString(R.string.no_items_found)
|
||||
}
|
||||
|
||||
fragment_placeholder.beVisibleIf(filtered.isEmpty())
|
||||
updateItems(filtered, text)
|
||||
updateItems(filtered, text.normalizeString())
|
||||
}
|
||||
}
|
||||
|
||||
private fun getProperText(text: String, shouldNormalize: Boolean) = if (shouldNormalize) text.normalizeString() else text
|
||||
|
||||
fun onSearchOpened() {
|
||||
contactsIgnoringSearch = (fragment_list?.adapter as? ContactsAdapter)?.contactItems ?: ArrayList()
|
||||
}
|
||||
|
||||
fun onSearchClosed() {
|
||||
(fragment_list.adapter as? ContactsAdapter)?.updateItems(contactsIgnoringSearch)
|
||||
setupViewVisibility(contactsIgnoringSearch)
|
||||
|
||||
if (this is FavoritesFragment) {
|
||||
fragment_placeholder.text = activity?.getString(R.string.no_favorites)
|
||||
}
|
||||
@ -272,6 +286,12 @@ abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet)
|
||||
fragment_placeholder_2.setTextColor(context.getAdjustedPrimaryColor())
|
||||
}
|
||||
|
||||
private fun setupViewVisibility(contacts: ArrayList<Contact>) {
|
||||
fragment_placeholder_2.beVisibleIf(contacts.isEmpty())
|
||||
fragment_placeholder.beVisibleIf(contacts.isEmpty())
|
||||
fragment_list.beVisibleIf(contacts.isNotEmpty())
|
||||
}
|
||||
|
||||
abstract fun fabClicked()
|
||||
|
||||
abstract fun placeholderClicked()
|
||||
|
@ -0,0 +1,79 @@
|
||||
package com.simplemobiletools.contacts.fragments
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.util.AttributeSet
|
||||
import com.simplemobiletools.commons.extensions.beVisibleIf
|
||||
import com.simplemobiletools.commons.extensions.hasPermission
|
||||
import com.simplemobiletools.commons.extensions.isActivityDestroyed
|
||||
import com.simplemobiletools.commons.helpers.PERMISSION_READ_CALL_LOG
|
||||
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_CALL_LOG
|
||||
import com.simplemobiletools.contacts.activities.EditContactActivity
|
||||
import com.simplemobiletools.contacts.adapters.RecentCallsAdapter
|
||||
import com.simplemobiletools.contacts.extensions.contactClicked
|
||||
import com.simplemobiletools.contacts.helpers.IS_FROM_SIMPLE_CONTACTS
|
||||
import com.simplemobiletools.contacts.helpers.KEY_PHONE
|
||||
import com.simplemobiletools.contacts.helpers.PHONE_NUMBER_PATTERN
|
||||
import com.simplemobiletools.contacts.helpers.RECENTS_TAB_MASK
|
||||
import com.simplemobiletools.contacts.models.Contact
|
||||
import com.simplemobiletools.contacts.models.RecentCall
|
||||
import kotlinx.android.synthetic.main.fragment_layout.view.*
|
||||
|
||||
class RecentsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet) {
|
||||
override fun fabClicked() {}
|
||||
|
||||
override fun placeholderClicked() {
|
||||
activity!!.handlePermission(PERMISSION_WRITE_CALL_LOG) {
|
||||
if (it) {
|
||||
activity!!.handlePermission(PERMISSION_READ_CALL_LOG) {
|
||||
activity?.refreshContacts(RECENTS_TAB_MASK)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateRecentCalls(recentCalls: ArrayList<RecentCall>) {
|
||||
if (activity == null || activity!!.isActivityDestroyed()) {
|
||||
return
|
||||
}
|
||||
|
||||
fragment_placeholder.beVisibleIf(recentCalls.isEmpty())
|
||||
fragment_placeholder_2.beVisibleIf(recentCalls.isEmpty() && !activity!!.hasPermission(PERMISSION_WRITE_CALL_LOG))
|
||||
fragment_list.beVisibleIf(recentCalls.isNotEmpty())
|
||||
|
||||
val currAdapter = fragment_list.adapter
|
||||
if (currAdapter == null) {
|
||||
RecentCallsAdapter(activity!!, recentCalls, activity, fragment_list, fragment_fastscroller) {
|
||||
val recentCall = (it as RecentCall).number.replace(PHONE_NUMBER_PATTERN.toRegex(), "")
|
||||
var selectedContact: Contact? = null
|
||||
for (contact in allContacts) {
|
||||
if (contact.phoneNumbers.any { it.value.replace(PHONE_NUMBER_PATTERN.toRegex(), "") == recentCall }) {
|
||||
selectedContact = contact
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedContact != null) {
|
||||
activity?.contactClicked(selectedContact)
|
||||
} else {
|
||||
Intent(context, EditContactActivity::class.java).apply {
|
||||
action = Intent.ACTION_INSERT
|
||||
putExtra(KEY_PHONE, recentCall)
|
||||
putExtra(IS_FROM_SIMPLE_CONTACTS, true)
|
||||
context.startActivity(this)
|
||||
}
|
||||
}
|
||||
}.apply {
|
||||
addVerticalDividers(true)
|
||||
fragment_list.adapter = this
|
||||
}
|
||||
|
||||
fragment_fastscroller.setViews(fragment_list) {
|
||||
val item = (fragment_list.adapter as RecentCallsAdapter).recentCalls.getOrNull(it)
|
||||
fragment_fastscroller.updateBubbleText(item?.name ?: item?.number ?: "")
|
||||
}
|
||||
} else {
|
||||
(currAdapter as RecentCallsAdapter).updateItems(recentCalls)
|
||||
}
|
||||
}
|
||||
}
|
@ -48,4 +48,12 @@ class Config(context: Context) : BaseConfig(context) {
|
||||
var filterDuplicates: Boolean
|
||||
get() = prefs.getBoolean(FILTER_DUPLICATES, true)
|
||||
set(filterDuplicates) = prefs.edit().putBoolean(FILTER_DUPLICATES, filterDuplicates).apply()
|
||||
|
||||
var showTabs: Int
|
||||
get() = prefs.getInt(SHOW_TABS, ALL_TABS_MASK)
|
||||
set(showTabs) = prefs.edit().putInt(SHOW_TABS, showTabs).apply()
|
||||
|
||||
var showCallConfirmation: Boolean
|
||||
get() = prefs.getBoolean(SHOW_CALL_CONFIRMATION, false)
|
||||
set(showCallConfirmation) = prefs.edit().putBoolean(SHOW_CALL_CONFIRMATION, showCallConfirmation).apply()
|
||||
}
|
||||
|
@ -12,23 +12,39 @@ const val LOCAL_ACCOUNT_NAME = "local_account_name"
|
||||
const val LOCAL_ACCOUNT_TYPE = "local_account_type"
|
||||
const val ON_CONTACT_CLICK = "on_contact_click"
|
||||
const val SHOW_CONTACT_FIELDS = "show_contact_fields"
|
||||
const val SHOW_TABS = "show_tabs"
|
||||
const val FILTER_DUPLICATES = "filter_duplicates"
|
||||
const val SHOW_CALL_CONFIRMATION = "show_call_confirmation"
|
||||
|
||||
const val CONTACT_ID = "contact_id"
|
||||
const val SMT_PRIVATE = "smt_private" // used at the contact source of local contacts hidden from other apps
|
||||
const val IS_PRIVATE = "is_private"
|
||||
const val GROUP = "group"
|
||||
const val FIRST_GROUP_ID = 10000
|
||||
const val PHONE_NUMBER_PATTERN = "\\D+"
|
||||
const val IS_FROM_SIMPLE_CONTACTS = "is_from_simple_contacts"
|
||||
|
||||
// extras used at third party intents
|
||||
const val KEY_PHONE = "phone"
|
||||
const val KEY_NAME = "name"
|
||||
|
||||
const val LOCATION_CONTACTS_TAB = 0
|
||||
const val LOCATION_FAVORITES_TAB = 1
|
||||
const val LOCATION_GROUPS_TAB = 2
|
||||
const val LOCATION_GROUP_CONTACTS = 3
|
||||
const val LOCATION_RECENTS_TAB = 2
|
||||
const val LOCATION_GROUPS_TAB = 3
|
||||
const val LOCATION_GROUP_CONTACTS = 4
|
||||
|
||||
const val CONTACTS_TAB_MASK = 1
|
||||
const val FAVORITES_TAB_MASK = 2
|
||||
const val GROUPS_TAB_MASK = 4
|
||||
const val ALL_TABS_MASK = 7
|
||||
const val RECENTS_TAB_MASK = 4
|
||||
const val GROUPS_TAB_MASK = 8
|
||||
const val ALL_TABS_MASK = 15
|
||||
|
||||
val tabsList = arrayListOf(CONTACTS_TAB_MASK,
|
||||
FAVORITES_TAB_MASK,
|
||||
RECENTS_TAB_MASK,
|
||||
GROUPS_TAB_MASK
|
||||
)
|
||||
|
||||
// contact photo changes
|
||||
const val PHOTO_ADDED = 1
|
||||
@ -36,25 +52,6 @@ const val PHOTO_REMOVED = 2
|
||||
const val PHOTO_CHANGED = 3
|
||||
const val PHOTO_UNCHANGED = 4
|
||||
|
||||
// export/import
|
||||
const val BEGIN_VCARD = "BEGIN:VCARD"
|
||||
const val END_VCARD = "END:VCARD"
|
||||
const val N = "N"
|
||||
const val TEL = "TEL"
|
||||
const val BDAY = "BDAY:"
|
||||
const val ANNIVERSARY = "ANNIVERSARY:"
|
||||
const val PHOTO = "PHOTO"
|
||||
const val EMAIL = "EMAIL"
|
||||
const val ADR = "ADR"
|
||||
const val NOTE = "NOTE:"
|
||||
const val ORG = "ORG:"
|
||||
const val TITLE = "TITLE:"
|
||||
const val URL = "URL:"
|
||||
const val ENCODING = "ENCODING"
|
||||
const val BASE64 = "BASE64"
|
||||
const val JPEG = "JPEG"
|
||||
const val VERSION_2_1 = "VERSION:2.1"
|
||||
|
||||
// phone number/email types
|
||||
const val CELL = "CELL"
|
||||
const val WORK = "WORK"
|
||||
@ -66,7 +63,6 @@ const val WORK_FAX = "WORK;FAX"
|
||||
const val HOME_FAX = "HOME;FAX"
|
||||
const val PAGER = "PAGER"
|
||||
const val MOBILE = "MOBILE"
|
||||
const val VOICE = "VOICE"
|
||||
|
||||
const val ON_CLICK_CALL_CONTACT = 1
|
||||
const val ON_CLICK_VIEW_CONTACT = 2
|
||||
@ -87,6 +83,7 @@ const val SHOW_ORGANIZATION_FIELD = 1024
|
||||
const val SHOW_GROUPS_FIELD = 2048
|
||||
const val SHOW_CONTACT_SOURCE_FIELD = 4096
|
||||
const val SHOW_WEBSITES_FIELD = 8192
|
||||
const val SHOW_NICKNAME_FIELD = 16384
|
||||
|
||||
const val DEFAULT_EMAIL_TYPE = CommonDataKinds.Email.TYPE_HOME
|
||||
const val DEFAULT_PHONE_NUMBER_TYPE = CommonDataKinds.Phone.TYPE_MOBILE
|
||||
|
@ -1,26 +1,29 @@
|
||||
package com.simplemobiletools.contacts.helpers
|
||||
|
||||
import android.accounts.Account
|
||||
import android.accounts.AccountManager
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.*
|
||||
import android.database.Cursor
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.provider.CallLog
|
||||
import android.provider.ContactsContract
|
||||
import android.provider.ContactsContract.CommonDataKinds
|
||||
import android.provider.ContactsContract.CommonDataKinds.Nickname
|
||||
import android.provider.ContactsContract.CommonDataKinds.Note
|
||||
import android.provider.MediaStore
|
||||
import android.text.TextUtils
|
||||
import android.util.SparseArray
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_FIRST_NAME
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_MIDDLE_NAME
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_SURNAME
|
||||
import com.simplemobiletools.commons.helpers.SORT_DESCENDING
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.contacts.R
|
||||
import com.simplemobiletools.contacts.extensions.*
|
||||
import com.simplemobiletools.contacts.models.*
|
||||
import com.simplemobiletools.contacts.overloads.times
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class ContactsHelper(val activity: Activity) {
|
||||
private val BATCH_SIZE = 100
|
||||
@ -61,6 +64,33 @@ class ContactsHelper(val activity: Activity) {
|
||||
}.start()
|
||||
}
|
||||
|
||||
private fun getContentResolverAccounts(): HashSet<ContactSource> {
|
||||
val uri = ContactsContract.Data.CONTENT_URI
|
||||
val projection = arrayOf(
|
||||
ContactsContract.RawContacts.ACCOUNT_NAME,
|
||||
ContactsContract.RawContacts.ACCOUNT_TYPE
|
||||
)
|
||||
|
||||
val sources = HashSet<ContactSource>()
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = activity.contentResolver.query(uri, projection, null, null, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
val name = cursor.getStringValue(ContactsContract.RawContacts.ACCOUNT_NAME) ?: ""
|
||||
val type = cursor.getStringValue(ContactsContract.RawContacts.ACCOUNT_TYPE) ?: ""
|
||||
val source = ContactSource(name, type)
|
||||
sources.add(source)
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
|
||||
return sources
|
||||
}
|
||||
|
||||
private fun getDeviceContacts(contacts: SparseArray<Contact>) {
|
||||
if (!activity.hasContactPermissions()) {
|
||||
return
|
||||
@ -83,6 +113,7 @@ class ContactsHelper(val activity: Activity) {
|
||||
val middleName = cursor.getStringValue(CommonDataKinds.StructuredName.MIDDLE_NAME) ?: ""
|
||||
val surname = cursor.getStringValue(CommonDataKinds.StructuredName.FAMILY_NAME) ?: ""
|
||||
val suffix = cursor.getStringValue(CommonDataKinds.StructuredName.SUFFIX) ?: ""
|
||||
val nickname = ""
|
||||
val photoUri = cursor.getStringValue(CommonDataKinds.StructuredName.PHOTO_URI) ?: ""
|
||||
val number = ArrayList<PhoneNumber>() // proper value is obtained below
|
||||
val emails = ArrayList<Email>()
|
||||
@ -96,8 +127,8 @@ class ContactsHelper(val activity: Activity) {
|
||||
val groups = ArrayList<Group>()
|
||||
val organization = Organization("", "")
|
||||
val websites = ArrayList<String>()
|
||||
val contact = Contact(id, prefix, firstName, middleName, surname, suffix, photoUri, number, emails, addresses, events,
|
||||
accountName, starred, contactId, thumbnailUri, null, notes, groups, organization, websites)
|
||||
val contact = Contact(id, prefix, firstName, middleName, surname, suffix, nickname, photoUri, number, emails, addresses,
|
||||
events, accountName, starred, contactId, thumbnailUri, null, notes, groups, organization, websites)
|
||||
|
||||
contacts.put(id, contact)
|
||||
} while (cursor.moveToNext())
|
||||
@ -115,6 +146,13 @@ class ContactsHelper(val activity: Activity) {
|
||||
contacts[key]?.phoneNumbers = phoneNumbers.valueAt(i)
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -196,6 +234,36 @@ class ContactsHelper(val activity: Activity) {
|
||||
return phoneNumbers
|
||||
}
|
||||
|
||||
private fun getNicknames(contactId: Int? = null): SparseArray<String> {
|
||||
val nicknames = SparseArray<String>()
|
||||
val uri = ContactsContract.Data.CONTENT_URI
|
||||
val projection = arrayOf(
|
||||
ContactsContract.Data.RAW_CONTACT_ID,
|
||||
Nickname.NAME
|
||||
)
|
||||
|
||||
val selection = getSourcesSelection(true, contactId != null)
|
||||
val selectionArgs = getSourcesSelectionArgs(Nickname.CONTENT_ITEM_TYPE, contactId)
|
||||
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = activity.contentResolver.query(uri, projection, selection, selectionArgs, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
val id = cursor.getIntValue(ContactsContract.Data.RAW_CONTACT_ID)
|
||||
val nickname = cursor.getStringValue(Nickname.NAME) ?: continue
|
||||
nicknames.put(id, nickname)
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
activity.showErrorToast(e)
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
|
||||
return nicknames
|
||||
}
|
||||
|
||||
private fun getEmails(contactId: Int? = null): SparseArray<ArrayList<Email>> {
|
||||
val emails = SparseArray<ArrayList<Email>>()
|
||||
val uri = CommonDataKinds.Email.CONTENT_URI
|
||||
@ -251,7 +319,7 @@ class ContactsHelper(val activity: Activity) {
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
val id = cursor.getIntValue(ContactsContract.Data.RAW_CONTACT_ID)
|
||||
val address = cursor.getStringValue(CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS) ?: ""
|
||||
val address = cursor.getStringValue(CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS) ?: continue
|
||||
val type = cursor.getIntValue(CommonDataKinds.StructuredPostal.TYPE)
|
||||
|
||||
if (addresses[id] == null) {
|
||||
@ -324,7 +392,7 @@ class ContactsHelper(val activity: Activity) {
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
val id = cursor.getIntValue(ContactsContract.Data.RAW_CONTACT_ID)
|
||||
val note = cursor.getStringValue(CommonDataKinds.Note.NOTE) ?: continue
|
||||
val note = cursor.getStringValue(Note.NOTE) ?: continue
|
||||
notes.put(id, note)
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
@ -355,8 +423,12 @@ class ContactsHelper(val activity: Activity) {
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
val id = cursor.getIntValue(ContactsContract.Data.RAW_CONTACT_ID)
|
||||
val company = cursor.getStringValue(CommonDataKinds.Organization.COMPANY) ?: continue
|
||||
val title = cursor.getStringValue(CommonDataKinds.Organization.TITLE) ?: continue
|
||||
val company = cursor.getStringValue(CommonDataKinds.Organization.COMPANY) ?: ""
|
||||
val title = cursor.getStringValue(CommonDataKinds.Organization.TITLE) ?: ""
|
||||
if (company.isEmpty() && title.isEmpty()) {
|
||||
continue
|
||||
}
|
||||
|
||||
val organization = Organization(company, title)
|
||||
organizations.put(id, organization)
|
||||
} while (cursor.moveToNext())
|
||||
@ -621,6 +693,7 @@ class ContactsHelper(val activity: Activity) {
|
||||
val middleName = cursor.getStringValue(CommonDataKinds.StructuredName.MIDDLE_NAME) ?: ""
|
||||
val surname = cursor.getStringValue(CommonDataKinds.StructuredName.FAMILY_NAME) ?: ""
|
||||
val suffix = cursor.getStringValue(CommonDataKinds.StructuredName.SUFFIX) ?: ""
|
||||
val nickname = getNicknames(id)[id] ?: ""
|
||||
val photoUri = cursor.getStringValue(CommonDataKinds.Phone.PHOTO_URI) ?: ""
|
||||
val number = getPhoneNumbers(id)[id] ?: ArrayList()
|
||||
val emails = getEmails(id)[id] ?: ArrayList()
|
||||
@ -634,8 +707,8 @@ class ContactsHelper(val activity: Activity) {
|
||||
val thumbnailUri = cursor.getStringValue(CommonDataKinds.StructuredName.PHOTO_THUMBNAIL_URI) ?: ""
|
||||
val organization = getOrganizations(id)[id] ?: Organization("", "")
|
||||
val websites = getWebsites(id)[id] ?: ArrayList()
|
||||
return Contact(id, prefix, firstName, middleName, surname, suffix, photoUri, number, emails, addresses, events, accountName,
|
||||
starred, contactId, thumbnailUri, null, notes, groups, organization, websites)
|
||||
return Contact(id, prefix, firstName, middleName, surname, suffix, nickname, photoUri, number, emails, addresses, events,
|
||||
accountName, starred, contactId, thumbnailUri, null, notes, groups, organization, websites)
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
@ -662,14 +735,19 @@ class ContactsHelper(val activity: Activity) {
|
||||
return sources
|
||||
}
|
||||
|
||||
val accountManager = AccountManager.get(activity)
|
||||
accountManager.accounts.filter { it.name.contains("@") || localAccountTypes.contains(it.type) }.forEach {
|
||||
val accounts = AccountManager.get(activity).accounts
|
||||
accounts.forEach {
|
||||
if (ContentResolver.getIsSyncable(it, ContactsContract.AUTHORITY) == 1) {
|
||||
val contactSource = ContactSource(it.name, it.type)
|
||||
sources.add(contactSource)
|
||||
}
|
||||
}
|
||||
|
||||
val contentResolverAccounts = getContentResolverAccounts().filter {
|
||||
it.name.isNotEmpty() && it.type.isNotEmpty() && !accounts.contains(Account(it.name, it.type))
|
||||
}
|
||||
sources.addAll(contentResolverAccounts)
|
||||
|
||||
if (sources.isEmpty() && activity.config.localAccountName.isEmpty() && activity.config.localAccountType.isEmpty()) {
|
||||
sources.add(ContactSource("", ""))
|
||||
}
|
||||
@ -747,6 +825,22 @@ class ContactsHelper(val activity: Activity) {
|
||||
operations.add(build())
|
||||
}
|
||||
|
||||
// delete nickname
|
||||
ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI).apply {
|
||||
val selection = "${ContactsContract.Data.RAW_CONTACT_ID} = ? AND ${ContactsContract.Data.MIMETYPE} = ? "
|
||||
val selectionArgs = arrayOf(contact.id.toString(), Nickname.CONTENT_ITEM_TYPE)
|
||||
withSelection(selection, selectionArgs)
|
||||
operations.add(build())
|
||||
}
|
||||
|
||||
// add nickname
|
||||
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply {
|
||||
withValue(ContactsContract.Data.RAW_CONTACT_ID, contact.id)
|
||||
withValue(ContactsContract.Data.MIMETYPE, Nickname.CONTENT_ITEM_TYPE)
|
||||
withValue(Nickname.NAME, contact.nickname)
|
||||
operations.add(build())
|
||||
}
|
||||
|
||||
// delete phone numbers
|
||||
ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI).apply {
|
||||
val selection = "${ContactsContract.Data.RAW_CONTACT_ID} = ? AND ${ContactsContract.Data.MIMETYPE} = ? "
|
||||
@ -823,20 +917,34 @@ class ContactsHelper(val activity: Activity) {
|
||||
}
|
||||
}
|
||||
|
||||
// notes
|
||||
ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI).apply {
|
||||
val selection = "${ContactsContract.Data.RAW_CONTACT_ID} = ? AND ${ContactsContract.Data.MIMETYPE} = ?"
|
||||
// delete notes
|
||||
ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI).apply {
|
||||
val selection = "${ContactsContract.Data.RAW_CONTACT_ID} = ? AND ${ContactsContract.Data.MIMETYPE} = ? "
|
||||
val selectionArgs = arrayOf(contact.id.toString(), Note.CONTENT_ITEM_TYPE)
|
||||
withSelection(selection, selectionArgs)
|
||||
operations.add(build())
|
||||
}
|
||||
|
||||
// add notes
|
||||
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply {
|
||||
withValue(ContactsContract.Data.RAW_CONTACT_ID, contact.id)
|
||||
withValue(ContactsContract.Data.MIMETYPE, Note.CONTENT_ITEM_TYPE)
|
||||
withValue(Note.NOTE, contact.notes)
|
||||
operations.add(build())
|
||||
}
|
||||
|
||||
// organization
|
||||
ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI).apply {
|
||||
val selection = "${ContactsContract.Data.RAW_CONTACT_ID} = ? AND ${ContactsContract.Data.MIMETYPE} = ?"
|
||||
// delete organization
|
||||
ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI).apply {
|
||||
val selection = "${ContactsContract.Data.RAW_CONTACT_ID} = ? AND ${ContactsContract.Data.MIMETYPE} = ? "
|
||||
val selectionArgs = arrayOf(contact.id.toString(), CommonDataKinds.Organization.CONTENT_ITEM_TYPE)
|
||||
withSelection(selection, selectionArgs)
|
||||
operations.add(build())
|
||||
}
|
||||
|
||||
// add organization
|
||||
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply {
|
||||
withValue(ContactsContract.Data.RAW_CONTACT_ID, contact.id)
|
||||
withValue(ContactsContract.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)
|
||||
@ -960,7 +1068,12 @@ class ContactsHelper(val activity: Activity) {
|
||||
operations.clear()
|
||||
}
|
||||
}
|
||||
activity.contentResolver.applyBatch(ContactsContract.AUTHORITY, operations)
|
||||
|
||||
try {
|
||||
activity.contentResolver.applyBatch(ContactsContract.AUTHORITY, operations)
|
||||
} catch (e: Exception) {
|
||||
activity.showErrorToast(e)
|
||||
}
|
||||
}
|
||||
|
||||
fun removeContactsFromGroup(contacts: ArrayList<Contact>, groupId: Long) {
|
||||
@ -1006,6 +1119,14 @@ class ContactsHelper(val activity: Activity) {
|
||||
operations.add(build())
|
||||
}
|
||||
|
||||
// nickname
|
||||
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply {
|
||||
withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
|
||||
withValue(ContactsContract.Data.MIMETYPE, Nickname.CONTENT_ITEM_TYPE)
|
||||
withValue(Nickname.NAME, contact.nickname)
|
||||
operations.add(build())
|
||||
}
|
||||
|
||||
// phone numbers
|
||||
contact.phoneNumbers.forEach {
|
||||
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI).apply {
|
||||
@ -1262,7 +1383,92 @@ class ContactsHelper(val activity: Activity) {
|
||||
}
|
||||
}
|
||||
|
||||
activity.contentResolver.applyBatch(ContactsContract.AUTHORITY, operations)
|
||||
if (activity.hasPermission(PERMISSION_WRITE_CONTACTS)) {
|
||||
activity.contentResolver.applyBatch(ContactsContract.AUTHORITY, operations)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
activity.showErrorToast(e)
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun getRecents(callback: (ArrayList<RecentCall>) -> Unit) {
|
||||
Thread {
|
||||
val calls = ArrayList<RecentCall>()
|
||||
if (!activity.hasPermission(PERMISSION_WRITE_CALL_LOG) || !activity.hasPermission(PERMISSION_READ_CALL_LOG)) {
|
||||
callback(calls)
|
||||
return@Thread
|
||||
}
|
||||
|
||||
val uri = CallLog.Calls.CONTENT_URI
|
||||
val projection = arrayOf(
|
||||
CallLog.Calls._ID,
|
||||
CallLog.Calls.NUMBER,
|
||||
CallLog.Calls.DATE,
|
||||
CallLog.Calls.CACHED_NAME
|
||||
)
|
||||
|
||||
val sorting = "${CallLog.Calls._ID} DESC LIMIT 100"
|
||||
val currentDate = Date(System.currentTimeMillis())
|
||||
val currentYear = SimpleDateFormat("yyyy", Locale.getDefault()).format(currentDate)
|
||||
val todayDate = SimpleDateFormat("dd MMM yyyy", Locale.getDefault()).format(currentDate)
|
||||
val yesterdayDate = SimpleDateFormat("dd MMM yyyy", Locale.getDefault()).format(Date(System.currentTimeMillis() - DAY_SECONDS * 1000))
|
||||
val yesterday = activity.getString(R.string.yesterday)
|
||||
var prevNumber = ""
|
||||
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = activity.contentResolver.query(uri, projection, null, null, sorting)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
val id = cursor.getIntValue(CallLog.Calls._ID)
|
||||
val number = cursor.getStringValue(CallLog.Calls.NUMBER)
|
||||
val date = cursor.getLongValue(CallLog.Calls.DATE)
|
||||
val name = cursor.getStringValue(CallLog.Calls.CACHED_NAME)
|
||||
if (number == prevNumber) {
|
||||
continue
|
||||
}
|
||||
|
||||
var formattedDate = SimpleDateFormat("dd MMM yyyy, HH:mm", Locale.getDefault()).format(Date(date))
|
||||
val datePart = formattedDate.substring(0, 11)
|
||||
when {
|
||||
datePart == todayDate -> formattedDate = formattedDate.substring(12)
|
||||
datePart == yesterdayDate -> formattedDate = yesterday + formattedDate.substring(11)
|
||||
formattedDate.substring(7, 11) == currentYear -> formattedDate = formattedDate.substring(0, 6) + formattedDate.substring(11)
|
||||
}
|
||||
|
||||
prevNumber = number
|
||||
val recentCall = RecentCall(id, number, formattedDate, name)
|
||||
calls.add(recentCall)
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
callback(calls)
|
||||
}.start()
|
||||
}
|
||||
|
||||
fun removeRecentCalls(ids: ArrayList<Int>) {
|
||||
Thread {
|
||||
try {
|
||||
val operations = ArrayList<ContentProviderOperation>()
|
||||
val selection = "${CallLog.Calls._ID} = ?"
|
||||
ids.forEach {
|
||||
ContentProviderOperation.newDelete(CallLog.Calls.CONTENT_URI).apply {
|
||||
val selectionArgs = arrayOf(it.toString())
|
||||
withSelection(selection, selectionArgs)
|
||||
operations.add(build())
|
||||
}
|
||||
|
||||
if (operations.size % BATCH_SIZE == 0) {
|
||||
activity.contentResolver.applyBatch(CallLog.AUTHORITY, operations)
|
||||
operations.clear()
|
||||
}
|
||||
}
|
||||
|
||||
activity.contentResolver.applyBatch(CallLog.AUTHORITY, operations)
|
||||
} catch (e: Exception) {
|
||||
activity.showErrorToast(e)
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
|
||||
private val COL_MIDDLE_NAME = "middle_name"
|
||||
private val COL_SURNAME = "surname"
|
||||
private val COL_SUFFIX = "suffix"
|
||||
private val COL_NICKNAME = "nickname"
|
||||
private val COL_PHOTO = "photo"
|
||||
private val COL_PHONE_NUMBERS = "phone_numbers"
|
||||
private val COL_EMAILS = "emails"
|
||||
@ -48,9 +49,9 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
|
||||
private val mDb = writableDatabase
|
||||
|
||||
companion object {
|
||||
private const val DB_VERSION = 5
|
||||
const val DB_NAME = "contacts.db"
|
||||
var dbInstance: DBHelper? = null
|
||||
private const val DB_VERSION = 6
|
||||
private var dbInstance: DBHelper? = null
|
||||
var gson = Gson()
|
||||
|
||||
fun newInstance(context: Context): DBHelper {
|
||||
@ -65,7 +66,7 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
|
||||
db.execSQL("CREATE TABLE $CONTACTS_TABLE_NAME ($COL_ID INTEGER PRIMARY KEY AUTOINCREMENT, $COL_FIRST_NAME TEXT, $COL_MIDDLE_NAME TEXT, " +
|
||||
"$COL_SURNAME TEXT, $COL_PHOTO BLOB, $COL_PHONE_NUMBERS TEXT, $COL_EMAILS TEXT, $COL_EVENTS TEXT, $COL_STARRED INTEGER, " +
|
||||
"$COL_ADDRESSES TEXT, $COL_NOTES TEXT, $COL_GROUPS TEXT, $COL_PREFIX TEXT, $COL_SUFFIX TEXT, $COL_COMPANY TEXT, $COL_JOB_POSITION TEXT," +
|
||||
"$COL_WEBSITES TEXT)")
|
||||
"$COL_WEBSITES TEXT, $COL_NICKNAME TEXT)")
|
||||
|
||||
// start autoincrement ID from FIRST_CONTACT_ID to avoid conflicts
|
||||
db.execSQL("REPLACE INTO sqlite_sequence (name, seq) VALUES ('$CONTACTS_TABLE_NAME', $FIRST_CONTACT_ID)")
|
||||
@ -94,6 +95,10 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
|
||||
if (oldVersion < 5) {
|
||||
db.execSQL("ALTER TABLE $CONTACTS_TABLE_NAME ADD COLUMN $COL_WEBSITES TEXT DEFAULT ''")
|
||||
}
|
||||
|
||||
if (oldVersion < 6) {
|
||||
db.execSQL("ALTER TABLE $CONTACTS_TABLE_NAME ADD COLUMN $COL_NICKNAME TEXT DEFAULT ''")
|
||||
}
|
||||
}
|
||||
|
||||
private fun createGroupsTable(db: SQLiteDatabase) {
|
||||
@ -135,6 +140,7 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
|
||||
put(COL_MIDDLE_NAME, contact.middleName)
|
||||
put(COL_SURNAME, contact.surname)
|
||||
put(COL_SUFFIX, contact.suffix)
|
||||
put(COL_NICKNAME, contact.nickname)
|
||||
put(COL_PHONE_NUMBERS, gson.toJson(contact.phoneNumbers))
|
||||
put(COL_EMAILS, gson.toJson(contact.emails))
|
||||
put(COL_ADDRESSES, gson.toJson(contact.addresses))
|
||||
@ -252,8 +258,8 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
|
||||
fun getContacts(activity: Activity, selection: String? = null, selectionArgs: Array<String>? = null): ArrayList<Contact> {
|
||||
val storedGroups = ContactsHelper(activity).getStoredGroups()
|
||||
val contacts = ArrayList<Contact>()
|
||||
val projection = arrayOf(COL_ID, COL_PREFIX, COL_FIRST_NAME, COL_MIDDLE_NAME, COL_SURNAME, COL_SUFFIX, COL_PHONE_NUMBERS, COL_EMAILS,
|
||||
COL_EVENTS, COL_STARRED, COL_PHOTO, COL_ADDRESSES, COL_NOTES, COL_GROUPS, COL_COMPANY, COL_JOB_POSITION, COL_WEBSITES)
|
||||
val projection = arrayOf(COL_ID, COL_PREFIX, COL_FIRST_NAME, COL_MIDDLE_NAME, COL_SURNAME, COL_SUFFIX, COL_NICKNAME, COL_PHONE_NUMBERS,
|
||||
COL_EMAILS, COL_EVENTS, COL_STARRED, COL_PHOTO, COL_ADDRESSES, COL_NOTES, COL_GROUPS, COL_COMPANY, COL_JOB_POSITION, COL_WEBSITES)
|
||||
|
||||
val phoneNumbersToken = object : TypeToken<List<PhoneNumber>>() {}.type
|
||||
val emailsToken = object : TypeToken<List<Email>>() {}.type
|
||||
@ -271,6 +277,7 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
|
||||
val middleName = cursor.getStringValue(COL_MIDDLE_NAME)
|
||||
val surname = cursor.getStringValue(COL_SURNAME)
|
||||
val suffix = cursor.getStringValue(COL_SUFFIX)
|
||||
val nickname = cursor.getStringValue(COL_NICKNAME)
|
||||
|
||||
val phoneNumbersJson = cursor.getStringValue(COL_PHONE_NUMBERS)
|
||||
val phoneNumbers = if (phoneNumbersJson == "[]") ArrayList() else gson.fromJson<ArrayList<PhoneNumber>>(phoneNumbersJson, phoneNumbersToken)
|
||||
@ -290,7 +297,11 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
|
||||
|
||||
val photoByteArray = cursor.getBlobValue(COL_PHOTO) ?: null
|
||||
val photo = if (photoByteArray?.isNotEmpty() == true) {
|
||||
BitmapFactory.decodeByteArray(photoByteArray, 0, photoByteArray.size)
|
||||
try {
|
||||
BitmapFactory.decodeByteArray(photoByteArray, 0, photoByteArray.size)
|
||||
} catch (e: OutOfMemoryError) {
|
||||
null
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
@ -311,8 +322,8 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
|
||||
val websites = if (websitesJson == "[]") ArrayList() else gson.fromJson<ArrayList<String>>(websitesJson, websitesToken)
|
||||
?: ArrayList(1)
|
||||
|
||||
val contact = Contact(id, prefix, firstName, middleName, surname, suffix, "", phoneNumbers, emails, addresses, events,
|
||||
SMT_PRIVATE, starred, id, "", photo, notes, groups, organization, websites)
|
||||
val contact = Contact(id, prefix, firstName, middleName, surname, suffix, nickname, "", phoneNumbers, emails, addresses,
|
||||
events, SMT_PRIVATE, starred, id, "", photo, notes, groups, organization, websites)
|
||||
contacts.add(contact)
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,30 @@
|
||||
package com.simplemobiletools.contacts.helpers
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.provider.ContactsContract.CommonDataKinds
|
||||
import android.provider.MediaStore
|
||||
import android.util.Base64
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.extensions.getFileOutputStream
|
||||
import com.simplemobiletools.commons.extensions.showErrorToast
|
||||
import com.simplemobiletools.commons.extensions.toFileDirItem
|
||||
import com.simplemobiletools.commons.extensions.toast
|
||||
import com.simplemobiletools.contacts.R
|
||||
import com.simplemobiletools.contacts.extensions.getByteArray
|
||||
import com.simplemobiletools.contacts.extensions.getDateTimeFromDateString
|
||||
import com.simplemobiletools.contacts.helpers.VcfExporter.ExportResult.EXPORT_FAIL
|
||||
import com.simplemobiletools.contacts.models.Contact
|
||||
import java.io.BufferedWriter
|
||||
import java.io.ByteArrayOutputStream
|
||||
import ezvcard.Ezvcard
|
||||
import ezvcard.VCard
|
||||
import ezvcard.parameter.AddressType
|
||||
import ezvcard.parameter.EmailType
|
||||
import ezvcard.parameter.ImageType
|
||||
import ezvcard.parameter.TelephoneType
|
||||
import ezvcard.property.*
|
||||
import ezvcard.util.PartialDate
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class VcfExporter {
|
||||
private val ENCODED_PHOTO_LINE_LENGTH = 74
|
||||
|
||||
enum class ExportResult {
|
||||
EXPORT_FAIL, EXPORT_OK, EXPORT_PARTIAL
|
||||
}
|
||||
@ -36,61 +44,93 @@ class VcfExporter {
|
||||
activity.toast(R.string.exporting)
|
||||
}
|
||||
|
||||
it.bufferedWriter().use { out ->
|
||||
for (contact in contacts) {
|
||||
out.writeLn(BEGIN_VCARD)
|
||||
out.writeLn(VERSION_2_1)
|
||||
out.writeLn("$N${getNames(contact)}")
|
||||
val cards = ArrayList<VCard>()
|
||||
for (contact in contacts) {
|
||||
val card = VCard()
|
||||
StructuredName().apply {
|
||||
prefixes.add(contact.prefix)
|
||||
given = contact.firstName
|
||||
additionalNames.add(contact.middleName)
|
||||
family = contact.surname
|
||||
suffixes.add(contact.suffix)
|
||||
card.structuredName = this
|
||||
}
|
||||
|
||||
contact.phoneNumbers.forEach {
|
||||
out.writeLn("$TEL;${getPhoneNumberLabel(it.type)}:${it.value}")
|
||||
}
|
||||
if (contact.nickname.isNotEmpty()) {
|
||||
card.setNickname(contact.nickname)
|
||||
}
|
||||
|
||||
contact.emails.forEach {
|
||||
val type = getEmailTypeLabel(it.type)
|
||||
val delimiterType = if (type.isEmpty()) "" else ";$type"
|
||||
out.writeLn("$EMAIL$delimiterType:${it.value}")
|
||||
}
|
||||
contact.phoneNumbers.forEach {
|
||||
val phoneNumber = Telephone(it.value)
|
||||
phoneNumber.types.add(TelephoneType.find(getPhoneNumberLabel(it.type)))
|
||||
card.addTelephoneNumber(phoneNumber)
|
||||
}
|
||||
|
||||
contact.addresses.forEach {
|
||||
val type = getAddressTypeLabel(it.type)
|
||||
val delimiterType = if (type.isEmpty()) "" else ";$type"
|
||||
out.writeLn("$ADR$delimiterType:;;${it.value.replace("\n", "\\n")};;;;")
|
||||
}
|
||||
contact.emails.forEach {
|
||||
val email = Email(it.value)
|
||||
email.types.add(EmailType.find(getEmailTypeLabel(it.type)))
|
||||
card.addEmail(email)
|
||||
}
|
||||
|
||||
contact.events.forEach {
|
||||
if (it.type == CommonDataKinds.Event.TYPE_BIRTHDAY) {
|
||||
out.writeLn("$BDAY${it.value}")
|
||||
contact.events.forEach {
|
||||
if (it.type == CommonDataKinds.Event.TYPE_BIRTHDAY || it.type == CommonDataKinds.Event.TYPE_ANNIVERSARY) {
|
||||
val dateTime = it.value.getDateTimeFromDateString()
|
||||
if (it.value.startsWith("--")) {
|
||||
val partialDate = PartialDate.builder().year(null).month(dateTime.monthOfYear - 1).date(dateTime.dayOfMonth).build()
|
||||
if (it.type == CommonDataKinds.Event.TYPE_BIRTHDAY) {
|
||||
card.birthdays.add(Birthday(partialDate))
|
||||
} else {
|
||||
card.anniversaries.add(Anniversary(partialDate))
|
||||
}
|
||||
} else {
|
||||
Calendar.getInstance().apply {
|
||||
clear()
|
||||
set(Calendar.YEAR, dateTime.year)
|
||||
set(Calendar.MONTH, dateTime.monthOfYear - 1)
|
||||
set(Calendar.DAY_OF_MONTH, dateTime.dayOfMonth)
|
||||
if (it.type == CommonDataKinds.Event.TYPE_BIRTHDAY) {
|
||||
card.birthdays.add(Birthday(time))
|
||||
} else {
|
||||
card.anniversaries.add(Anniversary(time))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (contact.notes.isNotEmpty()) {
|
||||
out.writeLn("$NOTE${contact.notes.replace("\n", "\\n")}")
|
||||
}
|
||||
|
||||
if (!contact.organization.isEmpty()) {
|
||||
out.writeLn("$ORG${contact.organization.company.replace("\n", "\\n")}")
|
||||
out.writeLn("$TITLE${contact.organization.jobPosition.replace("\n", "\\n")}")
|
||||
}
|
||||
|
||||
contact.websites.forEach {
|
||||
out.writeLn("$URL$it")
|
||||
}
|
||||
|
||||
if (contact.thumbnailUri.isNotEmpty()) {
|
||||
val bitmap = MediaStore.Images.Media.getBitmap(activity.contentResolver, Uri.parse(contact.thumbnailUri))
|
||||
addBitmap(bitmap, out)
|
||||
}
|
||||
|
||||
if (contact.photo != null) {
|
||||
addBitmap(contact.photo!!, out)
|
||||
}
|
||||
|
||||
out.writeLn(END_VCARD)
|
||||
contactsExported++
|
||||
}
|
||||
|
||||
contact.addresses.forEach {
|
||||
val address = Address()
|
||||
address.streetAddress = it.value
|
||||
address.types.add(AddressType.find(getAddressTypeLabel(it.type)))
|
||||
card.addAddress(address)
|
||||
}
|
||||
|
||||
if (contact.notes.isNotEmpty()) {
|
||||
card.addNote(contact.notes)
|
||||
}
|
||||
|
||||
if (!contact.organization.isEmpty()) {
|
||||
val organization = Organization()
|
||||
organization.values.add(contact.organization.company)
|
||||
card.organization = organization
|
||||
card.titles.add(Title(contact.organization.jobPosition))
|
||||
}
|
||||
|
||||
contact.websites.forEach {
|
||||
card.addUrl(it)
|
||||
}
|
||||
|
||||
if (contact.thumbnailUri.isNotEmpty()) {
|
||||
val photoByteArray = MediaStore.Images.Media.getBitmap(activity.contentResolver, Uri.parse(contact.thumbnailUri)).getByteArray()
|
||||
val photo = Photo(photoByteArray, ImageType.JPEG)
|
||||
card.addPhoto(photo)
|
||||
}
|
||||
|
||||
cards.add(card)
|
||||
contactsExported++
|
||||
}
|
||||
|
||||
Ezvcard.write(cards).go(file)
|
||||
} catch (e: Exception) {
|
||||
activity.showErrorToast(e)
|
||||
}
|
||||
@ -103,71 +143,24 @@ class VcfExporter {
|
||||
}
|
||||
}
|
||||
|
||||
private fun addBitmap(bitmap: Bitmap, out: BufferedWriter) {
|
||||
val firstLine = "$PHOTO;$ENCODING=$BASE64;$JPEG:"
|
||||
val byteArrayOutputStream = ByteArrayOutputStream()
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 85, byteArrayOutputStream)
|
||||
bitmap.recycle()
|
||||
val byteArray = byteArrayOutputStream.toByteArray()
|
||||
val encoded = Base64.encodeToString(byteArray, Base64.NO_WRAP)
|
||||
|
||||
val encodedFirstLineSection = encoded.substring(0, ENCODED_PHOTO_LINE_LENGTH - firstLine.length)
|
||||
out.writeLn(firstLine + encodedFirstLineSection)
|
||||
var curStartIndex = encodedFirstLineSection.length
|
||||
do {
|
||||
val part = encoded.substring(curStartIndex, Math.min(curStartIndex + ENCODED_PHOTO_LINE_LENGTH - 1, encoded.length))
|
||||
out.writeLn(" $part")
|
||||
curStartIndex += ENCODED_PHOTO_LINE_LENGTH - 1
|
||||
} while (curStartIndex < encoded.length)
|
||||
|
||||
out.writeLn("")
|
||||
}
|
||||
|
||||
private fun getNames(contact: Contact): String {
|
||||
var result = ""
|
||||
var firstName = contact.firstName
|
||||
var surName = contact.surname
|
||||
var middleName = contact.middleName
|
||||
var prefix = contact.prefix
|
||||
var suffix = contact.suffix
|
||||
|
||||
if (QuotedPrintable.urlEncode(firstName) != firstName
|
||||
|| QuotedPrintable.urlEncode(surName) != surName
|
||||
|| QuotedPrintable.urlEncode(middleName) != middleName
|
||||
|| QuotedPrintable.urlEncode(prefix) != prefix
|
||||
|| QuotedPrintable.urlEncode(suffix) != suffix) {
|
||||
firstName = QuotedPrintable.encode(firstName)
|
||||
surName = QuotedPrintable.encode(surName)
|
||||
middleName = QuotedPrintable.encode(middleName)
|
||||
prefix = QuotedPrintable.encode(prefix)
|
||||
suffix = QuotedPrintable.encode(suffix)
|
||||
result += ";CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE"
|
||||
}
|
||||
|
||||
return "$result:$surName;$firstName;$middleName;$prefix;$suffix"
|
||||
}
|
||||
|
||||
private fun getPhoneNumberLabel(type: Int) = when (type) {
|
||||
CommonDataKinds.Phone.TYPE_MOBILE -> CELL
|
||||
CommonDataKinds.Phone.TYPE_HOME -> HOME
|
||||
CommonDataKinds.Phone.TYPE_WORK -> WORK
|
||||
CommonDataKinds.Phone.TYPE_MAIN -> PREF
|
||||
CommonDataKinds.Phone.TYPE_FAX_WORK -> WORK_FAX
|
||||
CommonDataKinds.Phone.TYPE_FAX_HOME -> HOME_FAX
|
||||
CommonDataKinds.Phone.TYPE_PAGER -> PAGER
|
||||
else -> VOICE
|
||||
else -> HOME
|
||||
}
|
||||
|
||||
private fun getEmailTypeLabel(type: Int) = when (type) {
|
||||
CommonDataKinds.Email.TYPE_HOME -> HOME
|
||||
CommonDataKinds.Email.TYPE_WORK -> WORK
|
||||
CommonDataKinds.Email.TYPE_MOBILE -> MOBILE
|
||||
else -> ""
|
||||
else -> HOME
|
||||
}
|
||||
|
||||
private fun getAddressTypeLabel(type: Int) = when (type) {
|
||||
CommonDataKinds.StructuredPostal.TYPE_HOME -> HOME
|
||||
CommonDataKinds.StructuredPostal.TYPE_WORK -> WORK
|
||||
else -> ""
|
||||
else -> HOME
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package com.simplemobiletools.contacts.helpers
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.provider.ContactsContract.CommonDataKinds
|
||||
import android.util.Base64
|
||||
import android.widget.Toast
|
||||
import com.simplemobiletools.commons.extensions.showErrorToast
|
||||
import com.simplemobiletools.contacts.activities.SimpleActivity
|
||||
@ -11,40 +10,19 @@ import com.simplemobiletools.contacts.extensions.getCachePhoto
|
||||
import com.simplemobiletools.contacts.extensions.getCachePhotoUri
|
||||
import com.simplemobiletools.contacts.helpers.VcfImporter.ImportResult.*
|
||||
import com.simplemobiletools.contacts.models.*
|
||||
import ezvcard.Ezvcard
|
||||
import org.joda.time.DateTime
|
||||
import org.joda.time.format.DateTimeFormat
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.util.*
|
||||
|
||||
class VcfImporter(val activity: SimpleActivity) {
|
||||
enum class ImportResult {
|
||||
IMPORT_FAIL, IMPORT_OK, IMPORT_PARTIAL
|
||||
}
|
||||
|
||||
private var curPrefix = ""
|
||||
private var curFirstName = ""
|
||||
private var curMiddleName = ""
|
||||
private var curSurname = ""
|
||||
private var curSuffix = ""
|
||||
private var curPhotoUri = ""
|
||||
private var curNotes = ""
|
||||
private var curCompany = ""
|
||||
private var curJobPosition = ""
|
||||
private var curPhoneNumbers = ArrayList<PhoneNumber>()
|
||||
private var curEmails = ArrayList<Email>()
|
||||
private var curEvents = ArrayList<Event>()
|
||||
private var curAddresses = ArrayList<Address>()
|
||||
private var curGroups = ArrayList<Group>()
|
||||
private var curWebsites = ArrayList<String>()
|
||||
|
||||
private var isGettingPhoto = false
|
||||
private var currentPhotoString = StringBuilder()
|
||||
private var currentPhotoCompressionFormat = Bitmap.CompressFormat.JPEG
|
||||
|
||||
private var isGettingName = false
|
||||
private var currentNameIsANSI = false
|
||||
private var currentNameString = StringBuilder()
|
||||
|
||||
private var isGettingNotes = false
|
||||
private var currentNotesSB = StringBuilder()
|
||||
private val PATTERN = "EEE MMM dd HH:mm:ss 'GMT'ZZ YYYY"
|
||||
|
||||
private var contactsImported = 0
|
||||
private var contactsFailed = 0
|
||||
@ -57,45 +35,70 @@ class VcfImporter(val activity: SimpleActivity) {
|
||||
activity.assets.open(path)
|
||||
}
|
||||
|
||||
inputStream.bufferedReader().use {
|
||||
while (true) {
|
||||
val line = it.readLine() ?: break
|
||||
if (line.trim().isEmpty()) {
|
||||
if (isGettingPhoto) {
|
||||
savePhoto()
|
||||
isGettingPhoto = false
|
||||
}
|
||||
continue
|
||||
} else if (line.startsWith('\t') && isGettingName) {
|
||||
currentNameString.append(line.trimStart('\t'))
|
||||
isGettingName = false
|
||||
parseNames()
|
||||
} else if (isGettingNotes) {
|
||||
if (line.startsWith(' ')) {
|
||||
currentNotesSB.append(line.substring(1))
|
||||
} else {
|
||||
curNotes = currentNotesSB.toString().replace("\\n", "\n").replace("\\,", ",")
|
||||
isGettingNotes = false
|
||||
}
|
||||
}
|
||||
val ezContacts = Ezvcard.parse(inputStream).all()
|
||||
for (ezContact in ezContacts) {
|
||||
val structuredName = ezContact.structuredName
|
||||
val prefix = structuredName?.prefixes?.firstOrNull() ?: ""
|
||||
val firstName = structuredName?.given ?: ""
|
||||
val middleName = structuredName?.additionalNames?.firstOrNull() ?: ""
|
||||
val surname = structuredName?.family ?: ""
|
||||
val suffix = structuredName?.suffixes?.firstOrNull() ?: ""
|
||||
val nickname = ezContact.nickname?.values?.firstOrNull() ?: ""
|
||||
val photoUri = ""
|
||||
|
||||
when {
|
||||
line.toUpperCase() == BEGIN_VCARD -> resetValues()
|
||||
line.toUpperCase().startsWith(NOTE) -> addNotes(line.substring(NOTE.length))
|
||||
line.toUpperCase().startsWith(N) -> addNames(line.substring(N.length))
|
||||
line.toUpperCase().startsWith(TEL) -> addPhoneNumber(line.substring(TEL.length))
|
||||
line.toUpperCase().startsWith(EMAIL) -> addEmail(line.substring(EMAIL.length))
|
||||
line.toUpperCase().startsWith(ADR) -> addAddress(line.substring(ADR.length))
|
||||
line.toUpperCase().startsWith(BDAY) -> addBirthday(line.substring(BDAY.length))
|
||||
line.toUpperCase().startsWith(ANNIVERSARY) -> addAnniversary(line.substring(ANNIVERSARY.length))
|
||||
line.toUpperCase().startsWith(PHOTO) -> addPhoto(line.substring(PHOTO.length))
|
||||
line.toUpperCase().startsWith(ORG) -> addCompany(line.substring(ORG.length))
|
||||
line.toUpperCase().startsWith(TITLE) -> addJobPosition(line.substring(TITLE.length))
|
||||
line.toUpperCase().startsWith(URL) -> addWebsite(line.substring(URL.length))
|
||||
line.toUpperCase() == END_VCARD -> saveContact(targetContactSource)
|
||||
isGettingPhoto -> currentPhotoString.append(line.trim())
|
||||
val phoneNumbers = ArrayList<PhoneNumber>()
|
||||
ezContact.telephoneNumbers.forEach {
|
||||
val type = getPhoneNumberTypeId(it.types.firstOrNull()?.value ?: MOBILE)
|
||||
val number = it.text
|
||||
phoneNumbers.add(PhoneNumber(number, type))
|
||||
}
|
||||
|
||||
val emails = ArrayList<Email>()
|
||||
ezContact.emails.forEach {
|
||||
val type = getEmailTypeId(it.types.firstOrNull()?.value ?: HOME)
|
||||
val email = it.value
|
||||
emails.add(Email(email, type))
|
||||
}
|
||||
|
||||
val addresses = ArrayList<Address>()
|
||||
ezContact.addresses.forEach {
|
||||
val type = getAddressTypeId(it.types.firstOrNull()?.value ?: HOME)
|
||||
val address = it.streetAddress
|
||||
if (address?.isNotEmpty() == true) {
|
||||
addresses.add(Address(address, type))
|
||||
}
|
||||
}
|
||||
|
||||
val events = ArrayList<Event>()
|
||||
ezContact.birthdays.forEach {
|
||||
val event = Event(formatDateToDayCode(it.date), CommonDataKinds.Event.TYPE_BIRTHDAY)
|
||||
events.add(event)
|
||||
}
|
||||
|
||||
ezContact.anniversaries.forEach {
|
||||
val event = Event(formatDateToDayCode(it.date), CommonDataKinds.Event.TYPE_ANNIVERSARY)
|
||||
events.add(event)
|
||||
}
|
||||
|
||||
val starred = 0
|
||||
val contactId = 0
|
||||
val notes = ezContact.notes.firstOrNull()?.value ?: ""
|
||||
val groups = ArrayList<Group>()
|
||||
val company = ezContact.organization?.values?.firstOrNull() ?: ""
|
||||
val jobPosition = ezContact.titles?.firstOrNull()?.value ?: ""
|
||||
val organization = Organization(company, jobPosition)
|
||||
val websites = ezContact.urls.map { it.value } as ArrayList<String>
|
||||
|
||||
val photoData = ezContact.photos.firstOrNull()?.data
|
||||
val photo = null
|
||||
val thumbnailUri = savePhoto(photoData)
|
||||
|
||||
val contact = Contact(0, prefix, firstName, middleName, surname, suffix, nickname, photoUri, phoneNumbers, emails, addresses, events,
|
||||
targetContactSource, starred, contactId, thumbnailUri, photo, notes, groups, organization, websites)
|
||||
|
||||
if (ContactsHelper(activity).insertContact(contact)) {
|
||||
contactsImported++
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
activity.showErrorToast(e, Toast.LENGTH_LONG)
|
||||
@ -109,188 +112,51 @@ class VcfImporter(val activity: SimpleActivity) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun addNames(names: String) {
|
||||
val parts = names.split(":")
|
||||
currentNameIsANSI = parts.first().toUpperCase().contains("QUOTED-PRINTABLE")
|
||||
currentNameString.append(parts[1].trimEnd('='))
|
||||
if (!isGettingName && currentNameIsANSI && names.endsWith('=')) {
|
||||
isGettingName = true
|
||||
} else {
|
||||
parseNames()
|
||||
}
|
||||
private fun formatDateToDayCode(date: Date): String {
|
||||
val dateTime = DateTime.parse(date.toString(), DateTimeFormat.forPattern(PATTERN))
|
||||
return dateTime.toString("yyyy-MM-dd")
|
||||
}
|
||||
|
||||
private fun parseNames() {
|
||||
val nameParts = currentNameString.split(";")
|
||||
curSurname = if (currentNameIsANSI) QuotedPrintable.decode(nameParts[0]) else nameParts[0]
|
||||
curFirstName = if (currentNameIsANSI) QuotedPrintable.decode(nameParts[1]) else nameParts[1]
|
||||
if (nameParts.size > 2) {
|
||||
curMiddleName = if (currentNameIsANSI) QuotedPrintable.decode(nameParts[2]) else nameParts[2]
|
||||
curPrefix = if (currentNameIsANSI) QuotedPrintable.decode(nameParts[3]) else nameParts[3]
|
||||
curSuffix = if (currentNameIsANSI) QuotedPrintable.decode(nameParts[4]) else nameParts[4]
|
||||
}
|
||||
}
|
||||
|
||||
private fun addPhoneNumber(phoneNumber: String) {
|
||||
val phoneParts = phoneNumber.trimStart(';').split(":")
|
||||
var rawType = phoneParts[0]
|
||||
var subType = ""
|
||||
if (rawType.contains('=')) {
|
||||
val types = rawType.split('=')
|
||||
if (types.any { it.contains(';') }) {
|
||||
subType = types[1].split(';')[0]
|
||||
}
|
||||
rawType = types.last()
|
||||
}
|
||||
|
||||
val type = getPhoneNumberTypeId(rawType.toUpperCase(), subType)
|
||||
val value = phoneParts[1]
|
||||
curPhoneNumbers.add(PhoneNumber(value, type))
|
||||
}
|
||||
|
||||
private fun getPhoneNumberTypeId(type: String, subType: String) = when (type) {
|
||||
private fun getPhoneNumberTypeId(type: String) = when (type.toUpperCase()) {
|
||||
CELL -> CommonDataKinds.Phone.TYPE_MOBILE
|
||||
HOME -> CommonDataKinds.Phone.TYPE_HOME
|
||||
WORK -> CommonDataKinds.Phone.TYPE_WORK
|
||||
PREF, MAIN -> CommonDataKinds.Phone.TYPE_MAIN
|
||||
WORK_FAX -> CommonDataKinds.Phone.TYPE_FAX_WORK
|
||||
HOME_FAX -> CommonDataKinds.Phone.TYPE_FAX_HOME
|
||||
FAX -> if (subType == WORK) CommonDataKinds.Phone.TYPE_FAX_WORK else CommonDataKinds.Phone.TYPE_FAX_HOME
|
||||
FAX -> CommonDataKinds.Phone.TYPE_FAX_WORK
|
||||
PAGER -> CommonDataKinds.Phone.TYPE_PAGER
|
||||
else -> CommonDataKinds.Phone.TYPE_OTHER
|
||||
}
|
||||
|
||||
private fun addEmail(email: String) {
|
||||
val emailParts = email.trimStart(';').split(":")
|
||||
var rawType = emailParts[0]
|
||||
if (rawType.contains('=')) {
|
||||
rawType = rawType.split('=').last()
|
||||
}
|
||||
val type = getEmailTypeId(rawType.toUpperCase())
|
||||
val value = emailParts[1]
|
||||
curEmails.add(Email(value, type))
|
||||
}
|
||||
|
||||
private fun getEmailTypeId(type: String) = when (type) {
|
||||
private fun getEmailTypeId(type: String) = when (type.toUpperCase()) {
|
||||
HOME -> CommonDataKinds.Email.TYPE_HOME
|
||||
WORK -> CommonDataKinds.Email.TYPE_WORK
|
||||
MOBILE -> CommonDataKinds.Email.TYPE_MOBILE
|
||||
else -> CommonDataKinds.Email.TYPE_OTHER
|
||||
}
|
||||
|
||||
private fun addAddress(address: String) {
|
||||
val addressParts = address.trimStart(';').split(":")
|
||||
var rawType = addressParts[0]
|
||||
if (rawType.contains('=')) {
|
||||
rawType = rawType.split('=').last()
|
||||
}
|
||||
val type = getAddressTypeId(rawType.toUpperCase())
|
||||
val addresses = addressParts[1].split(";")
|
||||
if (addresses.size == 7) {
|
||||
curAddresses.add(Address(addresses[2].replace("\\n", "\n"), type))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAddressTypeId(type: String) = when (type) {
|
||||
private fun getAddressTypeId(type: String) = when (type.toUpperCase()) {
|
||||
HOME -> CommonDataKinds.Email.TYPE_HOME
|
||||
WORK -> CommonDataKinds.Email.TYPE_WORK
|
||||
else -> CommonDataKinds.Email.TYPE_OTHER
|
||||
}
|
||||
|
||||
private fun addBirthday(birthday: String) {
|
||||
curEvents.add(Event(birthday, CommonDataKinds.Event.TYPE_BIRTHDAY))
|
||||
}
|
||||
|
||||
private fun addAnniversary(anniversary: String) {
|
||||
curEvents.add(Event(anniversary, CommonDataKinds.Event.TYPE_ANNIVERSARY))
|
||||
}
|
||||
|
||||
private fun addPhoto(photo: String) {
|
||||
val photoParts = photo.trimStart(';').split(';')
|
||||
if (photoParts.size == 2) {
|
||||
val typeParts = photoParts[1].split(':')
|
||||
currentPhotoCompressionFormat = getPhotoCompressionFormat(typeParts[0])
|
||||
val encoding = photoParts[0].split('=').last()
|
||||
if (encoding == BASE64) {
|
||||
isGettingPhoto = true
|
||||
currentPhotoString.append(typeParts[1].trim())
|
||||
}
|
||||
private fun savePhoto(byteArray: ByteArray?): String {
|
||||
if (byteArray == null) {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPhotoCompressionFormat(type: String) = when (type.toLowerCase()) {
|
||||
"png" -> Bitmap.CompressFormat.PNG
|
||||
"webp" -> Bitmap.CompressFormat.WEBP
|
||||
else -> Bitmap.CompressFormat.JPEG
|
||||
}
|
||||
|
||||
private fun savePhoto() {
|
||||
val file = activity.getCachePhoto()
|
||||
val imageAsBytes = Base64.decode(currentPhotoString.toString().toByteArray(), Base64.DEFAULT)
|
||||
val bitmap = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.size)
|
||||
val bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size)
|
||||
var fileOutputStream: FileOutputStream? = null
|
||||
try {
|
||||
fileOutputStream = FileOutputStream(file)
|
||||
bitmap.compress(currentPhotoCompressionFormat, 100, fileOutputStream)
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream)
|
||||
} finally {
|
||||
fileOutputStream?.close()
|
||||
}
|
||||
|
||||
curPhotoUri = activity.getCachePhotoUri(file).toString()
|
||||
}
|
||||
|
||||
private fun addNotes(notes: String) {
|
||||
currentNotesSB.append(notes)
|
||||
isGettingNotes = true
|
||||
}
|
||||
|
||||
private fun addCompany(company: String) {
|
||||
curCompany = company
|
||||
}
|
||||
|
||||
private fun addJobPosition(jobPosition: String) {
|
||||
curJobPosition = jobPosition
|
||||
}
|
||||
|
||||
private fun addWebsite(website: String) {
|
||||
curWebsites.add(website)
|
||||
}
|
||||
|
||||
private fun saveContact(source: String) {
|
||||
val organization = Organization(curCompany, curJobPosition)
|
||||
val contact = Contact(0, curPrefix, curFirstName, curMiddleName, curSurname, curSuffix, curPhotoUri, curPhoneNumbers, curEmails, curAddresses, curEvents,
|
||||
source, 0, 0, "", null, curNotes, curGroups, organization, curWebsites)
|
||||
if (ContactsHelper(activity).insertContact(contact)) {
|
||||
contactsImported++
|
||||
}
|
||||
}
|
||||
|
||||
private fun resetValues() {
|
||||
curPrefix = ""
|
||||
curFirstName = ""
|
||||
curMiddleName = ""
|
||||
curSurname = ""
|
||||
curSuffix = ""
|
||||
curPhotoUri = ""
|
||||
curNotes = ""
|
||||
curCompany = ""
|
||||
curJobPosition = ""
|
||||
curPhoneNumbers = ArrayList()
|
||||
curEmails = ArrayList()
|
||||
curEvents = ArrayList()
|
||||
curAddresses = ArrayList()
|
||||
curGroups = ArrayList()
|
||||
curWebsites = ArrayList()
|
||||
|
||||
isGettingPhoto = false
|
||||
currentPhotoString = StringBuilder()
|
||||
currentPhotoCompressionFormat = Bitmap.CompressFormat.JPEG
|
||||
|
||||
isGettingName = false
|
||||
currentNameIsANSI = false
|
||||
currentNameString = StringBuilder()
|
||||
|
||||
isGettingNotes = false
|
||||
currentNotesSB = StringBuilder()
|
||||
return activity.getCachePhotoUri(file).toString()
|
||||
}
|
||||
}
|
||||
|
@ -1,39 +1,48 @@
|
||||
package com.simplemobiletools.contacts.models
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import com.simplemobiletools.commons.extensions.normalizeString
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_FIRST_NAME
|
||||
import com.simplemobiletools.commons.helpers.SORT_BY_MIDDLE_NAME
|
||||
import com.simplemobiletools.commons.helpers.SORT_DESCENDING
|
||||
import com.simplemobiletools.contacts.helpers.PHONE_NUMBER_PATTERN
|
||||
|
||||
data class Contact(val id: Int, var prefix: String, var firstName: String, var middleName: String, var surname: String, var suffix: String, var photoUri: String,
|
||||
var phoneNumbers: ArrayList<PhoneNumber>, var emails: ArrayList<Email>, var addresses: ArrayList<Address>, var events: ArrayList<Event>,
|
||||
var source: String, var starred: Int, val contactId: Int, val thumbnailUri: String, var photo: Bitmap?, var notes: String,
|
||||
data class Contact(val 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<PhoneNumber>, var emails: ArrayList<Email>, var addresses: ArrayList<Address>,
|
||||
var events: ArrayList<Event>, var source: String, var starred: Int, val contactId: Int, val thumbnailUri: String, var photo: Bitmap?, var notes: String,
|
||||
var groups: ArrayList<Group>, var organization: Organization, var websites: ArrayList<String>) : Comparable<Contact> {
|
||||
companion object {
|
||||
var sorting = 0
|
||||
var startWithSurname = false
|
||||
val pattern = "\\D+".toRegex()
|
||||
}
|
||||
|
||||
override fun compareTo(other: Contact): Int {
|
||||
val firstString: String
|
||||
val secondString: String
|
||||
var firstString: String
|
||||
var secondString: String
|
||||
|
||||
when {
|
||||
sorting and SORT_BY_FIRST_NAME != 0 -> {
|
||||
firstString = firstName
|
||||
secondString = other.firstName
|
||||
firstString = firstName.normalizeString()
|
||||
secondString = other.firstName.normalizeString()
|
||||
}
|
||||
sorting and SORT_BY_MIDDLE_NAME != 0 -> {
|
||||
firstString = middleName
|
||||
secondString = other.middleName
|
||||
firstString = middleName.normalizeString()
|
||||
secondString = other.middleName.normalizeString()
|
||||
}
|
||||
else -> {
|
||||
firstString = surname
|
||||
secondString = other.surname
|
||||
firstString = surname.normalizeString()
|
||||
secondString = other.surname.normalizeString()
|
||||
}
|
||||
}
|
||||
|
||||
if (firstString.isEmpty() && firstName.isEmpty() && middleName.isEmpty() && surname.isEmpty() && organization.company.isNotEmpty()) {
|
||||
firstString = organization.company.normalizeString()
|
||||
}
|
||||
|
||||
if (secondString.isEmpty() && other.firstName.isEmpty() && other.middleName.isEmpty() && other.surname.isEmpty() && other.organization.company.isNotEmpty()) {
|
||||
secondString = other.organization.company.normalizeString()
|
||||
}
|
||||
|
||||
var result = if (firstString.firstOrNull()?.isLetter() == true && secondString.firstOrNull()?.isLetter() == false) {
|
||||
-1
|
||||
} else if (firstString.firstOrNull()?.isLetter() == false && secondString.firstOrNull()?.isLetter() == true) {
|
||||
@ -45,9 +54,9 @@ data class Contact(val id: Int, var prefix: String, var firstName: String, var m
|
||||
-1
|
||||
} else {
|
||||
if (firstString.toLowerCase() == secondString.toLowerCase()) {
|
||||
getFullName().compareTo(other.getFullName())
|
||||
getFullName().compareTo(other.getFullName(), true)
|
||||
} else {
|
||||
firstString.toLowerCase().compareTo(secondString.toLowerCase())
|
||||
firstString.compareTo(secondString, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,8 +94,13 @@ data class Contact(val id: Int, var prefix: String, var firstName: String, var m
|
||||
|
||||
fun getHashToCompare(): Int {
|
||||
val newPhoneNumbers = ArrayList<PhoneNumber>()
|
||||
phoneNumbers.mapTo(newPhoneNumbers, { PhoneNumber(it.value.replace(pattern, ""), 0) })
|
||||
return copy(id = 0, prefix = "", firstName = getFullName().toLowerCase(), middleName = "", surname = "", suffix = "", photoUri = "",
|
||||
phoneNumbers = newPhoneNumbers, source = "", starred = 0, contactId = 0, thumbnailUri = "", notes = "").hashCode()
|
||||
phoneNumbers.mapTo(newPhoneNumbers) { PhoneNumber(it.value.replace(PHONE_NUMBER_PATTERN.toRegex(), ""), 0) }
|
||||
|
||||
val newEmails = ArrayList<Email>()
|
||||
emails.mapTo(newEmails) { Email(it.value, 0) }
|
||||
|
||||
return copy(id = 0, prefix = "", firstName = getFullName().toLowerCase(), middleName = "", surname = "", suffix = "", nickname = "", photoUri = "",
|
||||
phoneNumbers = newPhoneNumbers, events = ArrayList(), addresses = ArrayList(), emails = newEmails, source = "", starred = 0,
|
||||
contactId = 0, thumbnailUri = "", notes = "", groups = ArrayList(), websites = ArrayList(), organization = Organization("", "")).hashCode()
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,3 @@
|
||||
package com.simplemobiletools.contacts.models
|
||||
|
||||
data class RecentCall(var id: Int, var number: String, var dateTime: String, var name: String?)
|
14
app/src/main/res/anim/pulsing_animation.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<scale
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="1000"
|
||||
android:fillAfter="false"
|
||||
android:fromXScale="1.0"
|
||||
android:fromYScale="1.0"
|
||||
android:interpolator="@android:anim/accelerate_interpolator"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%"
|
||||
android:repeatCount="infinite"
|
||||
android:repeatMode="reverse"
|
||||
android:toXScale="1.2"
|
||||
android:toYScale="1.2"/>
|
BIN
app/src/main/res/drawable-hdpi/ic_clock.png
Normal file
After Width: | Height: | Size: 487 B |
BIN
app/src/main/res/drawable-hdpi/ic_phone_big.png
Normal file
After Width: | Height: | Size: 566 B |
BIN
app/src/main/res/drawable-xhdpi/ic_clock.png
Normal file
After Width: | Height: | Size: 655 B |
BIN
app/src/main/res/drawable-xhdpi/ic_phone_big.png
Normal file
After Width: | Height: | Size: 716 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_clock.png
Normal file
After Width: | Height: | Size: 947 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_phone_big.png
Normal file
After Width: | Height: | Size: 993 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_clock.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_phone_big.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
@ -170,6 +170,22 @@
|
||||
android:textCursorDrawable="@null"
|
||||
android:textSize="@dimen/bigger_text_size"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyEditText
|
||||
android:id="@+id/contact_nickname"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/contact_suffix"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginBottom="@dimen/medium_margin"
|
||||
android:layout_toRightOf="@+id/contact_name_image"
|
||||
android:hint="@string/nickname"
|
||||
android:inputType="textCapWords"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:textCursorDrawable="@null"
|
||||
android:textSize="@dimen/bigger_text_size"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/contact_numbers_image"
|
||||
android:layout_width="@dimen/contact_icons_size"
|
||||
@ -185,7 +201,7 @@
|
||||
android:id="@+id/contact_numbers_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/contact_suffix"
|
||||
android:layout_below="@+id/contact_nickname"
|
||||
android:layout_marginBottom="@dimen/small_margin"
|
||||
android:layout_toRightOf="@+id/contact_numbers_image"
|
||||
android:orientation="vertical">
|
||||
|
@ -14,27 +14,7 @@
|
||||
app:tabIndicatorColor="@android:color/white"
|
||||
app:tabIndicatorHeight="2dp"
|
||||
app:tabMinWidth="150dp"
|
||||
app:tabSelectedTextColor="@android:color/white">
|
||||
|
||||
<android.support.design.widget.TabItem
|
||||
android:id="@+id/tab_contacts"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:icon="@drawable/ic_person"/>
|
||||
|
||||
<android.support.design.widget.TabItem
|
||||
android:id="@+id/tab_favorites"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:icon="@drawable/ic_star_on"/>
|
||||
|
||||
<android.support.design.widget.TabItem
|
||||
android:id="@+id/tab_groups"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:icon="@drawable/ic_group"/>
|
||||
|
||||
</android.support.design.widget.TabLayout>
|
||||
app:tabSelectedTextColor="@android:color/white"/>
|
||||
|
||||
<com.booking.rtlviewpager.RtlViewPager
|
||||
android:id="@+id/viewpager"
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/settings_scrollview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
@ -11,6 +12,28 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_purchase_thank_you_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/settings_purchase_thank_you"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:text="@string/purchase_simple_thank_you"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_customize_colors_holder"
|
||||
android:layout_width="match_parent"
|
||||
@ -55,6 +78,28 @@
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_manage_tabs_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/settings_manage_tabs"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:text="@string/manage_shown_tabs"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_use_english_holder"
|
||||
android:layout_width="match_parent"
|
||||
@ -74,7 +119,8 @@
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:text="@string/use_english_language"/>
|
||||
android:text="@string/use_english_language"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
@ -97,7 +143,8 @@
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:text="@string/avoid_whats_new"/>
|
||||
android:text="@string/avoid_whats_new"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
@ -120,7 +167,8 @@
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:text="@string/show_info_bubble"/>
|
||||
android:text="@string/show_info_bubble"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
@ -143,7 +191,8 @@
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:text="@string/show_contact_thumbnails"/>
|
||||
android:text="@string/show_contact_thumbnails"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
@ -166,7 +215,8 @@
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:text="@string/show_phone_numbers"/>
|
||||
android:text="@string/show_phone_numbers"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
@ -189,7 +239,8 @@
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:text="@string/start_name_with_surname"/>
|
||||
android:text="@string/start_name_with_surname"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
@ -212,7 +263,32 @@
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:text="@string/filter_duplicates"/>
|
||||
android:text="@string/filter_duplicates"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_show_call_confirmation_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MySwitchCompat
|
||||
android:id="@+id/settings_show_call_confirmation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:text="@string/show_call_confirmation_dialog"
|
||||
app:switchPadding="@dimen/medium_margin"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
@ -166,6 +166,21 @@
|
||||
android:singleLine="true"
|
||||
android:textSize="@dimen/bigger_text_size"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/contact_nickname"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/contact_suffix"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toRightOf="@+id/contact_name_image"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:paddingBottom="@dimen/normal_margin"
|
||||
android:paddingLeft="@dimen/small_margin"
|
||||
android:paddingTop="@dimen/normal_margin"
|
||||
android:singleLine="true"
|
||||
android:textSize="@dimen/bigger_text_size"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/contact_numbers_image"
|
||||
android:layout_width="@dimen/contact_icons_size"
|
||||
@ -181,7 +196,7 @@
|
||||
android:id="@+id/contact_numbers_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/contact_suffix"
|
||||
android:layout_below="@+id/contact_nickname"
|
||||
android:layout_toRightOf="@+id/contact_numbers_image"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="@dimen/small_margin"/>
|
||||
|
18
app/src/main/res/layout/dialog_call_confirmation.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/dialog_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/call_confirm_phone"
|
||||
style="@style/MyBorderlessBackgroundStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:padding="@dimen/activity_margin"
|
||||
android:src="@drawable/ic_phone_big"/>
|
||||
|
||||
</RelativeLayout>
|
@ -54,6 +54,14 @@
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/suffix"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_visible_fields_nickname"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/nickname"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_visible_fields_phone_numbers"
|
||||
android:layout_width="match_parent"
|
||||
|
50
app/src/main/res/layout/dialog_manage_visible_tabs.xml
Normal file
@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/manage_visible_tabs_scroll_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/manage_visible_tabs_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_visible_tabs_contacts"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/contacts"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_visible_tabs_favorites"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/favorites"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_visible_tabs_recents"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/recent_calls"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
|
||||
android:id="@+id/manage_visible_tabs_groups"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:text="@string/groups"/>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
10
app/src/main/res/layout/fragment_recents.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.simplemobiletools.contacts.fragments.RecentsFragment
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/recents_fragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<include layout="@layout/fragment_layout"/>
|
||||
|
||||
</com.simplemobiletools.contacts.fragments.RecentsFragment>
|
62
app/src/main/res/layout/item_recent_call.xml
Normal file
@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/recent_call_frame"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="@drawable/selector">
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:id="@+id/recent_call_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/contact_item_height"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/activity_margin">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/recent_call_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:paddingRight="@dimen/activity_margin"
|
||||
android:textSize="@dimen/big_text_size"
|
||||
app:layout_constraintBottom_toTopOf="@+id/recent_call_number"
|
||||
app:layout_constraintEnd_toStartOf="@+id/recent_call_date_time"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="John Doe"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/recent_call_number"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/recent_call_name"
|
||||
android:maxLines="1"
|
||||
android:textSize="@dimen/bigger_text_size"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/recent_call_date_time"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="0123 456 789"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/recent_call_date_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:textSize="@dimen/normal_text_size"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:layout_editor_absoluteY="0dp"
|
||||
tools:text="Yesterday, 17:00"/>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</FrameLayout>
|
@ -3,7 +3,7 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/cab_edit"
|
||||
android:icon="@drawable/ic_rename"
|
||||
android:icon="@drawable/ic_edit"
|
||||
android:title="@string/edit_contact"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
|
@ -2,9 +2,9 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/cab_edit"
|
||||
android:icon="@drawable/ic_rename"
|
||||
android:title="@string/edit_contact"
|
||||
android:id="@+id/cab_rename"
|
||||
android:icon="@drawable/ic_rename_new"
|
||||
android:title="@string/rename"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/cab_select_all"
|
||||
|
14
app/src/main/res/menu/cab_recent_calls.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/cab_delete"
|
||||
android:icon="@drawable/ic_delete"
|
||||
android:title="@string/delete"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/cab_select_all"
|
||||
android:icon="@drawable/ic_select_all"
|
||||
android:title="@string/select_all"
|
||||
app:showAsAction="ifRoom"/>
|
||||
</menu>
|
@ -3,7 +3,7 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/edit"
|
||||
android:icon="@drawable/ic_rename"
|
||||
android:icon="@drawable/ic_edit"
|
||||
android:title="@string/edit_contact"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_orange_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_amber_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_blue_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_blue_grey_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_brown_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_cyan_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_deep_orange_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_deep_purple_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_green_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_grey_black"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_indigo_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_light_blue_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_light_green_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_lime_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_pink_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_purple_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_red_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_teal_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
@ -2,4 +2,4 @@
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/md_yellow_700"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
</adaptive-icon>
|
||||
|
133
app/src/main/res/values-az/strings.xml
Normal file
@ -0,0 +1,133 @@
|
||||
<resources>
|
||||
<string name="app_name">Sadə Kontaktlar</string>
|
||||
<string name="app_launcher_name">Kontaktlar</string>
|
||||
<string name="address">Ünvan</string>
|
||||
<string name="inserting">Daxil edilir…</string>
|
||||
<string name="updating">Yenilənir…</string>
|
||||
<string name="phone_storage">Telefon yaddaşı</string>
|
||||
<string name="phone_storage_hidden">Telefon yaddaşı (digər tətbiqlərə görünmür)</string>
|
||||
<string name="company">Şirkət</string>
|
||||
<string name="job_position">İş vəziyyəti</string>
|
||||
<string name="website">Vebsayt</string>
|
||||
<string name="send_sms_to_contacts">Kontaktlara SMS göndər</string>
|
||||
<string name="send_email_to_contacts">Kontaktlara e-poçt göndər</string>
|
||||
<string name="send_sms_to_group">Grupa SMS göndər</string>
|
||||
<string name="send_email_to_group">Grupa e-poçt göndər</string>
|
||||
<string name="call_person">%s şəxsinə zng et</string>
|
||||
<string name="request_the_required_permissions">Lazım olan icazələri istə</string>
|
||||
|
||||
<string name="new_contact">Yeni kontakt</string>
|
||||
<string name="edit_contact">Redaktə et</string>
|
||||
<string name="select_contact">Kontakt seç</string>
|
||||
<string name="select_contacts">Kontaktları seç</string>
|
||||
<string name="first_name">Ad</string>
|
||||
<string name="middle_name">Orta Ad</string>
|
||||
<string name="surname">Soyad</string>
|
||||
<string name="nickname">Nickname</string>
|
||||
|
||||
<!-- Groups -->
|
||||
<string name="no_groups">Qruplar yoxdur</string>
|
||||
<string name="create_new_group">Yeni qrup yarat</string>
|
||||
<string name="remove_from_group">Qrupdan sil</string>
|
||||
<string name="no_group_participants">Bu qrup boşdur</string>
|
||||
<string name="add_contacts">Kontaktlar əlavə et</string>
|
||||
<string name="no_group_created">Cihazda heçbir kontakt qrupu yoxdur</string>
|
||||
<string name="create_group">Qrup yarat</string>
|
||||
<string name="add_to_group">Qrupa əlavə et</string>
|
||||
<string name="create_group_under_account">Hesab altında qrup yarat</string>
|
||||
|
||||
<!-- Photo -->
|
||||
<string name="take_photo">Şəkil çək</string>
|
||||
<string name="choose_photo">Şəkil seç</string>
|
||||
<string name="remove_photo">Şəkli sil</string>
|
||||
|
||||
<!-- Settings -->
|
||||
<string name="start_name_with_surname">Ada soyaddan başla</string>
|
||||
<string name="show_phone_numbers">Telefon nömrələrini əsas ekranda göstər</string>
|
||||
<string name="show_contact_thumbnails">Kontakt görüntülərini göstər</string>
|
||||
<string name="on_contact_click">Kontakta toxunduqda</string>
|
||||
<string name="call_contact">Kontakta zəng et</string>
|
||||
<string name="view_contact">Kontakt detallarına bax</string>
|
||||
<string name="manage_shown_contact_fields">Göstərilən kontakt sahəsini idarə et</string>
|
||||
<string name="filter_duplicates">Təkrarlanmış kontaktları filtrləməyə çalış</string>
|
||||
<string name="manage_shown_tabs">Göstərilən nişanları idarə et</string>
|
||||
<string name="contacts">Kontaktlar</string>
|
||||
<string name="favorites">Sevimlilər</string>
|
||||
<string name="recent_calls">Hazırki zənglər</string>
|
||||
<string name="show_call_confirmation_dialog">Zəngə başlamazdan əvvəl zəng təsdiq pəncərəsi göstər</string>
|
||||
|
||||
<!-- Emails -->
|
||||
<string name="email">E-poçt</string>
|
||||
<string name="home">Ev</string>
|
||||
<string name="work">İş</string>
|
||||
<string name="other">Başqa</string>
|
||||
|
||||
<!-- Phone numbers -->
|
||||
<string name="number">Nömrə</string>
|
||||
<string name="mobile">Mobil</string>
|
||||
<string name="main_number">Əsas</string>
|
||||
<string name="work_fax">İş Faksı</string>
|
||||
<string name="home_fax">Ev Faksı</string>
|
||||
<string name="pager">Zəng cihazı</string>
|
||||
<string name="no_phone_number_found">Heçbir telefon nömrəsi tapılmadı</string>
|
||||
|
||||
<!-- Events -->
|
||||
<string name="birthday">Ad günü</string>
|
||||
<string name="anniversary">İl dönümü</string>
|
||||
|
||||
<!-- Favorites -->
|
||||
<string name="no_favorites">Görünür, hələlik heçbir sevimli kontakt əlavə etməmisiniz.</string>
|
||||
<string name="add_favorites">Sevimlilər əlavə et</string>
|
||||
<string name="add_to_favorites">Sevimlilərə əlavə et</string>
|
||||
<string name="remove_from_favorites">Sevimlilərdən sil</string>
|
||||
<string name="must_be_at_edit">Kontaktı dəyişmək üçün İdarə et ekranında olmalısınız</string>
|
||||
|
||||
<!-- Search -->
|
||||
<string name="search_contacts">Kontaktları axtar</string>
|
||||
<string name="search_favorites">Sevimliləri axtar</string>
|
||||
|
||||
<!-- Export / Import -->
|
||||
<string name="import_contacts">Kontaktları daxil et</string>
|
||||
<string name="export_contacts">Kontaktları xaric et</string>
|
||||
<string name="import_contacts_from_vcf">.vcf faylından kontaktları daxil et</string>
|
||||
<string name="export_contacts_to_vcf">.vcf faylından kontaktları xaric et</string>
|
||||
<string name="target_contact_source">Kontakt kökünü nişanla</string>
|
||||
<string name="include_contact_sources">Kontakt köklərini daxil et</string>
|
||||
<string name="filename_without_vcf">Fayl adı (.vcf olmadan)</string>
|
||||
|
||||
<!-- Visible fields -->
|
||||
<string name="select_fields_to_show">Göstərmək üçün sahəni seç</string>
|
||||
<string name="prefix">Ön şəkilçi</string>
|
||||
<string name="suffix">Orta şəkilçi</string>
|
||||
<string name="phone_numbers">Telefon nömrələri</string>
|
||||
<string name="emails">E-poçtlar</string>
|
||||
<string name="addresses">Ünvanlar</string>
|
||||
<string name="events">Hadisələr (ad günləri, il dönümləri)</string>
|
||||
<string name="notes">Qeydlər</string>
|
||||
<string name="organization">Təşkilat</string>
|
||||
<string name="websites">Vebsaytlar</string>
|
||||
<string name="groups">Qruplar </string>
|
||||
<string name="contact_source">Kontakt kökü</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">I want to change what fields are visible at contacts. Can I do it?</string>
|
||||
<string name="faq_1_text">Yes, all you have to do is go in Settings -> Manage shown contact fields. There you can select what fields should be visible. Some of them are even disabled by default, so you might find some new ones there.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
<string name="app_short_description">A contacts app for managing your contacts without ads.</string>
|
||||
<string name="app_long_description">
|
||||
A simple app for creating or managing your contacts from any source. The contacts can be stored on your device only, but also synchronized via Google, or other accounts. You can display your favorite contacts on a separate list.
|
||||
|
||||
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.
|
||||
|
||||
Contains no ads or unnecessary permissions. It is fully opensource, provides customizable colors.
|
||||
|
||||
This app is just one piece of a bigger series of apps. You can find the rest of them at https://www.simplemobiletools.com
|
||||
</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
-->
|
||||
</resources>
|
@ -6,13 +6,15 @@
|
||||
<string name="updating">Aktualisiere…</string>
|
||||
<string name="phone_storage">Gerätespeicher</string>
|
||||
<string name="phone_storage_hidden">Gerätespeicher (nicht sichtbar für andere Apps)</string>
|
||||
<string name="company">Company</string>
|
||||
<string name="job_position">Job position</string>
|
||||
<string name="website">Website</string>
|
||||
<string name="send_sms_to_contacts">Send SMS to contacts</string>
|
||||
<string name="send_email_to_contacts">Send email to contacts</string>
|
||||
<string name="send_sms_to_group">Send SMS to group</string>
|
||||
<string name="send_email_to_group">Send email to group</string>
|
||||
<string name="company">Unternehmen</string>
|
||||
<string name="job_position">Arbeitsstelle</string>
|
||||
<string name="website">Webseite</string>
|
||||
<string name="send_sms_to_contacts">Sende SMS an Kontakte</string>
|
||||
<string name="send_email_to_contacts">Sende E-Mail an Kontakte</string>
|
||||
<string name="send_sms_to_group">Sende SMS an Gruppe</string>
|
||||
<string name="send_email_to_group">Sende E-Mail an Gruppe</string>
|
||||
<string name="call_person">%s anrufen</string>
|
||||
<string name="request_the_required_permissions">Benötigte Berechtigungen anfordern</string>
|
||||
|
||||
<string name="new_contact">Neuer Kontakt</string>
|
||||
<string name="edit_contact">Kontakt bearbeiten</string>
|
||||
@ -20,12 +22,13 @@
|
||||
<string name="select_contacts">Kontakte auswählen</string>
|
||||
<string name="first_name">Vorname</string>
|
||||
<string name="middle_name">Zweiter Vorname</string>
|
||||
<string name="surname">Familienname</string>
|
||||
<string name="surname">Nachname</string>
|
||||
<string name="nickname">Spitzname</string>
|
||||
|
||||
<!-- Groups -->
|
||||
<string name="no_groups">Keine Gruppen</string>
|
||||
<string name="create_new_group">Eine neue Gruppe erstellen</string>
|
||||
<string name="remove_from_group">Von Gruppe entfernen</string>
|
||||
<string name="remove_from_group">Aus Gruppe entfernen</string>
|
||||
<string name="no_group_participants">Diese Gruppe ist leer</string>
|
||||
<string name="add_contacts">Kontakte hinzufügen</string>
|
||||
<string name="no_group_created">Es sind keine Kontaktgruppen auf diesem Gerät vorhanden</string>
|
||||
@ -34,24 +37,27 @@
|
||||
<string name="create_group_under_account">Gruppe in diesem Konto erstellen</string>
|
||||
|
||||
<!-- Photo -->
|
||||
<string name="take_photo">Foto machen</string>
|
||||
<string name="take_photo">Foto aufnehmen</string>
|
||||
<string name="choose_photo">Foto auswählen</string>
|
||||
<string name="remove_photo">Foto entfernen</string>
|
||||
|
||||
<!-- Settings -->
|
||||
<string name="start_name_with_surname">Namen mit Nachnamen beginnen</string>
|
||||
<string name="show_phone_numbers">Zeige Telefonnummern im Hauptmenü</string>
|
||||
<string name="show_contact_thumbnails">Zeige Vorschaubilder für Kontakte</string>
|
||||
<string name="show_contact_thumbnails">Zeige Vorschaubilder der Kontakte</string>
|
||||
<string name="on_contact_click">Beim Klicken auf den Kontakt</string>
|
||||
<string name="call_contact">Kontakt anrufen</string>
|
||||
<string name="view_contact">Kontaktdetails ansehen</string>
|
||||
<string name="show_favorites_tab">Show favorites tab</string>
|
||||
<string name="show_groups_tab">Show groups tab</string>
|
||||
<string name="manage_shown_contact_fields">Manage shown contact fields</string>
|
||||
<string name="filter_duplicates">Try filtering out duplicate contacts</string>
|
||||
<string name="view_contact">Kontaktdetails anzeigen</string>
|
||||
<string name="manage_shown_contact_fields">Bearbeite sichtbare Kontaktfelder</string>
|
||||
<string name="filter_duplicates">Versuche Kontaktduplikate herauszufiltern</string>
|
||||
<string name="manage_shown_tabs">Anzuzeigende Tabs festlegen</string>
|
||||
<string name="contacts">Kontakte</string>
|
||||
<string name="favorites">Favoriten</string>
|
||||
<string name="recent_calls">Anrufliste</string>
|
||||
<string name="show_call_confirmation_dialog">Bestätigungsdialog zeigen, bevor ein Anruf durchgeführt wird</string>
|
||||
|
||||
<!-- Emails -->
|
||||
<string name="email">Email</string>
|
||||
<string name="email">E-Mail</string>
|
||||
<string name="home">Privat</string>
|
||||
<string name="work">Arbeit</string>
|
||||
<string name="other">Sonstiges</string>
|
||||
@ -74,7 +80,7 @@
|
||||
<string name="add_favorites">Favoriten hinzufügen</string>
|
||||
<string name="add_to_favorites">Zu Favoriten hinzufügen</string>
|
||||
<string name="remove_from_favorites">Aus Favoriten entfernen</string>
|
||||
<string name="must_be_at_edit">You must be at the Edit screen to modify a contact</string>
|
||||
<string name="must_be_at_edit">Sie müssen sich im Bearbeitungsmodus befinden, um einen Kontakt zu bearbeiten</string>
|
||||
|
||||
<!-- Search -->
|
||||
<string name="search_contacts">Kontakte durchsuchen</string>
|
||||
@ -90,34 +96,34 @@
|
||||
<string name="filename_without_vcf">Dateiname (ohne .vcf)</string>
|
||||
|
||||
<!-- Visible fields -->
|
||||
<string name="select_fields_to_show">Select fields to show</string>
|
||||
<string name="prefix">Prefix</string>
|
||||
<string name="select_fields_to_show">Sichtbare Felder auswählen</string>
|
||||
<string name="prefix">Titel</string>
|
||||
<string name="suffix">Suffix</string>
|
||||
<string name="phone_numbers">Phone numbers</string>
|
||||
<string name="emails">Emails</string>
|
||||
<string name="addresses">Addresses</string>
|
||||
<string name="events">Events (birthdays, anniversaries)</string>
|
||||
<string name="notes">Notes</string>
|
||||
<string name="organization">Organization</string>
|
||||
<string name="websites">Websites</string>
|
||||
<string name="groups">Groups</string>
|
||||
<string name="contact_source">Contact source</string>
|
||||
<string name="phone_numbers">Telefonnummern</string>
|
||||
<string name="emails">E-Mails</string>
|
||||
<string name="addresses">Addressen</string>
|
||||
<string name="events">Termine (Geburtstage, Jahrestage)</string>
|
||||
<string name="notes">Notizen</string>
|
||||
<string name="organization">Organisation</string>
|
||||
<string name="websites">Webseiten</string>
|
||||
<string name="groups">Gruppen</string>
|
||||
<string name="contact_source">Kontaktquelle</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">I want to change what fields are visible at contacts. Can I do it?</string>
|
||||
<string name="faq_1_text">Yes, all you have to do is go in Settings -> Manage shown contact fields. There you can select what fields should be visible. Some of them are even disabled by default, so you might find some new ones there.</string>
|
||||
<string name="faq_1_title">Ich möchte die sichtbaren Kontaktfelder ändern. Kann ich das machen?</string>
|
||||
<string name="faq_1_text">Ja, alles, was Sie tun müssen ist folgendes: Gehen Sie zu Einstellungen -> Bearbeite sichtbare Kontaktfelder. Hier können die sichtbaren Felder ausgewählt werden. Einige sind standardmäßig deaktiviert, weshalb hier neue gefunden werden können.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
<string name="app_short_description">Eine App zum Verwalten von Kontakten, ganz ohne Werbung.</string>
|
||||
<string name="app_short_description">Eine Kontakte-App zur Verwaltung Ihrer Kontake. Ohne Werbung.</string>
|
||||
<string name="app_long_description">
|
||||
Eine schlichte App um Kontakte aus allen Quellen zu verwalten und neue zu erstellen. Die Kontakte können nur auf deinem Gerät gespeichert werden, aber auch über Google oder andere Dienste synchronisiert werden. Deine wichtigsten Kontakte werden in einer separaten Liste angezeigt.
|
||||
Eine einfache App, mit der Sie Kontakte erstellen oder von jeder Quelle verwalten können. Die Kontakte können entweder nur auf Ihrem Gerät gespeichert, oder mittels Google oder anderer Konten synchronisiert werden. Sie können Ihre Lieblingskontake in einer separaten Liste anzeigen.
|
||||
|
||||
Du kannst diese App auch dazu nutzen, um die Email-Adressen und Termine von Kontakten zu verwalten. Sie hat die Möglichkeit mithilfe von mehreren Parametern zu sortieren/filtern, optional auch den Familiennamen als Vornamen anzuzeigen.
|
||||
Sie können es auch zur Verwaltung von Nutzer-E-Mails und Ereignisse nutzen. Es kann nach mehreren Parametern sortieren oder filtern, oder optional den Nachnamen zuerst anzeigen.
|
||||
|
||||
Beinhaltet keine Werbung oder unnötige Berechtigungen. Sie ist komplett Open Source, alle verwendeten Farben sind anpassbar.
|
||||
Enthält keine Werbung oder unnötige Berechtigungen. Vollständig quelloffen. Die Farben sind anpassbar.
|
||||
|
||||
Diese App ist nur eine aus einer größeren Serie von schlichten Apps. Der Rest davon findet sich auf https://www.simplemobiletools.com
|
||||
Diese App ist nur ein Teil einer größeren App-Familie. Die übrigen finden Sie unter https://www.simplemobiletools.com
|
||||
</string>
|
||||
|
||||
<!--
|
||||
|
@ -1,18 +1,20 @@
|
||||
<resources>
|
||||
<string name="app_name">Απλές Επαφές</string>
|
||||
<string name="app_name">Simple Contacts</string>
|
||||
<string name="app_launcher_name">Επαφές</string>
|
||||
<string name="address">Διεύθυνση</string>
|
||||
<string name="inserting">Εισαγωγή…</string>
|
||||
<string name="updating">Ενημέρωση…</string>
|
||||
<string name="phone_storage">Μνήμη τηλεφώνου</string>
|
||||
<string name="phone_storage_hidden">Μνήμη τηλεφώνου (δεν είναι ορατή από άλλες εφαρμογές)</string>
|
||||
<string name="company">Company</string>
|
||||
<string name="job_position">Job position</string>
|
||||
<string name="website">Website</string>
|
||||
<string name="send_sms_to_contacts">Send SMS to contacts</string>
|
||||
<string name="send_email_to_contacts">Send email to contacts</string>
|
||||
<string name="send_sms_to_group">Send SMS to group</string>
|
||||
<string name="send_email_to_group">Send email to group</string>
|
||||
<string name="phone_storage_hidden">Μνήμη τηλεφώνου (κρυφές από άλλες εφαρμογές)</string>
|
||||
<string name="company">Εταιρεία</string>
|
||||
<string name="job_position">Θέση Εργασίας</string>
|
||||
<string name="website">Ιστοσελίδα</string>
|
||||
<string name="send_sms_to_contacts">Αποστολή SMS σε επαφές</string>
|
||||
<string name="send_email_to_contacts">Αποστολή email σε επαφές</string>
|
||||
<string name="send_sms_to_group">Αποστολή SMS σε ομάδες</string>
|
||||
<string name="send_email_to_group">Αποστολή email σε ομάδες</string>
|
||||
<string name="call_person">Κλήση %s</string>
|
||||
<string name="request_the_required_permissions">Ζητούνται τα απαιτούμενα δικαιώματα</string>
|
||||
|
||||
<string name="new_contact">Νέα επαφή</string>
|
||||
<string name="edit_contact">Επεξεργασία επαφής</string>
|
||||
@ -21,6 +23,7 @@
|
||||
<string name="first_name">Όνομα</string>
|
||||
<string name="middle_name">Μεσαίο όνομα</string>
|
||||
<string name="surname">Επώνυμο</string>
|
||||
<string name="nickname">Ψευδώνυμο</string>
|
||||
|
||||
<!-- Groups -->
|
||||
<string name="no_groups">Δεν υπάρχουν ομάδες</string>
|
||||
@ -31,7 +34,7 @@
|
||||
<string name="no_group_created">Δεν υπάρχουν ομάδες επαφών στη συσκευή</string>
|
||||
<string name="create_group">Δημιουργία ομάδας</string>
|
||||
<string name="add_to_group">Προσθήκη σε ομάδα</string>
|
||||
<string name="create_group_under_account">Δημιουργία ομάδας κάτω από λογαριασμό</string>
|
||||
<string name="create_group_under_account">Δημιουργία ομάδας υπο ενός λογαριασμού</string>
|
||||
|
||||
<!-- Photo -->
|
||||
<string name="take_photo">Λήψη φωτογραφίας</string>
|
||||
@ -39,20 +42,23 @@
|
||||
<string name="remove_photo">Αφαίρεση φωτογραφίας</string>
|
||||
|
||||
<!-- Settings -->
|
||||
<string name="start_name_with_surname">Το όνομα ξεκινά με το επώνυμο</string>
|
||||
<string name="start_name_with_surname">Εμφάνιση πρώτα το επώνυμο</string>
|
||||
<string name="show_phone_numbers">Εμφάνιση τηλεφωνικών αριθμών στην κύρια οθόνη</string>
|
||||
<string name="show_contact_thumbnails">Εμφάνιση μικρογραφιών επαφής</string>
|
||||
<string name="on_contact_click">Στην επιλογή επαφής</string>
|
||||
<string name="call_contact">Κλήση επαφής</string>
|
||||
<string name="view_contact">Εμφάνιση λεπτομερειών επαφής</string>
|
||||
<string name="show_favorites_tab">Εμφάνιση καρτέλας αγαπημένων</string>
|
||||
<string name="show_groups_tab">Εμφάνιση καρτέλας ομάδων</string>
|
||||
<string name="manage_shown_contact_fields">Manage shown contact fields</string>
|
||||
<string name="filter_duplicates">Try filtering out duplicate contacts</string>
|
||||
<string name="manage_shown_contact_fields">Διαχείριση εμφανιζόμενων πεδίων επαφής</string>
|
||||
<string name="filter_duplicates">Δοκιμάστε το φιλτράρισμα διπλών επαφών</string>
|
||||
<string name="manage_shown_tabs">Διαχείριση εμφανιζόμενων καρτελών</string>
|
||||
<string name="contacts">Επαφές</string>
|
||||
<string name="favorites">Αγαπημένες</string>
|
||||
<string name="recent_calls">Πρόσφατες Κλήσεις</string>
|
||||
<string name="show_call_confirmation_dialog">Εμφάνιση διαλόγου επιβεβαίωσης πριν από την έναρξη μιας κλήσης</string>
|
||||
|
||||
<!-- Emails -->
|
||||
<string name="email">Email</string>
|
||||
<string name="home">Σπίτι</string>
|
||||
<string name="home">Οικία</string>
|
||||
<string name="work">Εργασία</string>
|
||||
<string name="other">Άλλο</string>
|
||||
|
||||
@ -60,8 +66,8 @@
|
||||
<string name="number">Αριθμός</string>
|
||||
<string name="mobile">Κινητό</string>
|
||||
<string name="main_number">Κύριο</string>
|
||||
<string name="work_fax">Φαξ εργασίας</string>
|
||||
<string name="home_fax">Φαξ σπιτιού</string>
|
||||
<string name="work_fax">Φαξ Εργασίας</string>
|
||||
<string name="home_fax">Φαξ Οικίας</string>
|
||||
<string name="pager">Βομβητής</string>
|
||||
<string name="no_phone_number_found">Δεν βρέθηκε τηλεφωνικός αριθμός</string>
|
||||
|
||||
@ -70,11 +76,11 @@
|
||||
<string name="anniversary">Επέτειος</string>
|
||||
|
||||
<!-- Favorites -->
|
||||
<string name="no_favorites">Φαίνεται ότι δεν έχεις προσθέσει αγαπημένες επαφές ακόμα.</string>
|
||||
<string name="no_favorites">Φαίνεται ότι δεν έχετε προσθέσει αγαπημένες επαφές ακόμη.</string>
|
||||
<string name="add_favorites">Προσθήκη αγαπημένων</string>
|
||||
<string name="add_to_favorites">Προσθήκη στα αγαπημένα</string>
|
||||
<string name="add_to_favorites">Προσθήκη στις αγαπημένες</string>
|
||||
<string name="remove_from_favorites">Αφαίρεση από τα αγαπημένα</string>
|
||||
<string name="must_be_at_edit">You must be at the Edit screen to modify a contact</string>
|
||||
<string name="must_be_at_edit">Πρέπει να είστε στην οθόνη "Επεξεργασία" για να τροποποιήσετε μια επαφή</string>
|
||||
|
||||
<!-- Search -->
|
||||
<string name="search_contacts">Αναζήτηση επαφών</string>
|
||||
@ -90,34 +96,34 @@
|
||||
<string name="filename_without_vcf">Όνομα αρχείου (χωρίς .vcf)</string>
|
||||
|
||||
<!-- Visible fields -->
|
||||
<string name="select_fields_to_show">Select fields to show</string>
|
||||
<string name="prefix">Prefix</string>
|
||||
<string name="suffix">Suffix</string>
|
||||
<string name="phone_numbers">Phone numbers</string>
|
||||
<string name="select_fields_to_show">Επιλογή εμφάνισης πεδίων</string>
|
||||
<string name="prefix">Πρόθεμα</string>
|
||||
<string name="suffix">Κατάληξη</string>
|
||||
<string name="phone_numbers">Αριθμοί Τηλεφώνων</string>
|
||||
<string name="emails">Emails</string>
|
||||
<string name="addresses">Addresses</string>
|
||||
<string name="events">Events (birthdays, anniversaries)</string>
|
||||
<string name="notes">Notes</string>
|
||||
<string name="organization">Organization</string>
|
||||
<string name="websites">Websites</string>
|
||||
<string name="groups">Groups</string>
|
||||
<string name="contact_source">Contact source</string>
|
||||
<string name="addresses">Διευθύνσεις</string>
|
||||
<string name="events">Εκδηλώσεις (γενέθλια, επετείους)</string>
|
||||
<string name="notes">Σημειώσεις</string>
|
||||
<string name="organization">Εταιρεία</string>
|
||||
<string name="websites">Ιστοσελίδα</string>
|
||||
<string name="groups">Ομάδες</string>
|
||||
<string name="contact_source">Προέλευση επαφής</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">I want to change what fields are visible at contacts. Can I do it?</string>
|
||||
<string name="faq_1_text">Yes, all you have to do is go in Settings -> Manage shown contact fields. There you can select what fields should be visible. Some of them are even disabled by default, so you might find some new ones there.</string>
|
||||
<string name="faq_1_title">Θέλω να αλλάξω τα πεδία που θα είναι ορατά στις επαφές. Μπορώ να το κάνω?</string>
|
||||
<string name="faq_1_text">Ναι, το μόνο που έχετε να κάνετε είναι να μεταβείτε στις Ρυθμίσεις -> Διαχείριση εμφανιζόμενων πεδίων επαφής. Εκεί μπορείτε να επιλέξετε ποια πεδία θα πρέπει να είναι ορατά. Κάποια από αυτά είναι ακόμη και απενεργοποιημένα από προεπιλογή, επομένως ίσως βρείτε κάποια νέα εκεί.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
<string name="app_short_description">Μια εφαρμογή επαφών για να διαχειρίζεσαι τις επαφές σου χωρίς διαφημίσεις.</string>
|
||||
<string name="app_short_description">Μια εφαρμογή για την διαχείρηση των επαφών σου χωρίς διαφημίσεις.</string>
|
||||
<string name="app_long_description">
|
||||
Μια απλή εφαρμογή για δημιουργία και διαχείριση των επαφών σου από κάθε πηγή. Οι επαφές μπορεί να είναι αποθηκευμένες μόνο στη συσκευή σου, αλλά μπορούν να συγχρονίζονται στο Google, ή σε κάποιο άλλο λογαριασμό. Μπορείς να εμφανίσεις τις αγαπημένες σου επαφές σε ξεχωριστή λίστα.
|
||||
|
||||
Μπορείς να τη χρησιμοποιήσεις για τη διαχείριση των email των χρηστών και τα γεγονότα. Έχει τη δυνατότητα ταξινόμησης/φιλτραρίσματος με διάφορες παραμέτρους, προαιρετικά να εμφανίζεται το επώνυμο σαν όνομα.
|
||||
Μπορείτε να τη χρησιμοποιήσετε για τη διαχείριση των email και εκδηλώσεων επίσης. Έχει τη δυνατότητα ταξινόμησης/φιλτραρίσματος με διάφορες παραμέτρους, προαιρετικά να εμφανίζεται το επώνυμο πρώτα ή το όνομα.
|
||||
|
||||
Δεν περιέχει διαφημίσεις ή περιττές άδειες. Είναι πλήρως ανοικτού κώδικα, παρέχει δυνατότητα προσαρμογής των χρωμάτων.
|
||||
Δεν περιέχει διαφημίσεις ή περιττές άδειες. Έιναι όλη ανοιχτού κώδικα και παρέχει προσαρμόσιμα χρώματα για την εφαρμογή.
|
||||
|
||||
Αυτή η εφαρμογή είναι ένα μικρό κομμάτι μιας μεγαλύτερης συλλογής εφαρμογών. Μπορείς να βρεις τις υπόλοιπες στο https://www.simplemobiletools.com
|
||||
Αυτή η εφαρμογή είναι μέρος μιας σειράς εφαρμογών. Μπορείτε να βρείτε τις υπόλοιπες στο https://www.simplemobiletools.com
|
||||
</string>
|
||||
|
||||
<!--
|
||||
|
@ -13,6 +13,8 @@
|
||||
<string name="send_email_to_contacts">Envoyer un e-mail aux contacts</string>
|
||||
<string name="send_sms_to_group">Envoyer un SMS au groupe</string>
|
||||
<string name="send_email_to_group">Envoyer un e-mail au groupe</string>
|
||||
<string name="call_person">Call %s</string>
|
||||
<string name="request_the_required_permissions">Request the required permissions</string>
|
||||
|
||||
<string name="new_contact">Nouveau contact</string>
|
||||
<string name="edit_contact">Modifier contact</string>
|
||||
@ -21,6 +23,7 @@
|
||||
<string name="first_name">Prénom</string>
|
||||
<string name="middle_name">Deuxième prénom</string>
|
||||
<string name="surname">Nom</string>
|
||||
<string name="nickname">Nickname</string>
|
||||
|
||||
<!-- Groups -->
|
||||
<string name="no_groups">Pas de groupe</string>
|
||||
@ -45,10 +48,13 @@
|
||||
<string name="on_contact_click">Sur appui du contact</string>
|
||||
<string name="call_contact">Appeler le contact</string>
|
||||
<string name="view_contact">Voir les détails du contact</string>
|
||||
<string name="show_favorites_tab">Afficher l\'onglet favoris</string>
|
||||
<string name="show_groups_tab">Afficher l\'onglet groupes</string>
|
||||
<string name="manage_shown_contact_fields">Configurer l\'affichage des champs des contacts</string>
|
||||
<string name="filter_duplicates">Try filtering out duplicate contacts</string>
|
||||
<string name="manage_shown_tabs">Manage shown tabs</string>
|
||||
<string name="contacts">Contacts</string>
|
||||
<string name="favorites">Favorites</string>
|
||||
<string name="recent_calls">Recent calls</string>
|
||||
<string name="show_call_confirmation_dialog">Show a call confirmation dialog before initiating a call</string>
|
||||
|
||||
<!-- Emails -->
|
||||
<string name="email">E-mail</string>
|
||||
|
@ -13,6 +13,8 @@
|
||||
<string name="send_email_to_contacts">Send email to contacts</string>
|
||||
<string name="send_sms_to_group">Send SMS to group</string>
|
||||
<string name="send_email_to_group">Send email to group</string>
|
||||
<string name="call_person">Call %s</string>
|
||||
<string name="request_the_required_permissions">Request the required permissions</string>
|
||||
|
||||
<string name="new_contact">Novi kontakt</string>
|
||||
<string name="edit_contact">Uredi kontakt</string>
|
||||
@ -21,6 +23,7 @@
|
||||
<string name="first_name">Ime</string>
|
||||
<string name="middle_name">Srednje ime</string>
|
||||
<string name="surname">Prezime</string>
|
||||
<string name="nickname">Nickname</string>
|
||||
|
||||
<!-- Groups -->
|
||||
<string name="no_groups">Nema grupa</string>
|
||||
@ -45,10 +48,13 @@
|
||||
<string name="on_contact_click">Prilikom dodira kontakta</string>
|
||||
<string name="call_contact">Nazovi kontakt</string>
|
||||
<string name="view_contact">Prikaži pojedinosti o kontaktu</string>
|
||||
<string name="show_favorites_tab">Prikaži karticu favorita</string>
|
||||
<string name="show_groups_tab">Prikaži karticu grupa</string>
|
||||
<string name="manage_shown_contact_fields">Manage shown contact fields</string>
|
||||
<string name="filter_duplicates">Try filtering out duplicate contacts</string>
|
||||
<string name="manage_shown_tabs">Manage shown tabs</string>
|
||||
<string name="contacts">Contacts</string>
|
||||
<string name="favorites">Favorites</string>
|
||||
<string name="recent_calls">Recent calls</string>
|
||||
<string name="show_call_confirmation_dialog">Show a call confirmation dialog before initiating a call</string>
|
||||
|
||||
<!-- Emails -->
|
||||
<string name="email">E-pošta</string>
|
||||
|
133
app/src/main/res/values-ja/strings.xml
Normal file
@ -0,0 +1,133 @@
|
||||
<resources>
|
||||
<string name="app_name">Simple Contacts</string>
|
||||
<string name="app_launcher_name">連絡先</string>
|
||||
<string name="address">住所</string>
|
||||
<string name="inserting">挿入中…</string>
|
||||
<string name="updating">更新中…</string>
|
||||
<string name="phone_storage">内部ストレージ</string>
|
||||
<string name="phone_storage_hidden">内部ストレージ (他のアプリからは表示されません)</string>
|
||||
<string name="company">会社</string>
|
||||
<string name="job_position">役職</string>
|
||||
<string name="website">ウェブサイト</string>
|
||||
<string name="send_sms_to_contacts">連絡先にSMSを送信</string>
|
||||
<string name="send_email_to_contacts">連絡先にメールを送信</string>
|
||||
<string name="send_sms_to_group">グループにSMSを送信</string>
|
||||
<string name="send_email_to_group">グループにメールを送信</string>
|
||||
<string name="call_person">Call %s</string>
|
||||
<string name="request_the_required_permissions">Request the required permissions</string>
|
||||
|
||||
<string name="new_contact">新しい連絡先</string>
|
||||
<string name="edit_contact">連絡先を編集</string>
|
||||
<string name="select_contact">連絡先を選択</string>
|
||||
<string name="select_contacts">連絡先を選択</string>
|
||||
<string name="first_name">名</string>
|
||||
<string name="middle_name">ミドルネーム</string>
|
||||
<string name="surname">姓</string>
|
||||
<string name="nickname">Nickname</string>
|
||||
|
||||
<!-- Groups -->
|
||||
<string name="no_groups">グループなし</string>
|
||||
<string name="create_new_group">新しいグループを作成</string>
|
||||
<string name="remove_from_group">グループから削除</string>
|
||||
<string name="no_group_participants">このグループは空です</string>
|
||||
<string name="add_contacts">連絡先を追加</string>
|
||||
<string name="no_group_created">連絡先グループがありません</string>
|
||||
<string name="create_group">グループを作成</string>
|
||||
<string name="add_to_group">グループに追加</string>
|
||||
<string name="create_group_under_account">アカウントの下にグループを作成</string>
|
||||
|
||||
<!-- Photo -->
|
||||
<string name="take_photo">写真を撮影</string>
|
||||
<string name="choose_photo">写真を選択</string>
|
||||
<string name="remove_photo">写真を削除</string>
|
||||
|
||||
<!-- Settings -->
|
||||
<string name="start_name_with_surname">姓を先に表示</string>
|
||||
<string name="show_phone_numbers">メイン画面に電話番号を表示</string>
|
||||
<string name="show_contact_thumbnails">連絡先のサムネイルを表示</string>
|
||||
<string name="on_contact_click">連絡先をタップ</string>
|
||||
<string name="call_contact">連絡先に発信</string>
|
||||
<string name="view_contact">連絡先の詳細を表示</string>
|
||||
<string name="manage_shown_contact_fields">連絡先に表示するフィールドを管理</string>
|
||||
<string name="filter_duplicates">重複した連絡先を除外する</string>
|
||||
<string name="manage_shown_tabs">表示するタブを管理</string>
|
||||
<string name="contacts">連絡先</string>
|
||||
<string name="favorites">お気に入り</string>
|
||||
<string name="recent_calls">Recent calls</string>
|
||||
<string name="show_call_confirmation_dialog">発信する前に確認ダイアログを表示する</string>
|
||||
|
||||
<!-- Emails -->
|
||||
<string name="email">メール</string>
|
||||
<string name="home">自宅</string>
|
||||
<string name="work">職場</string>
|
||||
<string name="other">その他</string>
|
||||
|
||||
<!-- Phone numbers -->
|
||||
<string name="number">番号</string>
|
||||
<string name="mobile">携帯</string>
|
||||
<string name="main_number">Main</string>
|
||||
<string name="work_fax">職場FAX</string>
|
||||
<string name="home_fax">自宅FAX</string>
|
||||
<string name="pager">ポケベル</string>
|
||||
<string name="no_phone_number_found">電話番号が見つかりません</string>
|
||||
|
||||
<!-- Events -->
|
||||
<string name="birthday">誕生日</string>
|
||||
<string name="anniversary">記念日</string>
|
||||
|
||||
<!-- Favorites -->
|
||||
<string name="no_favorites">お気に入りの連絡先はまだありません</string>
|
||||
<string name="add_favorites">お気に入りを追加</string>
|
||||
<string name="add_to_favorites">お気に入りに追加</string>
|
||||
<string name="remove_from_favorites">お気に入りから削除</string>
|
||||
<string name="must_be_at_edit">連絡先を編集するには編集画面に切り替えてください</string>
|
||||
|
||||
<!-- Search -->
|
||||
<string name="search_contacts">連絡先を検索</string>
|
||||
<string name="search_favorites">お気に入りを検索</string>
|
||||
|
||||
<!-- Export / Import -->
|
||||
<string name="import_contacts">連絡先をインポート</string>
|
||||
<string name="export_contacts">連絡先をエクスポート</string>
|
||||
<string name="import_contacts_from_vcf">.vcfファイルから連絡先をインポート</string>
|
||||
<string name="export_contacts_to_vcf">連絡先を.vcfファイルにエクスポート</string>
|
||||
<string name="target_contact_source">Target contact source</string>
|
||||
<string name="include_contact_sources">Include contact sources</string>
|
||||
<string name="filename_without_vcf">ファイル名 (.vcfを含めない)</string>
|
||||
|
||||
<!-- Visible fields -->
|
||||
<string name="select_fields_to_show">表示する項目を選択</string>
|
||||
<string name="prefix">敬称(名前の前)</string>
|
||||
<string name="suffix">敬称(名前の後)</string>
|
||||
<string name="phone_numbers">電話番号</string>
|
||||
<string name="emails">メール</string>
|
||||
<string name="addresses">住所</string>
|
||||
<string name="events">予定 (誕生日、記念日)</string>
|
||||
<string name="notes">メモ</string>
|
||||
<string name="organization">所属</string>
|
||||
<string name="websites">ウェブサイト</string>
|
||||
<string name="groups">グループ</string>
|
||||
<string name="contact_source">インポート元</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">連絡先に表示される項目(フィールド)を変更することはできますか?</string>
|
||||
<string name="faq_1_text">可能です。[設定] -> [連絡先に表示するフィールドを管理] から、表示されるフィールドを選択することができます。これらの中にはデフォルトで無効になっているものもあるので、あなたは新しいものを見つけるかもしれません。</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
<string name="app_short_description">連絡先を管理するシンプルなアプリ (広告表示なし)。</string>
|
||||
<string name="app_long_description">
|
||||
連絡先を作成または管理するためのシンプルなアプリです。連絡先はお使いの端末上にのみ保存されますが、Googleや他のアカウントと同期することもできます。お気に入りの連絡先を別のリストとして表示することができます。
|
||||
|
||||
友人のメールアドレスや予定の管理にも使用できます。これらは複数の項目で並べ替えやフィルタリングする機能があり、名前を\"姓 名\"の順に表示することもできます。
|
||||
|
||||
広告や不要なアクセス許可は含まれていません。完全にオープンソースで、色のカスタマイズも可能です。
|
||||
|
||||
このアプリは大きな一連のアプリの一つです。 その他のアプリは http://www.simplemobiletools.com で見つけることができます。
|
||||
</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
-->
|
||||
</resources>
|
@ -13,6 +13,8 @@
|
||||
<string name="send_email_to_contacts">Send email to contacts</string>
|
||||
<string name="send_sms_to_group">Send SMS to group</string>
|
||||
<string name="send_email_to_group">Send email to group</string>
|
||||
<string name="call_person">Call %s</string>
|
||||
<string name="request_the_required_permissions">Request the required permissions</string>
|
||||
|
||||
<string name="new_contact">새로운 연락처</string>
|
||||
<string name="edit_contact">연락처 수정</string>
|
||||
@ -21,6 +23,7 @@
|
||||
<string name="first_name">이름</string>
|
||||
<string name="middle_name">중간 이름</string>
|
||||
<string name="surname">성</string>
|
||||
<string name="nickname">Nickname</string>
|
||||
|
||||
<!-- Groups -->
|
||||
<string name="no_groups">No groups</string>
|
||||
@ -45,10 +48,13 @@
|
||||
<string name="on_contact_click">On contact click</string>
|
||||
<string name="call_contact">Call contact</string>
|
||||
<string name="view_contact">View contact details</string>
|
||||
<string name="show_favorites_tab">Show favorites tab</string>
|
||||
<string name="show_groups_tab">Show groups tab</string>
|
||||
<string name="manage_shown_contact_fields">Manage shown contact fields</string>
|
||||
<string name="filter_duplicates">Try filtering out duplicate contacts</string>
|
||||
<string name="manage_shown_tabs">Manage shown tabs</string>
|
||||
<string name="contacts">Contacts</string>
|
||||
<string name="favorites">Favorites</string>
|
||||
<string name="recent_calls">Recent calls</string>
|
||||
<string name="show_call_confirmation_dialog">Show a call confirmation dialog before initiating a call</string>
|
||||
|
||||
<!-- Emails -->
|
||||
<string name="email">이메일</string>
|
||||
|
@ -13,6 +13,8 @@
|
||||
<string name="send_email_to_contacts">Send email to contacts</string>
|
||||
<string name="send_sms_to_group">Send SMS to group</string>
|
||||
<string name="send_email_to_group">Send email to group</string>
|
||||
<string name="call_person">Call %s</string>
|
||||
<string name="request_the_required_permissions">Request the required permissions</string>
|
||||
|
||||
<string name="new_contact">Naujas kontaktas</string>
|
||||
<string name="edit_contact">Redaguoti kontaktą</string>
|
||||
@ -21,6 +23,7 @@
|
||||
<string name="first_name">Vardas</string>
|
||||
<string name="middle_name">Antras vardas</string>
|
||||
<string name="surname">Pavardė</string>
|
||||
<string name="nickname">Nickname</string>
|
||||
|
||||
<!-- Groups -->
|
||||
<string name="no_groups">Nėra grupių</string>
|
||||
@ -45,10 +48,13 @@
|
||||
<string name="on_contact_click">Ant kontakto paspaudimo</string>
|
||||
<string name="call_contact">Skambinti kontaktui</string>
|
||||
<string name="view_contact">Žiūrėti kontakto detales</string>
|
||||
<string name="show_favorites_tab">Rodyti mėgiamiausiųjų skirtuką</string>
|
||||
<string name="show_groups_tab">Rodyti grupių skirtuką</string>
|
||||
<string name="manage_shown_contact_fields">Manage shown contact fields</string>
|
||||
<string name="filter_duplicates">Try filtering out duplicate contacts</string>
|
||||
<string name="manage_shown_tabs">Manage shown tabs</string>
|
||||
<string name="contacts">Contacts</string>
|
||||
<string name="favorites">Favorites</string>
|
||||
<string name="recent_calls">Recent calls</string>
|
||||
<string name="show_call_confirmation_dialog">Show a call confirmation dialog before initiating a call</string>
|
||||
|
||||
<!-- Emails -->
|
||||
<string name="email">Elektroninis paštas</string>
|
||||
|
@ -13,6 +13,8 @@
|
||||
<string name="send_email_to_contacts">Enviar e-mail aos contactos</string>
|
||||
<string name="send_sms_to_group">Enviar SMS para o grupo</string>
|
||||
<string name="send_email_to_group">Enviar e-mail para o grupo</string>
|
||||
<string name="call_person">Ligar a %s</string>
|
||||
<string name="request_the_required_permissions">Request the required permissions</string>
|
||||
|
||||
<string name="new_contact">Novo contacto</string>
|
||||
<string name="edit_contact">Editar contacto</string>
|
||||
@ -21,6 +23,7 @@
|
||||
<string name="first_name">Primeiro nome</string>
|
||||
<string name="middle_name">Segundo nome</string>
|
||||
<string name="surname">Apelido</string>
|
||||
<string name="nickname">Alcunha</string>
|
||||
|
||||
<!-- Groups -->
|
||||
<string name="no_groups">Não há grupos</string>
|
||||
@ -45,10 +48,13 @@
|
||||
<string name="on_contact_click">Ao tocar no contacto</string>
|
||||
<string name="call_contact">Ligar</string>
|
||||
<string name="view_contact">Ver detalhes</string>
|
||||
<string name="show_favorites_tab">Mostrar favoritos</string>
|
||||
<string name="show_groups_tab">Mostrar grupos</string>
|
||||
<string name="manage_shown_contact_fields">Gerir campos a exibir</string>
|
||||
<string name="filter_duplicates">Try filtering out duplicate contacts</string>
|
||||
<string name="filter_duplicates">Tentar filtrar contactos duplicados</string>
|
||||
<string name="manage_shown_tabs">Manage shown tabs</string>
|
||||
<string name="contacts">Contactos</string>
|
||||
<string name="favorites">Favoritos</string>
|
||||
<string name="recent_calls">Chamadas recentes</string>
|
||||
<string name="show_call_confirmation_dialog">Mostrar diálogo para confirmar a chamada</string>
|
||||
|
||||
<!-- Emails -->
|
||||
<string name="email">E-mail</string>
|
||||
|
@ -13,6 +13,8 @@
|
||||
<string name="send_email_to_contacts">Отправить письмо контактам</string>
|
||||
<string name="send_sms_to_group">Отправить SMS группе</string>
|
||||
<string name="send_email_to_group">Отправить письмо группе</string>
|
||||
<string name="call_person">Call %s</string>
|
||||
<string name="request_the_required_permissions">Request the required permissions</string>
|
||||
|
||||
<string name="new_contact">Новый контакт</string>
|
||||
<string name="edit_contact">Редактировать контакт</string>
|
||||
@ -21,6 +23,7 @@
|
||||
<string name="first_name">Имя</string>
|
||||
<string name="middle_name">Отчество</string>
|
||||
<string name="surname">Фамилия</string>
|
||||
<string name="nickname">Nickname</string>
|
||||
|
||||
<!-- Groups -->
|
||||
<string name="no_groups">Нет групп</string>
|
||||
@ -45,10 +48,13 @@
|
||||
<string name="on_contact_click">При нажатии на контакт</string>
|
||||
<string name="call_contact">Позвонить контакту</string>
|
||||
<string name="view_contact">Просмотреть подробности о контакте</string>
|
||||
<string name="show_favorites_tab">Показывать вкладку избранного</string>
|
||||
<string name="show_groups_tab">Показывать вкладку групп</string>
|
||||
<string name="manage_shown_contact_fields">Управление отображаемыми полями контактов</string>
|
||||
<string name="filter_duplicates">Отфильтровывать повторяющиеся контакты</string>
|
||||
<string name="manage_shown_tabs">Manage shown tabs</string>
|
||||
<string name="contacts">Contacts</string>
|
||||
<string name="favorites">Favorites</string>
|
||||
<string name="recent_calls">Recent calls</string>
|
||||
<string name="show_call_confirmation_dialog">Show a call confirmation dialog before initiating a call</string>
|
||||
|
||||
<!-- Emails -->
|
||||
<string name="email">Эл. почта</string>
|
||||
|
@ -13,6 +13,8 @@
|
||||
<string name="send_email_to_contacts">Poslať kontaktom email</string>
|
||||
<string name="send_sms_to_group">Poslať skupine SMS</string>
|
||||
<string name="send_email_to_group">Poslať skupine email</string>
|
||||
<string name="call_person">Zavolať %s</string>
|
||||
<string name="request_the_required_permissions">Vyžiadať potrebné oprávnenia</string>
|
||||
|
||||
<string name="new_contact">Nový kontakt</string>
|
||||
<string name="edit_contact">Upraviť kontakt</string>
|
||||
@ -21,6 +23,7 @@
|
||||
<string name="first_name">Krstné meno</string>
|
||||
<string name="middle_name">Stredné meno</string>
|
||||
<string name="surname">Priezvisko</string>
|
||||
<string name="nickname">Prezývka</string>
|
||||
|
||||
<!-- Groups -->
|
||||
<string name="no_groups">Žiadne skupiny</string>
|
||||
@ -45,10 +48,13 @@
|
||||
<string name="on_contact_click">Po kliknutí na kontakt</string>
|
||||
<string name="call_contact">Zavolať kontakt</string>
|
||||
<string name="view_contact">Zobraziť údaje kontaktu</string>
|
||||
<string name="show_favorites_tab">Zobraziť okno s obľúbenými</string>
|
||||
<string name="show_groups_tab">Zobraziť okno so skupinami</string>
|
||||
<string name="manage_shown_contact_fields">Spravovať zobrazené polia kontaktov</string>
|
||||
<string name="filter_duplicates">Pokúsiť sa vyfiltrovať duplicitné kontakty</string>
|
||||
<string name="manage_shown_tabs">Spravovať zobrazené karty</string>
|
||||
<string name="contacts">Kontakty</string>
|
||||
<string name="favorites">Obľúbené</string>
|
||||
<string name="recent_calls">Predošlé hovory</string>
|
||||
<string name="show_call_confirmation_dialog">Zobraziť pred spustením hovoru okno na jeho potvrdenie</string>
|
||||
|
||||
<!-- Emails -->
|
||||
<string name="email">Email</string>
|
||||
|
@ -13,6 +13,8 @@
|
||||
<string name="send_email_to_contacts">Skicka e-post till kontakter</string>
|
||||
<string name="send_sms_to_group">Skicka sms till grupp</string>
|
||||
<string name="send_email_to_group">Skicka e-post till grupp</string>
|
||||
<string name="call_person">Ring %s</string>
|
||||
<string name="request_the_required_permissions">Begär de behörigheter som krävs</string>
|
||||
|
||||
<string name="new_contact">Ny kontakt</string>
|
||||
<string name="edit_contact">Redigera kontakt</string>
|
||||
@ -21,6 +23,7 @@
|
||||
<string name="first_name">Förnamn</string>
|
||||
<string name="middle_name">Mellannamn</string>
|
||||
<string name="surname">Efternamn</string>
|
||||
<string name="nickname">Smeknamn</string>
|
||||
|
||||
<!-- Groups -->
|
||||
<string name="no_groups">Inga grupper</string>
|
||||
@ -45,10 +48,13 @@
|
||||
<string name="on_contact_click">Vid kontakttryckning</string>
|
||||
<string name="call_contact">Ring kontakt</string>
|
||||
<string name="view_contact">Visa kontaktuppgifter</string>
|
||||
<string name="show_favorites_tab">Visa fliken Favoriter</string>
|
||||
<string name="show_groups_tab">Visa fliken Grupper</string>
|
||||
<string name="manage_shown_contact_fields">Hantera visade kontaktfält</string>
|
||||
<string name="filter_duplicates">Try filtering out duplicate contacts</string>
|
||||
<string name="filter_duplicates">Försök filtrera bort dubblettkontakter</string>
|
||||
<string name="manage_shown_tabs">Hantera visade flikar</string>
|
||||
<string name="contacts">Kontakter</string>
|
||||
<string name="favorites">Favoriter</string>
|
||||
<string name="recent_calls">Senaste samtal</string>
|
||||
<string name="show_call_confirmation_dialog">Visa en bekräftelsedialogruta före uppringning</string>
|
||||
|
||||
<!-- Emails -->
|
||||
<string name="email">E-post</string>
|
||||
@ -74,7 +80,7 @@
|
||||
<string name="add_favorites">Lägg till favoriter</string>
|
||||
<string name="add_to_favorites">Lägg till i favoriter</string>
|
||||
<string name="remove_from_favorites">Ta bort från favoriter</string>
|
||||
<string name="must_be_at_edit">You must be at the Edit screen to modify a contact</string>
|
||||
<string name="must_be_at_edit">Kontakter kan bara redigeras i redigeringsvyn</string>
|
||||
|
||||
<!-- Search -->
|
||||
<string name="search_contacts">Sök efter kontakter</string>
|
||||
|
133
app/src/main/res/values-tr/strings.xml
Normal file
@ -0,0 +1,133 @@
|
||||
<resources>
|
||||
<string name="app_name">Basit Kişiler</string>
|
||||
<string name="app_launcher_name">Kişiler</string>
|
||||
<string name="address">Adres</string>
|
||||
<string name="inserting">Ekleniyor…</string>
|
||||
<string name="updating">Güncelleniyor…</string>
|
||||
<string name="phone_storage">Telefon belleği</string>
|
||||
<string name="phone_storage_hidden">Telefon belleği (diğer uygulamalar tarafından görülmez)</string>
|
||||
<string name="company">Şirket</string>
|
||||
<string name="job_position">İş pozisyonu</string>
|
||||
<string name="website">Web sitesi</string>
|
||||
<string name="send_sms_to_contacts">Kişilere SMS gönder</string>
|
||||
<string name="send_email_to_contacts">Kişilere e-posta gönder</string>
|
||||
<string name="send_sms_to_group">Gruba SMS gönder</string>
|
||||
<string name="send_email_to_group">Gruba e-posta gönder</string>
|
||||
<string name="call_person">Call %s</string>
|
||||
<string name="request_the_required_permissions">Request the required permissions</string>
|
||||
|
||||
<string name="new_contact">Yeni kişi</string>
|
||||
<string name="edit_contact">Kişiyi düzenle</string>
|
||||
<string name="select_contact">Kişi seç</string>
|
||||
<string name="select_contacts">Kişileri seç</string>
|
||||
<string name="first_name">Adı</string>
|
||||
<string name="middle_name">Göbek adı</string>
|
||||
<string name="surname">Soyadı</string>
|
||||
<string name="nickname">Nickname</string>
|
||||
|
||||
<!-- Groups -->
|
||||
<string name="no_groups">Grup yok</string>
|
||||
<string name="create_new_group">Yeni grup oluştur</string>
|
||||
<string name="remove_from_group">Gruptan kaldır</string>
|
||||
<string name="no_group_participants">Bu grup boş</string>
|
||||
<string name="add_contacts">Kişi ekle</string>
|
||||
<string name="no_group_created">Cihazda kişi grubu yok</string>
|
||||
<string name="create_group">Grup oluştur</string>
|
||||
<string name="add_to_group">Gruba ekle</string>
|
||||
<string name="create_group_under_account">Hesap altında grup oluştur</string>
|
||||
|
||||
<!-- Photo -->
|
||||
<string name="take_photo">Fotoğraf çek</string>
|
||||
<string name="choose_photo">Fotoğraf seç</string>
|
||||
<string name="remove_photo">Fotoğrafı kaldır</string>
|
||||
|
||||
<!-- Settings -->
|
||||
<string name="start_name_with_surname">Soyadı ile başla</string>
|
||||
<string name="show_phone_numbers">Ana ekranda telefon numaralarını göster</string>
|
||||
<string name="show_contact_thumbnails">Kişi küçük resimlerini göster</string>
|
||||
<string name="on_contact_click">Kişi tıklandığında</string>
|
||||
<string name="call_contact">Kişiyi ara</string>
|
||||
<string name="view_contact">Kişi bilgilerini göster</string>
|
||||
<string name="manage_shown_contact_fields">Görüntülenecek kişi alanlarını yönet</string>
|
||||
<string name="filter_duplicates">Çift kişileri filtrelemeyi dene</string>
|
||||
<string name="manage_shown_tabs">Manage shown tabs</string>
|
||||
<string name="contacts">Contacts</string>
|
||||
<string name="favorites">Favorites</string>
|
||||
<string name="recent_calls">Recent calls</string>
|
||||
<string name="show_call_confirmation_dialog">Show a call confirmation dialog before initiating a call</string>
|
||||
|
||||
<!-- Emails -->
|
||||
<string name="email">E-posta</string>
|
||||
<string name="home">Ev</string>
|
||||
<string name="work">İş</string>
|
||||
<string name="other">Diğer</string>
|
||||
|
||||
<!-- Phone numbers -->
|
||||
<string name="number">Numara</string>
|
||||
<string name="mobile">Cep</string>
|
||||
<string name="main_number">Ana</string>
|
||||
<string name="work_fax">İş Faksı</string>
|
||||
<string name="home_fax">Ev Faksı</string>
|
||||
<string name="pager">Çağrı Cihazı</string>
|
||||
<string name="no_phone_number_found">Telefon numarası bulunamadı</string>
|
||||
|
||||
<!-- Events -->
|
||||
<string name="birthday">Doğum günü</string>
|
||||
<string name="anniversary">Yıldönümü</string>
|
||||
|
||||
<!-- Favorites -->
|
||||
<string name="no_favorites">Henüz hiç favori kişi eklemediniz gibi görünüyor.</string>
|
||||
<string name="add_favorites">Favorilerini ekle</string>
|
||||
<string name="add_to_favorites">Favorilere ekle</string>
|
||||
<string name="remove_from_favorites">Favorilerden kaldır</string>
|
||||
<string name="must_be_at_edit">Bir kişiyi değiştirmek için Düzen ekranında olmalısınız</string>
|
||||
|
||||
<!-- Search -->
|
||||
<string name="search_contacts">Kişileri ara</string>
|
||||
<string name="search_favorites">Favorileri ara</string>
|
||||
|
||||
<!-- Export / Import -->
|
||||
<string name="import_contacts">Kişileri içe aktar</string>
|
||||
<string name="export_contacts">Kişileri dışa aktar</string>
|
||||
<string name="import_contacts_from_vcf">Kişileri bir .vcf dosyasından içe aktar</string>
|
||||
<string name="export_contacts_to_vcf">Kişileri bir .vcf dosyasına aktar</string>
|
||||
<string name="target_contact_source">Hedef kişi kaynağı</string>
|
||||
<string name="include_contact_sources">Kişi kaynaklarını dahil et</string>
|
||||
<string name="filename_without_vcf">Dosya adı (.vcf olmadan)</string>
|
||||
|
||||
<!-- Visible fields -->
|
||||
<string name="select_fields_to_show">Görüntülenecek alanları seç</string>
|
||||
<string name="prefix">Önek</string>
|
||||
<string name="suffix">Sonek</string>
|
||||
<string name="phone_numbers">Telefon numaraları</string>
|
||||
<string name="emails">E-postalar</string>
|
||||
<string name="addresses">Adresler</string>
|
||||
<string name="events">Etkinlikler (doğum günleri, yıldönümleri)</string>
|
||||
<string name="notes">Notlar</string>
|
||||
<string name="organization">Organizasyon</string>
|
||||
<string name="websites">Web siteleri</string>
|
||||
<string name="groups">Gruplar</string>
|
||||
<string name="contact_source">Kişi kaynağı</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">Rehberde görüntülenecek alanları değiştirmek istiyorum. Bunu yapabilir miyim?</string>
|
||||
<string name="faq_1_text">Evet, tek yapmanız gereken Ayarlar -> Görüntülenecek kişi alanlarını yönet\'e gitmek. Orada hangi alanların görüntüleneceğini seçebilirsiniz. Bazıları varsayılan olarak devre dışı bile olsa, orada bazı yenilerini bulabilirsiniz.</string>
|
||||
|
||||
<!-- Strings displayed only on Google Playstore. Optional, but good to have -->
|
||||
<!-- Short description has to have less than 80 chars -->
|
||||
<string name="app_short_description">Kişilerinizi reklamsız yönetmek için bir kişiler uygulaması.</string>
|
||||
<string name="app_long_description">
|
||||
Kişilerinizi herhangi bir kaynaktan oluşturmak veya yönetmek için basit bir uygulama. Kişiler yalnızca cihazınızda saklanabilir, aynı zamanda Google veya diğer hesaplarla senkronize edilebilir. Favori kişilerinizi ayrı bir listede görüntüleyebilirsiniz.
|
||||
|
||||
Kullanıcı e-postalarını ve etkinliklerini yönetmek için de kullanabilirsiniz. Birden çok parametreye göre sıralama/filtreleme, isteğe bağlı olarak soyadı ilk ad olarak görüntüleme yeteneğine sahiptir.
|
||||
|
||||
Reklam veya gereksiz izinler içermez. Tamamen açık kaynaktır, özelleştirilebilir renkler sağlar.
|
||||
|
||||
Bu uygulama, daha büyük bir uygulama serisinden sadece bir parça. Geri kalanı http://www.simplemobiletools.com adresinde bulabilirsiniz
|
||||
</string>
|
||||
|
||||
<!--
|
||||
Haven't found some strings? There's more at
|
||||
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
|
||||
-->
|
||||
</resources>
|
@ -8,11 +8,13 @@
|
||||
<string name="phone_storage_hidden">手機空間 (其他程式不可見)</string>
|
||||
<string name="company">公司</string>
|
||||
<string name="job_position">職位</string>
|
||||
<string name="website">Website</string>
|
||||
<string name="send_sms_to_contacts">Send SMS to contacts</string>
|
||||
<string name="send_email_to_contacts">Send email to contacts</string>
|
||||
<string name="send_sms_to_group">Send SMS to group</string>
|
||||
<string name="send_email_to_group">Send email to group</string>
|
||||
<string name="website">網站</string>
|
||||
<string name="send_sms_to_contacts">發送簡訊給聯絡人</string>
|
||||
<string name="send_email_to_contacts">發送電子郵件給聯絡人</string>
|
||||
<string name="send_sms_to_group">發送簡訊給群組</string>
|
||||
<string name="send_email_to_group">發送電子郵件給群組</string>
|
||||
<string name="call_person">打電話給 %s</string>
|
||||
<string name="request_the_required_permissions">請求必要的權限</string>
|
||||
|
||||
<string name="new_contact">新聯絡人</string>
|
||||
<string name="edit_contact">編輯聯絡人</string>
|
||||
@ -21,6 +23,7 @@
|
||||
<string name="first_name">名字</string>
|
||||
<string name="middle_name">中間名</string>
|
||||
<string name="surname">姓氏</string>
|
||||
<string name="nickname">Nickname</string>
|
||||
|
||||
<!-- Groups -->
|
||||
<string name="no_groups">沒有群組</string>
|
||||
@ -45,10 +48,13 @@
|
||||
<string name="on_contact_click">點擊聯絡人</string>
|
||||
<string name="call_contact">打電話給聯絡人</string>
|
||||
<string name="view_contact">顯示聯絡人資料</string>
|
||||
<string name="show_favorites_tab">顯示我的最愛頁面</string>
|
||||
<string name="show_groups_tab">顯示群組頁面</string>
|
||||
<string name="manage_shown_contact_fields">管理顯示的聯絡人欄位</string>
|
||||
<string name="filter_duplicates">Try filtering out duplicate contacts</string>
|
||||
<string name="filter_duplicates">試著過濾重複的聯絡人</string>
|
||||
<string name="manage_shown_tabs">管理顯示的頁面</string>
|
||||
<string name="contacts">聯絡人</string>
|
||||
<string name="favorites">我的最愛</string>
|
||||
<string name="recent_calls">通話紀錄</string>
|
||||
<string name="show_call_confirmation_dialog">開始通話前顯示通話確認框</string>
|
||||
|
||||
<!-- Emails -->
|
||||
<string name="email">電子信箱</string>
|
||||
@ -74,7 +80,7 @@
|
||||
<string name="add_favorites">添加我的最愛</string>
|
||||
<string name="add_to_favorites">加入我的最愛</string>
|
||||
<string name="remove_from_favorites">從我的最愛移除</string>
|
||||
<string name="must_be_at_edit">You must be at the Edit screen to modify a contact</string>
|
||||
<string name="must_be_at_edit">你必須在編輯畫面去修改聯絡人</string>
|
||||
|
||||
<!-- Search -->
|
||||
<string name="search_contacts">搜尋聯絡人</string>
|
||||
@ -99,7 +105,7 @@
|
||||
<string name="events">活動 (生日、紀念日)</string>
|
||||
<string name="notes">筆記</string>
|
||||
<string name="organization">組織</string>
|
||||
<string name="websites">Websites</string>
|
||||
<string name="websites">網站</string>
|
||||
<string name="groups">群組</string>
|
||||
<string name="contact_source">聯絡人來源</string>
|
||||
|
||||
|
@ -2,6 +2,11 @@
|
||||
<resources>
|
||||
|
||||
<!-- Release notes -->
|
||||
<string name="release_29">Added an optional Nickname field</string>
|
||||
<string name="release_27">
|
||||
Allow customizing which tabs are visible\n
|
||||
Added an optional call confirmation dialog
|
||||
</string>
|
||||
<string name="release_16">
|
||||
Added name prefix/suffix and contact organizations\n
|
||||
Added a settings item \"Manage shown contact fields\" for customizing visible contact details, with some fields disabled by default
|
||||
|
@ -13,6 +13,8 @@
|
||||
<string name="send_email_to_contacts">Send email to contacts</string>
|
||||
<string name="send_sms_to_group">Send SMS to group</string>
|
||||
<string name="send_email_to_group">Send email to group</string>
|
||||
<string name="call_person">Call %s</string>
|
||||
<string name="request_the_required_permissions">Request the required permissions</string>
|
||||
|
||||
<string name="new_contact">New contact</string>
|
||||
<string name="edit_contact">Edit contact</string>
|
||||
@ -21,6 +23,7 @@
|
||||
<string name="first_name">First name</string>
|
||||
<string name="middle_name">Middle name</string>
|
||||
<string name="surname">Surname</string>
|
||||
<string name="nickname">Nickname</string>
|
||||
|
||||
<!-- Groups -->
|
||||
<string name="no_groups">No groups</string>
|
||||
@ -45,10 +48,13 @@
|
||||
<string name="on_contact_click">On contact click</string>
|
||||
<string name="call_contact">Call contact</string>
|
||||
<string name="view_contact">View contact details</string>
|
||||
<string name="show_favorites_tab">Show favorites tab</string>
|
||||
<string name="show_groups_tab">Show groups tab</string>
|
||||
<string name="manage_shown_contact_fields">Manage shown contact fields</string>
|
||||
<string name="filter_duplicates">Try filtering out duplicate contacts</string>
|
||||
<string name="manage_shown_tabs">Manage shown tabs</string>
|
||||
<string name="contacts">Contacts</string>
|
||||
<string name="favorites">Favorites</string>
|
||||
<string name="recent_calls">Recent calls</string>
|
||||
<string name="show_call_confirmation_dialog">Show a call confirmation dialog before initiating a call</string>
|
||||
|
||||
<!-- Emails -->
|
||||
<string name="email">Email</string>
|
||||
|
@ -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.2.41'
|
||||
ext.kotlin_version = '1.2.61'
|
||||
|
||||
repositories {
|
||||
google()
|
||||
@ -9,7 +9,7 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.1.2'
|
||||
classpath 'com.android.tools.build:gradle:3.1.4'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
After Width: | Height: | Size: 95 KiB |
After Width: | Height: | Size: 106 KiB |