Merge pull request #945 from ismailnurudeen/refactor/common-contacts

feat: moved sharable contacts code to commons
This commit is contained in:
Tibor Kaputa 2023-02-24 16:24:00 +01:00 committed by GitHub
commit 2fbd044a2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 63 additions and 2784 deletions

View File

@ -24,12 +24,12 @@ import com.bumptech.glide.request.target.Target
import com.simplemobiletools.commons.dialogs.ConfirmationDialog import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.dialogs.RadioGroupDialog import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ContactsHelper
import com.simplemobiletools.commons.helpers.letterBackgroundColors import com.simplemobiletools.commons.helpers.letterBackgroundColors
import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.extensions.shareContacts import com.simplemobiletools.contacts.pro.extensions.shareContacts
import com.simplemobiletools.contacts.pro.helpers.ContactsHelper import com.simplemobiletools.commons.models.contacts.Contact
import com.simplemobiletools.contacts.pro.models.Contact
abstract class ContactActivity : SimpleActivity() { abstract class ContactActivity : SimpleActivity() {
protected val PICK_RINGTONE_INTENT_ID = 1500 protected val PICK_RINGTONE_INTENT_ID = 1500

View File

@ -29,6 +29,10 @@ import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.PhoneNumber import com.simplemobiletools.commons.models.PhoneNumber
import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.commons.models.contacts.*
import com.simplemobiletools.commons.models.contacts.Email
import com.simplemobiletools.commons.models.contacts.Event
import com.simplemobiletools.commons.models.contacts.Organization
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.dialogs.CustomLabelDialog import com.simplemobiletools.contacts.pro.dialogs.CustomLabelDialog
import com.simplemobiletools.contacts.pro.dialogs.ManageVisibleFieldsDialog import com.simplemobiletools.contacts.pro.dialogs.ManageVisibleFieldsDialog
@ -36,10 +40,6 @@ import com.simplemobiletools.contacts.pro.dialogs.MyDatePickerDialog
import com.simplemobiletools.contacts.pro.dialogs.SelectGroupsDialog import com.simplemobiletools.contacts.pro.dialogs.SelectGroupsDialog
import com.simplemobiletools.contacts.pro.extensions.* import com.simplemobiletools.contacts.pro.extensions.*
import com.simplemobiletools.contacts.pro.helpers.* import com.simplemobiletools.contacts.pro.helpers.*
import com.simplemobiletools.contacts.pro.models.*
import com.simplemobiletools.contacts.pro.models.Email
import com.simplemobiletools.contacts.pro.models.Event
import com.simplemobiletools.contacts.pro.models.Organization
import kotlinx.android.synthetic.main.activity_edit_contact.* import kotlinx.android.synthetic.main.activity_edit_contact.*
import kotlinx.android.synthetic.main.item_edit_address.view.* import kotlinx.android.synthetic.main.item_edit_address.view.*
import kotlinx.android.synthetic.main.item_edit_email.view.* import kotlinx.android.synthetic.main.item_edit_email.view.*

View File

@ -7,19 +7,18 @@ import android.net.Uri
import android.os.Bundle import android.os.Bundle
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ContactsHelper
import com.simplemobiletools.commons.helpers.NavigationIcon import com.simplemobiletools.commons.helpers.NavigationIcon
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.adapters.ContactsAdapter import com.simplemobiletools.contacts.pro.adapters.ContactsAdapter
import com.simplemobiletools.contacts.pro.dialogs.SelectContactsDialog import com.simplemobiletools.contacts.pro.dialogs.SelectContactsDialog
import com.simplemobiletools.contacts.pro.extensions.* import com.simplemobiletools.contacts.pro.extensions.*
import com.simplemobiletools.contacts.pro.helpers.ContactsHelper
import com.simplemobiletools.contacts.pro.helpers.GROUP import com.simplemobiletools.contacts.pro.helpers.GROUP
import com.simplemobiletools.contacts.pro.helpers.LOCATION_GROUP_CONTACTS import com.simplemobiletools.contacts.pro.helpers.LOCATION_GROUP_CONTACTS
import com.simplemobiletools.contacts.pro.interfaces.RefreshContactsListener import com.simplemobiletools.contacts.pro.interfaces.RefreshContactsListener
import com.simplemobiletools.contacts.pro.interfaces.RemoveFromGroupListener import com.simplemobiletools.contacts.pro.interfaces.RemoveFromGroupListener
import com.simplemobiletools.contacts.pro.models.Contact import com.simplemobiletools.commons.models.contacts.*
import com.simplemobiletools.contacts.pro.models.Group
import kotlinx.android.synthetic.main.activity_group_contacts.* import kotlinx.android.synthetic.main.activity_group_contacts.*
class GroupContactsActivity : SimpleActivity(), RemoveFromGroupListener, RefreshContactsListener { class GroupContactsActivity : SimpleActivity(), RemoveFromGroupListener, RefreshContactsListener {

View File

@ -13,19 +13,17 @@ import android.widget.TextView
import androidx.viewpager.widget.ViewPager import androidx.viewpager.widget.ViewPager
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.contacts.*
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.adapters.ViewPagerAdapter import com.simplemobiletools.contacts.pro.adapters.ViewPagerAdapter
import com.simplemobiletools.contacts.pro.dialogs.ChangeSortingDialog import com.simplemobiletools.contacts.pro.dialogs.ChangeSortingDialog
import com.simplemobiletools.contacts.pro.dialogs.FilterContactSourcesDialog import com.simplemobiletools.contacts.pro.dialogs.FilterContactSourcesDialog
import com.simplemobiletools.contacts.pro.extensions.config import com.simplemobiletools.contacts.pro.extensions.config
import com.simplemobiletools.contacts.pro.extensions.getContactPublicUri
import com.simplemobiletools.contacts.pro.fragments.MyViewPagerFragment import com.simplemobiletools.contacts.pro.fragments.MyViewPagerFragment
import com.simplemobiletools.contacts.pro.helpers.ADD_NEW_CONTACT_NUMBER import com.simplemobiletools.contacts.pro.helpers.ADD_NEW_CONTACT_NUMBER
import com.simplemobiletools.contacts.pro.helpers.ContactsHelper
import com.simplemobiletools.contacts.pro.helpers.KEY_EMAIL import com.simplemobiletools.contacts.pro.helpers.KEY_EMAIL
import com.simplemobiletools.contacts.pro.helpers.KEY_NAME import com.simplemobiletools.contacts.pro.helpers.KEY_NAME
import com.simplemobiletools.contacts.pro.interfaces.RefreshContactsListener import com.simplemobiletools.contacts.pro.interfaces.RefreshContactsListener
import com.simplemobiletools.contacts.pro.models.Contact
import kotlinx.android.synthetic.main.activity_insert_edit_contact.* import kotlinx.android.synthetic.main.activity_insert_edit_contact.*
import kotlinx.android.synthetic.main.fragment_contacts.* import kotlinx.android.synthetic.main.fragment_contacts.*
import kotlinx.android.synthetic.main.fragment_favorites.* import kotlinx.android.synthetic.main.fragment_favorites.*

View File

@ -14,31 +14,28 @@ import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.viewpager.widget.ViewPager import androidx.viewpager.widget.ViewPager
import com.simplemobiletools.commons.databases.ContactsDatabase
import com.simplemobiletools.commons.dialogs.ConfirmationDialog import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.dialogs.FilePickerDialog import com.simplemobiletools.commons.dialogs.FilePickerDialog
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.FAQItem import com.simplemobiletools.commons.models.FAQItem
import com.simplemobiletools.commons.models.Release import com.simplemobiletools.commons.models.Release
import com.simplemobiletools.commons.models.contacts.*
import com.simplemobiletools.contacts.pro.BuildConfig import com.simplemobiletools.contacts.pro.BuildConfig
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.adapters.ViewPagerAdapter import com.simplemobiletools.contacts.pro.adapters.ViewPagerAdapter
import com.simplemobiletools.contacts.pro.databases.ContactsDatabase
import com.simplemobiletools.contacts.pro.dialogs.ChangeSortingDialog import com.simplemobiletools.contacts.pro.dialogs.ChangeSortingDialog
import com.simplemobiletools.contacts.pro.dialogs.ExportContactsDialog import com.simplemobiletools.contacts.pro.dialogs.ExportContactsDialog
import com.simplemobiletools.contacts.pro.dialogs.FilterContactSourcesDialog import com.simplemobiletools.contacts.pro.dialogs.FilterContactSourcesDialog
import com.simplemobiletools.contacts.pro.dialogs.ImportContactsDialog import com.simplemobiletools.contacts.pro.dialogs.ImportContactsDialog
import com.simplemobiletools.contacts.pro.extensions.config import com.simplemobiletools.contacts.pro.extensions.config
import com.simplemobiletools.contacts.pro.extensions.getTempFile
import com.simplemobiletools.contacts.pro.extensions.handleGenericContactClick import com.simplemobiletools.contacts.pro.extensions.handleGenericContactClick
import com.simplemobiletools.contacts.pro.fragments.FavoritesFragment import com.simplemobiletools.contacts.pro.fragments.FavoritesFragment
import com.simplemobiletools.contacts.pro.fragments.MyViewPagerFragment import com.simplemobiletools.contacts.pro.fragments.MyViewPagerFragment
import com.simplemobiletools.contacts.pro.helpers.ALL_TABS_MASK
import com.simplemobiletools.contacts.pro.helpers.ContactsHelper
import com.simplemobiletools.contacts.pro.helpers.VcfExporter import com.simplemobiletools.contacts.pro.helpers.VcfExporter
import com.simplemobiletools.contacts.pro.helpers.tabsList import com.simplemobiletools.contacts.pro.helpers.tabsList
import com.simplemobiletools.contacts.pro.interfaces.RefreshContactsListener import com.simplemobiletools.contacts.pro.interfaces.RefreshContactsListener
import com.simplemobiletools.contacts.pro.models.Contact
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.fragment_contacts.* import kotlinx.android.synthetic.main.fragment_contacts.*
import kotlinx.android.synthetic.main.fragment_favorites.* import kotlinx.android.synthetic.main.fragment_favorites.*

View File

@ -9,9 +9,6 @@ import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.dialogs.ManageVisibleFieldsDialog import com.simplemobiletools.contacts.pro.dialogs.ManageVisibleFieldsDialog
import com.simplemobiletools.contacts.pro.dialogs.ManageVisibleTabsDialog import com.simplemobiletools.contacts.pro.dialogs.ManageVisibleTabsDialog
import com.simplemobiletools.contacts.pro.extensions.config import com.simplemobiletools.contacts.pro.extensions.config
import com.simplemobiletools.contacts.pro.helpers.ON_CLICK_CALL_CONTACT
import com.simplemobiletools.contacts.pro.helpers.ON_CLICK_EDIT_CONTACT
import com.simplemobiletools.contacts.pro.helpers.ON_CLICK_VIEW_CONTACT
import kotlinx.android.synthetic.main.activity_settings.* import kotlinx.android.synthetic.main.activity_settings.*
import java.util.* import java.util.*

View File

@ -22,12 +22,12 @@ import com.simplemobiletools.commons.dialogs.SelectAlarmSoundDialog
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.PhoneNumber import com.simplemobiletools.commons.models.PhoneNumber
import com.simplemobiletools.commons.models.contacts.*
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.dialogs.ChooseSocialDialog import com.simplemobiletools.contacts.pro.dialogs.ChooseSocialDialog
import com.simplemobiletools.contacts.pro.dialogs.ManageVisibleFieldsDialog import com.simplemobiletools.contacts.pro.dialogs.ManageVisibleFieldsDialog
import com.simplemobiletools.contacts.pro.extensions.* import com.simplemobiletools.contacts.pro.extensions.*
import com.simplemobiletools.contacts.pro.helpers.* import com.simplemobiletools.contacts.pro.helpers.*
import com.simplemobiletools.contacts.pro.models.*
import kotlinx.android.synthetic.main.activity_view_contact.* import kotlinx.android.synthetic.main.activity_view_contact.*
import kotlinx.android.synthetic.main.item_view_address.view.* import kotlinx.android.synthetic.main.item_view_address.view.*
import kotlinx.android.synthetic.main.item_view_contact_source.view.* import kotlinx.android.synthetic.main.item_view_contact_source.view.*

View File

@ -28,10 +28,12 @@ import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.dialogs.RadioGroupDialog import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.helpers.ContactsHelper
import com.simplemobiletools.commons.interfaces.ItemMoveCallback import com.simplemobiletools.commons.interfaces.ItemMoveCallback
import com.simplemobiletools.commons.interfaces.ItemTouchHelperContract import com.simplemobiletools.commons.interfaces.ItemTouchHelperContract
import com.simplemobiletools.commons.interfaces.StartReorderDragListener import com.simplemobiletools.commons.interfaces.StartReorderDragListener
import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.commons.models.contacts.Contact
import com.simplemobiletools.commons.views.MyRecyclerView import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.activities.SimpleActivity import com.simplemobiletools.contacts.pro.activities.SimpleActivity
@ -41,7 +43,7 @@ import com.simplemobiletools.contacts.pro.extensions.*
import com.simplemobiletools.contacts.pro.helpers.* import com.simplemobiletools.contacts.pro.helpers.*
import com.simplemobiletools.contacts.pro.interfaces.RefreshContactsListener import com.simplemobiletools.contacts.pro.interfaces.RefreshContactsListener
import com.simplemobiletools.contacts.pro.interfaces.RemoveFromGroupListener import com.simplemobiletools.contacts.pro.interfaces.RemoveFromGroupListener
import com.simplemobiletools.contacts.pro.models.Contact import com.simplemobiletools.commons.models.contacts.*
import java.util.* import java.util.*
class ContactsAdapter( class ContactsAdapter(

View File

@ -7,9 +7,9 @@ import com.simplemobiletools.commons.extensions.getProperBackgroundColor
import com.simplemobiletools.commons.extensions.getProperPrimaryColor import com.simplemobiletools.commons.extensions.getProperPrimaryColor
import com.simplemobiletools.commons.extensions.getProperTextColor import com.simplemobiletools.commons.extensions.getProperTextColor
import com.simplemobiletools.commons.helpers.SMT_PRIVATE import com.simplemobiletools.commons.helpers.SMT_PRIVATE
import com.simplemobiletools.commons.models.contacts.ContactSource
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.activities.SimpleActivity import com.simplemobiletools.contacts.pro.activities.SimpleActivity
import com.simplemobiletools.contacts.pro.models.ContactSource
import kotlinx.android.synthetic.main.item_filter_contact_source.view.* import kotlinx.android.synthetic.main.item_filter_contact_source.view.*
class FilterContactSourcesAdapter( class FilterContactSourcesAdapter(

View File

@ -7,9 +7,7 @@ import android.view.ViewGroup
import com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller import com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.dialogs.ConfirmationDialog import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.extensions.beVisibleIf import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.extensions.getTextSize
import com.simplemobiletools.commons.extensions.highlightTextPart
import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.SimpleContactsHelper
import com.simplemobiletools.commons.helpers.TAB_GROUPS import com.simplemobiletools.commons.helpers.TAB_GROUPS
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
@ -17,11 +15,10 @@ import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.activities.SimpleActivity import com.simplemobiletools.contacts.pro.activities.SimpleActivity
import com.simplemobiletools.contacts.pro.dialogs.RenameGroupDialog import com.simplemobiletools.contacts.pro.dialogs.RenameGroupDialog
import com.simplemobiletools.commons.helpers.ContactsHelper
import com.simplemobiletools.commons.models.contacts.Group
import com.simplemobiletools.contacts.pro.extensions.config import com.simplemobiletools.contacts.pro.extensions.config
import com.simplemobiletools.contacts.pro.extensions.groupsDB
import com.simplemobiletools.contacts.pro.helpers.ContactsHelper
import com.simplemobiletools.contacts.pro.interfaces.RefreshContactsListener import com.simplemobiletools.contacts.pro.interfaces.RefreshContactsListener
import com.simplemobiletools.contacts.pro.models.Group
import kotlinx.android.synthetic.main.item_group.view.* import kotlinx.android.synthetic.main.item_group.view.*
import java.util.* import java.util.*

View File

@ -12,11 +12,11 @@ import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.signature.ObjectKey import com.bumptech.glide.signature.ObjectKey
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.SimpleContactsHelper
import com.simplemobiletools.commons.models.contacts.*
import com.simplemobiletools.commons.views.MyRecyclerView import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.activities.SimpleActivity import com.simplemobiletools.contacts.pro.activities.SimpleActivity
import com.simplemobiletools.contacts.pro.extensions.config import com.simplemobiletools.contacts.pro.extensions.config
import com.simplemobiletools.contacts.pro.models.Contact
import kotlinx.android.synthetic.main.item_add_favorite_with_number.view.* import kotlinx.android.synthetic.main.item_add_favorite_with_number.view.*
class SelectContactsAdapter( class SelectContactsAdapter(

View File

@ -7,8 +7,8 @@ import android.database.MatrixCursor
import android.net.Uri import android.net.Uri
import com.google.gson.Gson import com.google.gson.Gson
import com.simplemobiletools.commons.helpers.MyContactsContentProvider import com.simplemobiletools.commons.helpers.MyContactsContentProvider
import com.simplemobiletools.commons.helpers.LocalContactsHelper
import com.simplemobiletools.contacts.pro.extensions.config import com.simplemobiletools.contacts.pro.extensions.config
import com.simplemobiletools.contacts.pro.helpers.LocalContactsHelper
class MyContactsContentProvider : ContentProvider() { class MyContactsContentProvider : ContentProvider() {
override fun insert(uri: Uri, contentValues: ContentValues?) = null override fun insert(uri: Uri, contentValues: ContentValues?) = null

View File

@ -1,90 +0,0 @@
package com.simplemobiletools.contacts.pro.databases
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.simplemobiletools.contacts.pro.helpers.Converters
import com.simplemobiletools.contacts.pro.helpers.FIRST_CONTACT_ID
import com.simplemobiletools.contacts.pro.helpers.FIRST_GROUP_ID
import com.simplemobiletools.contacts.pro.helpers.getEmptyLocalContact
import com.simplemobiletools.contacts.pro.interfaces.ContactsDao
import com.simplemobiletools.contacts.pro.interfaces.GroupsDao
import com.simplemobiletools.contacts.pro.models.Group
import com.simplemobiletools.contacts.pro.models.LocalContact
import java.util.concurrent.Executors
@Database(entities = [LocalContact::class, Group::class], version = 3)
@TypeConverters(Converters::class)
abstract class ContactsDatabase : RoomDatabase() {
abstract fun ContactsDao(): ContactsDao
abstract fun GroupsDao(): GroupsDao
companion object {
private var db: ContactsDatabase? = null
fun getInstance(context: Context): ContactsDatabase {
if (db == null) {
synchronized(ContactsDatabase::class) {
if (db == null) {
db = Room.databaseBuilder(context.applicationContext, ContactsDatabase::class.java, "local_contacts.db")
.addCallback(object : Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
increaseAutoIncrementIds()
}
})
.addMigrations(MIGRATION_1_2)
.addMigrations(MIGRATION_2_3)
.build()
}
}
}
return db!!
}
fun destroyInstance() {
db = null
}
// start autoincrement ID from FIRST_CONTACT_ID/FIRST_GROUP_ID to avoid conflicts
// Room doesn't seem to have a built in way for it, so just create a contact/group and delete it
private fun increaseAutoIncrementIds() {
Executors.newSingleThreadExecutor().execute {
val emptyContact = getEmptyLocalContact()
emptyContact.id = FIRST_CONTACT_ID
db!!.ContactsDao().apply {
insertOrUpdate(emptyContact)
deleteContactId(FIRST_CONTACT_ID)
}
val emptyGroup = Group(FIRST_GROUP_ID, "")
db!!.GroupsDao().apply {
insertOrUpdate(emptyGroup)
deleteGroupId(FIRST_GROUP_ID)
}
}
}
private val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.apply {
execSQL("ALTER TABLE contacts ADD COLUMN photo_uri TEXT NOT NULL DEFAULT ''")
}
}
}
private val MIGRATION_2_3 = object : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
database.apply {
execSQL("ALTER TABLE contacts ADD COLUMN ringtone TEXT DEFAULT ''")
}
}
}
}
}

View File

@ -8,9 +8,9 @@ import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.extensions.beGone import com.simplemobiletools.commons.extensions.beGone
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.models.contacts.SocialAction
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.extensions.getPackageDrawable import com.simplemobiletools.contacts.pro.extensions.getPackageDrawable
import com.simplemobiletools.contacts.pro.models.SocialAction
import kotlinx.android.synthetic.main.dialog_choose_social.view.* import kotlinx.android.synthetic.main.dialog_choose_social.view.*
import kotlinx.android.synthetic.main.item_choose_social.view.* import kotlinx.android.synthetic.main.item_choose_social.view.*

View File

@ -5,13 +5,12 @@ import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.dialogs.RadioGroupDialog import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ContactsHelper
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.commons.models.contacts.ContactSource
import com.simplemobiletools.commons.models.contacts.Group
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.extensions.getPrivateContactSource
import com.simplemobiletools.contacts.pro.helpers.ContactsHelper
import com.simplemobiletools.contacts.pro.models.ContactSource
import com.simplemobiletools.contacts.pro.models.Group
import kotlinx.android.synthetic.main.dialog_create_new_group.view.* import kotlinx.android.synthetic.main.dialog_create_new_group.view.*
class CreateNewGroupDialog(val activity: BaseSimpleActivity, val callback: (newGroup: Group) -> Unit) { class CreateNewGroupDialog(val activity: BaseSimpleActivity, val callback: (newGroup: Group) -> Unit) {

View File

@ -5,15 +5,13 @@ import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.dialogs.FilePickerDialog import com.simplemobiletools.commons.dialogs.FilePickerDialog
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ContactsHelper
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.models.contacts.*
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.activities.SimpleActivity import com.simplemobiletools.contacts.pro.activities.SimpleActivity
import com.simplemobiletools.contacts.pro.adapters.FilterContactSourcesAdapter import com.simplemobiletools.contacts.pro.adapters.FilterContactSourcesAdapter
import com.simplemobiletools.contacts.pro.extensions.config import com.simplemobiletools.contacts.pro.extensions.config
import com.simplemobiletools.contacts.pro.extensions.getVisibleContactSources
import com.simplemobiletools.contacts.pro.helpers.ContactsHelper
import com.simplemobiletools.contacts.pro.models.Contact
import com.simplemobiletools.contacts.pro.models.ContactSource
import kotlinx.android.synthetic.main.dialog_export_contacts.view.* import kotlinx.android.synthetic.main.dialog_export_contacts.view.*
import java.io.File import java.io.File

View File

@ -7,11 +7,10 @@ import com.simplemobiletools.commons.helpers.SMT_PRIVATE
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.activities.SimpleActivity import com.simplemobiletools.contacts.pro.activities.SimpleActivity
import com.simplemobiletools.contacts.pro.adapters.FilterContactSourcesAdapter import com.simplemobiletools.contacts.pro.adapters.FilterContactSourcesAdapter
import com.simplemobiletools.commons.extensions.getVisibleContactSources
import com.simplemobiletools.commons.helpers.ContactsHelper
import com.simplemobiletools.commons.models.contacts.*
import com.simplemobiletools.contacts.pro.extensions.config import com.simplemobiletools.contacts.pro.extensions.config
import com.simplemobiletools.contacts.pro.extensions.getVisibleContactSources
import com.simplemobiletools.contacts.pro.helpers.ContactsHelper
import com.simplemobiletools.contacts.pro.models.Contact
import com.simplemobiletools.contacts.pro.models.ContactSource
import kotlinx.android.synthetic.main.dialog_filter_contact_sources.view.* import kotlinx.android.synthetic.main.dialog_filter_contact_sources.view.*
class FilterContactSourcesDialog(val activity: SimpleActivity, private val callback: () -> Unit) { class FilterContactSourcesDialog(val activity: SimpleActivity, private val callback: () -> Unit) {

View File

@ -2,17 +2,14 @@ package com.simplemobiletools.contacts.pro.dialogs
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.extensions.setupDialogStuff import com.simplemobiletools.commons.helpers.ContactsHelper
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.helpers.SMT_PRIVATE import com.simplemobiletools.commons.helpers.SMT_PRIVATE
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.activities.SimpleActivity import com.simplemobiletools.contacts.pro.activities.SimpleActivity
import com.simplemobiletools.contacts.pro.extensions.config import com.simplemobiletools.contacts.pro.extensions.config
import com.simplemobiletools.contacts.pro.extensions.getPublicContactSource
import com.simplemobiletools.contacts.pro.extensions.showContactSourcePicker import com.simplemobiletools.contacts.pro.extensions.showContactSourcePicker
import com.simplemobiletools.contacts.pro.helpers.ContactsHelper
import com.simplemobiletools.contacts.pro.helpers.VcfImporter import com.simplemobiletools.contacts.pro.helpers.VcfImporter
import com.simplemobiletools.contacts.pro.helpers.VcfImporter.ImportResult.IMPORT_FAIL import com.simplemobiletools.contacts.pro.helpers.VcfImporter.ImportResult.IMPORT_FAIL
import kotlinx.android.synthetic.main.dialog_import_contacts.view.* import kotlinx.android.synthetic.main.dialog_import_contacts.view.*

View File

@ -5,8 +5,8 @@ import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.views.MyAppCompatCheckbox import com.simplemobiletools.commons.views.MyAppCompatCheckbox
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.contacts.pro.extensions.config import com.simplemobiletools.contacts.pro.extensions.config
import com.simplemobiletools.contacts.pro.helpers.*
class ManageVisibleFieldsDialog(val activity: BaseSimpleActivity, val callback: (hasSomethingChanged: Boolean) -> Unit) { class ManageVisibleFieldsDialog(val activity: BaseSimpleActivity, val callback: (hasSomethingChanged: Boolean) -> Unit) {
private var view = activity.layoutInflater.inflate(R.layout.dialog_manage_visible_fields, null) private var view = activity.layoutInflater.inflate(R.layout.dialog_manage_visible_fields, null)

View File

@ -8,8 +8,8 @@ import com.simplemobiletools.commons.helpers.TAB_FAVORITES
import com.simplemobiletools.commons.helpers.TAB_GROUPS import com.simplemobiletools.commons.helpers.TAB_GROUPS
import com.simplemobiletools.commons.views.MyAppCompatCheckbox import com.simplemobiletools.commons.views.MyAppCompatCheckbox
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.commons.helpers.ALL_TABS_MASK
import com.simplemobiletools.contacts.pro.extensions.config import com.simplemobiletools.contacts.pro.extensions.config
import com.simplemobiletools.contacts.pro.helpers.ALL_TABS_MASK
class ManageVisibleTabsDialog(val activity: BaseSimpleActivity) { class ManageVisibleTabsDialog(val activity: BaseSimpleActivity) {
private var view = activity.layoutInflater.inflate(R.layout.dialog_manage_visible_tabs, null) private var view = activity.layoutInflater.inflate(R.layout.dialog_manage_visible_tabs, null)

View File

@ -3,11 +3,10 @@ package com.simplemobiletools.contacts.pro.dialogs
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ContactsHelper
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.models.contacts.Group
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.extensions.groupsDB
import com.simplemobiletools.contacts.pro.helpers.ContactsHelper
import com.simplemobiletools.contacts.pro.models.Group
import kotlinx.android.synthetic.main.dialog_rename_group.view.* import kotlinx.android.synthetic.main.dialog_rename_group.view.*
class RenameGroupDialog(val activity: BaseSimpleActivity, val group: Group, val callback: () -> Unit) { class RenameGroupDialog(val activity: BaseSimpleActivity, val group: Group, val callback: () -> Unit) {

View File

@ -7,8 +7,7 @@ import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.activities.SimpleActivity import com.simplemobiletools.contacts.pro.activities.SimpleActivity
import com.simplemobiletools.contacts.pro.adapters.SelectContactsAdapter import com.simplemobiletools.contacts.pro.adapters.SelectContactsAdapter
import com.simplemobiletools.contacts.pro.extensions.getVisibleContactSources import com.simplemobiletools.commons.models.contacts.*
import com.simplemobiletools.contacts.pro.models.Contact
import kotlinx.android.synthetic.main.dialog_select_contact.view.* import kotlinx.android.synthetic.main.dialog_select_contact.view.*
import java.util.* import java.util.*

View File

@ -3,11 +3,11 @@ package com.simplemobiletools.contacts.pro.dialogs
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ContactsHelper
import com.simplemobiletools.commons.models.contacts.Group
import com.simplemobiletools.commons.views.MyAppCompatCheckbox import com.simplemobiletools.commons.views.MyAppCompatCheckbox
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.activities.SimpleActivity import com.simplemobiletools.contacts.pro.activities.SimpleActivity
import com.simplemobiletools.contacts.pro.helpers.ContactsHelper
import com.simplemobiletools.contacts.pro.models.Group
import kotlinx.android.synthetic.main.dialog_select_groups.view.* import kotlinx.android.synthetic.main.dialog_select_groups.view.*
import kotlinx.android.synthetic.main.item_checkbox.view.* import kotlinx.android.synthetic.main.item_checkbox.view.*
import kotlinx.android.synthetic.main.item_textview.view.* import kotlinx.android.synthetic.main.item_textview.view.*

View File

@ -7,18 +7,16 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.dialogs.CallConfirmationDialog import com.simplemobiletools.commons.dialogs.CallConfirmationDialog
import com.simplemobiletools.commons.dialogs.RadioGroupDialog import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.CONTACT_ID import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.helpers.IS_PRIVATE
import com.simplemobiletools.commons.helpers.PERMISSION_CALL_PHONE
import com.simplemobiletools.commons.helpers.SMT_PRIVATE
import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.commons.models.contacts.Contact
import com.simplemobiletools.contacts.pro.BuildConfig import com.simplemobiletools.contacts.pro.BuildConfig
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.activities.EditContactActivity import com.simplemobiletools.contacts.pro.activities.EditContactActivity
import com.simplemobiletools.contacts.pro.activities.SimpleActivity import com.simplemobiletools.contacts.pro.activities.SimpleActivity
import com.simplemobiletools.contacts.pro.activities.ViewContactActivity import com.simplemobiletools.contacts.pro.activities.ViewContactActivity
import com.simplemobiletools.contacts.pro.helpers.* import com.simplemobiletools.contacts.pro.helpers.DEFAULT_FILE_NAME
import com.simplemobiletools.contacts.pro.models.Contact import com.simplemobiletools.contacts.pro.helpers.VcfExporter
fun SimpleActivity.startCallIntent(recipient: String) { fun SimpleActivity.startCallIntent(recipient: String) {
handlePermission(PERMISSION_CALL_PHONE) { handlePermission(PERMISSION_CALL_PHONE) {

View File

@ -2,339 +2,21 @@ package com.simplemobiletools.contacts.pro.extensions
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Intent
import android.database.Cursor
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Handler
import android.os.Looper
import android.provider.ContactsContract
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.getCachePhoto
import com.simplemobiletools.commons.helpers.PERMISSION_READ_CONTACTS import com.simplemobiletools.commons.helpers.SIGNAL_PACKAGE
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_CONTACTS import com.simplemobiletools.commons.helpers.TELEGRAM_PACKAGE
import com.simplemobiletools.commons.helpers.SMT_PRIVATE import com.simplemobiletools.commons.helpers.VIBER_PACKAGE
import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.WHATSAPP_PACKAGE
import com.simplemobiletools.contacts.pro.BuildConfig import com.simplemobiletools.contacts.pro.BuildConfig
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.databases.ContactsDatabase import com.simplemobiletools.contacts.pro.helpers.Config
import com.simplemobiletools.contacts.pro.helpers.*
import com.simplemobiletools.contacts.pro.interfaces.ContactsDao
import com.simplemobiletools.contacts.pro.interfaces.GroupsDao
import com.simplemobiletools.contacts.pro.models.Contact
import com.simplemobiletools.contacts.pro.models.ContactSource
import com.simplemobiletools.contacts.pro.models.Organization
import com.simplemobiletools.contacts.pro.models.SocialAction
import java.io.File import java.io.File
val Context.config: Config get() = Config.newInstance(applicationContext) val Context.config: Config get() = Config.newInstance(applicationContext)
val Context.contactsDB: ContactsDao get() = ContactsDatabase.getInstance(applicationContext).ContactsDao()
val Context.groupsDB: GroupsDao get() = ContactsDatabase.getInstance(applicationContext).GroupsDao()
fun Context.getEmptyContact(): Contact {
val originalContactSource = if (hasContactPermissions()) config.lastUsedContactSource else SMT_PRIVATE
val organization = Organization("", "")
return Contact(
0, "", "", "", "", "", "", "", ArrayList(), ArrayList(), ArrayList(), ArrayList(), originalContactSource, 0, 0, "",
null, "", ArrayList(), organization, ArrayList(), ArrayList(), DEFAULT_MIMETYPE, null
)
}
fun Context.sendAddressIntent(address: String) {
val location = Uri.encode(address)
val uri = Uri.parse("geo:0,0?q=$location")
Intent(Intent.ACTION_VIEW, uri).apply {
launchActivityIntent(this)
}
}
fun Context.openWebsiteIntent(url: String) {
val website = if (url.startsWith("http")) {
url
} else {
"https://$url"
}
Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse(website)
launchActivityIntent(this)
}
}
fun Context.getLookupUriRawId(dataUri: Uri): Int {
val lookupKey = getLookupKeyFromUri(dataUri)
if (lookupKey != null) {
val uri = lookupContactUri(lookupKey, this)
if (uri != null) {
return getContactUriRawId(uri)
}
}
return -1
}
fun Context.getContactUriRawId(uri: Uri): Int {
val projection = arrayOf(ContactsContract.Contacts.NAME_RAW_CONTACT_ID)
var cursor: Cursor? = null
try {
cursor = contentResolver.query(uri, projection, null, null, null)
if (cursor!!.moveToFirst()) {
return cursor.getIntValue(ContactsContract.Contacts.NAME_RAW_CONTACT_ID)
}
} catch (ignored: Exception) {
} finally {
cursor?.close()
}
return -1
}
// from https://android.googlesource.com/platform/packages/apps/Dialer/+/68038172793ee0e2ab3e2e56ddfbeb82879d1f58/java/com/android/contacts/common/util/UriUtils.java
fun getLookupKeyFromUri(lookupUri: Uri): String? {
return if (!isEncodedContactUri(lookupUri)) {
val segments = lookupUri.pathSegments
if (segments.size < 3) null else Uri.encode(segments[2])
} else {
null
}
}
fun isEncodedContactUri(uri: Uri?): Boolean {
if (uri == null) {
return false
}
val lastPathSegment = uri.lastPathSegment ?: return false
return lastPathSegment == "encoded"
}
fun lookupContactUri(lookup: String, context: Context): Uri? {
val lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookup)
return try {
ContactsContract.Contacts.lookupContact(context.contentResolver, lookupUri)
} catch (e: Exception) {
null
}
}
fun Context.getCachePhoto(): File {
val imagesFolder = File(cacheDir, "my_cache")
if (!imagesFolder.exists()) {
imagesFolder.mkdirs()
}
val file = File(imagesFolder, "Photo_${System.currentTimeMillis()}.jpg")
file.createNewFile()
return file
}
fun Context.getCachePhotoUri(file: File = getCachePhoto()) = FileProvider.getUriForFile(this, "${BuildConfig.APPLICATION_ID}.provider", file) fun Context.getCachePhotoUri(file: File = getCachePhoto()) = FileProvider.getUriForFile(this, "${BuildConfig.APPLICATION_ID}.provider", file)
fun Context.getPhotoThumbnailSize(): Int {
val uri = ContactsContract.DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI
val projection = arrayOf(ContactsContract.DisplayPhoto.THUMBNAIL_MAX_DIM)
var cursor: Cursor? = null
try {
cursor = contentResolver.query(uri, projection, null, null, null)
if (cursor?.moveToFirst() == true) {
return cursor.getIntValue(ContactsContract.DisplayPhoto.THUMBNAIL_MAX_DIM)
}
} catch (ignored: Exception) {
} finally {
cursor?.close()
}
return 0
}
fun Context.hasContactPermissions() = hasPermission(PERMISSION_READ_CONTACTS) && hasPermission(PERMISSION_WRITE_CONTACTS)
fun Context.getPublicContactSource(source: String, callback: (String) -> Unit) {
when (source) {
SMT_PRIVATE -> callback(getString(R.string.phone_storage_hidden))
else -> {
ContactsHelper(this).getContactSources {
var newSource = source
for (contactSource in it) {
if (contactSource.name == source && contactSource.type == TELEGRAM_PACKAGE) {
newSource = getString(R.string.telegram)
break
} else if (contactSource.name == source && contactSource.type == VIBER_PACKAGE) {
newSource = getString(R.string.viber)
break
}
}
Handler(Looper.getMainLooper()).post {
callback(newSource)
}
}
}
}
}
fun Context.getPublicContactSourceSync(source: String, contactSources: ArrayList<ContactSource>): String {
return when (source) {
SMT_PRIVATE -> getString(R.string.phone_storage_hidden)
else -> {
var newSource = source
for (contactSource in contactSources) {
if (contactSource.name == source && contactSource.type == TELEGRAM_PACKAGE) {
newSource = getString(R.string.telegram)
break
} else if (contactSource.name == source && contactSource.type == VIBER_PACKAGE) {
newSource = getString(R.string.viber)
break
}
}
return newSource
}
}
}
fun Context.sendSMSToContacts(contacts: ArrayList<Contact>) {
val numbers = StringBuilder()
contacts.forEach {
val number = it.phoneNumbers.firstOrNull { it.type == ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE }
?: it.phoneNumbers.firstOrNull()
if (number != null) {
numbers.append("${Uri.encode(number.value)};")
}
}
val uriString = "smsto:${numbers.toString().trimEnd(';')}"
Intent(Intent.ACTION_SENDTO, Uri.parse(uriString)).apply {
launchActivityIntent(this)
}
}
fun Context.sendEmailToContacts(contacts: ArrayList<Contact>) {
val emails = ArrayList<String>()
contacts.forEach {
it.emails.forEach {
if (it.value.isNotEmpty()) {
emails.add(it.value)
}
}
}
Intent(Intent.ACTION_SEND_MULTIPLE).apply {
type = "message/rfc822"
putExtra(Intent.EXTRA_EMAIL, emails.toTypedArray())
launchActivityIntent(this)
}
}
fun Context.getTempFile(filename: String = DEFAULT_FILE_NAME): File? {
val folder = File(cacheDir, "contacts")
if (!folder.exists()) {
if (!folder.mkdir()) {
toast(R.string.unknown_error_occurred)
return null
}
}
return File(folder, filename)
}
fun Context.addContactsToGroup(contacts: ArrayList<Contact>, groupId: Long) {
val publicContacts = contacts.filter { !it.isPrivate() }.toMutableList() as ArrayList<Contact>
val privateContacts = contacts.filter { it.isPrivate() }.toMutableList() as ArrayList<Contact>
if (publicContacts.isNotEmpty()) {
ContactsHelper(this).addContactsToGroup(publicContacts, groupId)
}
if (privateContacts.isNotEmpty()) {
LocalContactsHelper(this).addContactsToGroup(privateContacts, groupId)
}
}
fun Context.removeContactsFromGroup(contacts: ArrayList<Contact>, groupId: Long) {
val publicContacts = contacts.filter { !it.isPrivate() }.toMutableList() as ArrayList<Contact>
val privateContacts = contacts.filter { it.isPrivate() }.toMutableList() as ArrayList<Contact>
if (publicContacts.isNotEmpty() && hasContactPermissions()) {
ContactsHelper(this).removeContactsFromGroup(publicContacts, groupId)
}
if (privateContacts.isNotEmpty()) {
LocalContactsHelper(this).removeContactsFromGroup(privateContacts, groupId)
}
}
fun Context.getContactPublicUri(contact: Contact): Uri {
val lookupKey = if (contact.isPrivate()) {
"local_${contact.id}"
} else {
SimpleContactsHelper(this).getContactLookupKey(contact.id.toString())
}
return Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey)
}
fun Context.getVisibleContactSources(): ArrayList<String> {
val sources = getAllContactSources()
val ignoredContactSources = config.ignoredContactSources
return ArrayList(sources).filter { !ignoredContactSources.contains(it.getFullIdentifier()) }
.map { it.name }.toMutableList() as ArrayList<String>
}
fun Context.getAllContactSources(): ArrayList<ContactSource> {
val sources = ContactsHelper(this).getDeviceContactSources()
sources.add(getPrivateContactSource())
return sources.toMutableList() as ArrayList<ContactSource>
}
fun Context.getPrivateContactSource() = ContactSource(SMT_PRIVATE, SMT_PRIVATE, getString(R.string.phone_storage_hidden))
fun Context.getSocialActions(id: Int): ArrayList<SocialAction> {
val uri = ContactsContract.Data.CONTENT_URI
val projection = arrayOf(
ContactsContract.Data._ID,
ContactsContract.Data.DATA3,
ContactsContract.Data.MIMETYPE,
ContactsContract.Data.ACCOUNT_TYPE_AND_DATA_SET
)
val socialActions = ArrayList<SocialAction>()
var curActionId = 0
val selection = "${ContactsContract.Data.RAW_CONTACT_ID} = ?"
val selectionArgs = arrayOf(id.toString())
queryCursor(uri, projection, selection, selectionArgs, null, true) { cursor ->
val mimetype = cursor.getStringValue(ContactsContract.Data.MIMETYPE)
val type = when (mimetype) {
// WhatsApp
"vnd.android.cursor.item/vnd.com.whatsapp.profile" -> SOCIAL_MESSAGE
"vnd.android.cursor.item/vnd.com.whatsapp.voip.call" -> SOCIAL_VOICE_CALL
"vnd.android.cursor.item/vnd.com.whatsapp.video.call" -> SOCIAL_VIDEO_CALL
// Viber
"vnd.android.cursor.item/vnd.com.viber.voip.viber_number_call" -> SOCIAL_VOICE_CALL
"vnd.android.cursor.item/vnd.com.viber.voip.viber_out_call_viber" -> SOCIAL_VOICE_CALL
"vnd.android.cursor.item/vnd.com.viber.voip.viber_out_call_none_viber" -> SOCIAL_VOICE_CALL
"vnd.android.cursor.item/vnd.com.viber.voip.viber_number_message" -> SOCIAL_MESSAGE
// Signal
"vnd.android.cursor.item/vnd.org.thoughtcrime.securesms.contact" -> SOCIAL_MESSAGE
"vnd.android.cursor.item/vnd.org.thoughtcrime.securesms.call" -> SOCIAL_VOICE_CALL
// Telegram
"vnd.android.cursor.item/vnd.org.telegram.messenger.android.call" -> SOCIAL_VOICE_CALL
"vnd.android.cursor.item/vnd.org.telegram.messenger.android.call.video" -> SOCIAL_VIDEO_CALL
"vnd.android.cursor.item/vnd.org.telegram.messenger.android.profile" -> SOCIAL_MESSAGE
// Threema
"vnd.android.cursor.item/vnd.ch.threema.app.profile" -> SOCIAL_MESSAGE
"vnd.android.cursor.item/vnd.ch.threema.app.call" -> SOCIAL_VOICE_CALL
else -> return@queryCursor
}
val label = cursor.getStringValue(ContactsContract.Data.DATA3)
val realID = cursor.getLongValue(ContactsContract.Data._ID)
val packageName = cursor.getStringValue(ContactsContract.Data.ACCOUNT_TYPE_AND_DATA_SET)
val socialAction = SocialAction(curActionId++, type, label, mimetype, realID, packageName)
socialActions.add(socialAction)
}
return socialActions
}
@SuppressLint("UseCompatLoadingForDrawables") @SuppressLint("UseCompatLoadingForDrawables")
fun Context.getPackageDrawable(packageName: String): Drawable { fun Context.getPackageDrawable(packageName: String): Drawable {
return resources.getDrawable( return resources.getDrawable(

View File

@ -2,11 +2,11 @@ package com.simplemobiletools.contacts.pro.fragments
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import com.simplemobiletools.commons.helpers.ContactsHelper
import com.simplemobiletools.commons.helpers.TAB_FAVORITES import com.simplemobiletools.commons.helpers.TAB_FAVORITES
import com.simplemobiletools.contacts.pro.activities.MainActivity import com.simplemobiletools.contacts.pro.activities.MainActivity
import com.simplemobiletools.contacts.pro.activities.SimpleActivity import com.simplemobiletools.contacts.pro.activities.SimpleActivity
import com.simplemobiletools.contacts.pro.dialogs.SelectContactsDialog import com.simplemobiletools.contacts.pro.dialogs.SelectContactsDialog
import com.simplemobiletools.contacts.pro.helpers.ContactsHelper
class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet) { class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet) {
override fun fabClicked() { override fun fabClicked() {

View File

@ -17,12 +17,11 @@ import com.simplemobiletools.contacts.pro.activities.MainActivity
import com.simplemobiletools.contacts.pro.activities.SimpleActivity import com.simplemobiletools.contacts.pro.activities.SimpleActivity
import com.simplemobiletools.contacts.pro.adapters.ContactsAdapter import com.simplemobiletools.contacts.pro.adapters.ContactsAdapter
import com.simplemobiletools.contacts.pro.adapters.GroupsAdapter import com.simplemobiletools.contacts.pro.adapters.GroupsAdapter
import com.simplemobiletools.contacts.pro.extensions.config import com.simplemobiletools.commons.helpers.Converters
import com.simplemobiletools.contacts.pro.extensions.getVisibleContactSources
import com.simplemobiletools.contacts.pro.helpers.* import com.simplemobiletools.contacts.pro.helpers.*
import com.simplemobiletools.contacts.pro.interfaces.RefreshContactsListener import com.simplemobiletools.contacts.pro.interfaces.RefreshContactsListener
import com.simplemobiletools.contacts.pro.models.Contact import com.simplemobiletools.commons.models.contacts.*
import com.simplemobiletools.contacts.pro.models.Group import com.simplemobiletools.contacts.pro.extensions.config
import kotlinx.android.synthetic.main.fragment_layout.view.* import kotlinx.android.synthetic.main.fragment_layout.view.*
import kotlinx.android.synthetic.main.fragment_layout.view.fragment_fab import kotlinx.android.synthetic.main.fragment_layout.view.fragment_fab
import kotlinx.android.synthetic.main.fragment_layout.view.fragment_list import kotlinx.android.synthetic.main.fragment_layout.view.fragment_list

View File

@ -7,71 +7,4 @@ class Config(context: Context) : BaseConfig(context) {
companion object { companion object {
fun newInstance(context: Context) = Config(context) fun newInstance(context: Context) = Config(context)
} }
var ignoredContactSources: HashSet<String>
get() = prefs.getStringSet(IGNORED_CONTACT_SOURCES, hashSetOf(".")) as HashSet
set(ignoreContactSources) = prefs.edit().remove(IGNORED_CONTACT_SOURCES).putStringSet(IGNORED_CONTACT_SOURCES, ignoreContactSources).apply()
var showContactThumbnails: Boolean
get() = prefs.getBoolean(SHOW_CONTACT_THUMBNAILS, true)
set(showContactThumbnails) = prefs.edit().putBoolean(SHOW_CONTACT_THUMBNAILS, showContactThumbnails).apply()
var showPhoneNumbers: Boolean
get() = prefs.getBoolean(SHOW_PHONE_NUMBERS, false)
set(showPhoneNumbers) = prefs.edit().putBoolean(SHOW_PHONE_NUMBERS, showPhoneNumbers).apply()
var showOnlyContactsWithNumbers: Boolean
get() = prefs.getBoolean(SHOW_ONLY_CONTACTS_WITH_NUMBERS, false)
set(showOnlyContactsWithNumbers) = prefs.edit().putBoolean(SHOW_ONLY_CONTACTS_WITH_NUMBERS, showOnlyContactsWithNumbers).apply()
var lastUsedContactSource: String
get() = prefs.getString(LAST_USED_CONTACT_SOURCE, "")!!
set(lastUsedContactSource) = prefs.edit().putString(LAST_USED_CONTACT_SOURCE, lastUsedContactSource).apply()
var onContactClick: Int
get() = prefs.getInt(ON_CONTACT_CLICK, ON_CLICK_VIEW_CONTACT)
set(onContactClick) = prefs.edit().putInt(ON_CONTACT_CLICK, onContactClick).apply()
var showContactFields: Int
get() = prefs.getInt(
SHOW_CONTACT_FIELDS, SHOW_FIRST_NAME_FIELD or SHOW_SURNAME_FIELD or SHOW_PHONE_NUMBERS_FIELD or SHOW_EMAILS_FIELD or
SHOW_ADDRESSES_FIELD or SHOW_EVENTS_FIELD or SHOW_NOTES_FIELD or SHOW_GROUPS_FIELD or SHOW_CONTACT_SOURCE_FIELD
)
set(showContactFields) = prefs.edit().putInt(SHOW_CONTACT_FIELDS, showContactFields).apply()
var showTabs: Int
get() = prefs.getInt(SHOW_TABS, ALL_TABS_MASK)
set(showTabs) = prefs.edit().putInt(SHOW_TABS, showTabs).apply()
var showDialpadButton: Boolean
get() = prefs.getBoolean(SHOW_DIALPAD_BUTTON, true)
set(showDialpadButton) = prefs.edit().putBoolean(SHOW_DIALPAD_BUTTON, showDialpadButton).apply()
var wasLocalAccountInitialized: Boolean
get() = prefs.getBoolean(WAS_LOCAL_ACCOUNT_INITIALIZED, false)
set(wasLocalAccountInitialized) = prefs.edit().putBoolean(WAS_LOCAL_ACCOUNT_INITIALIZED, wasLocalAccountInitialized).apply()
var lastExportPath: String
get() = prefs.getString(LAST_EXPORT_PATH, "")!!
set(lastExportPath) = prefs.edit().putString(LAST_EXPORT_PATH, lastExportPath).apply()
var speedDial: String
get() = prefs.getString(SPEED_DIAL, "")!!
set(speedDial) = prefs.edit().putString(SPEED_DIAL, speedDial).apply()
var showPrivateContacts: Boolean
get() = prefs.getBoolean(SHOW_PRIVATE_CONTACTS, true)
set(showPrivateContacts) = prefs.edit().putBoolean(SHOW_PRIVATE_CONTACTS, showPrivateContacts).apply()
var mergeDuplicateContacts: Boolean
get() = prefs.getBoolean(MERGE_DUPLICATE_CONTACTS, true)
set(mergeDuplicateContacts) = prefs.edit().putBoolean(MERGE_DUPLICATE_CONTACTS, mergeDuplicateContacts).apply()
var favoritesContactsOrder: String
get() = prefs.getString(FAVORITES_CONTACTS_ORDER, "")!!
set(order) = prefs.edit().putString(FAVORITES_CONTACTS_ORDER, order).apply()
var isCustomOrderSelected: Boolean
get() = prefs.getBoolean(FAVORITES_CUSTOM_ORDER_SELECTED, false)
set(selected) = prefs.edit().putBoolean(FAVORITES_CUSTOM_ORDER_SELECTED, selected).apply()
} }

View File

@ -1,29 +1,8 @@
package com.simplemobiletools.contacts.pro.helpers package com.simplemobiletools.contacts.pro.helpers
import android.provider.ContactsContract.CommonDataKinds
import com.simplemobiletools.commons.extensions.normalizeString
import com.simplemobiletools.commons.helpers.TAB_CONTACTS import com.simplemobiletools.commons.helpers.TAB_CONTACTS
import com.simplemobiletools.commons.helpers.TAB_FAVORITES import com.simplemobiletools.commons.helpers.TAB_FAVORITES
import com.simplemobiletools.commons.helpers.TAB_GROUPS import com.simplemobiletools.commons.helpers.TAB_GROUPS
import com.simplemobiletools.contacts.pro.models.LocalContact
// shared prefs
const val SHOW_CONTACT_THUMBNAILS = "show_contact_thumbnails"
const val SHOW_PHONE_NUMBERS = "show_phone_numbers"
const val SHOW_ONLY_CONTACTS_WITH_NUMBERS = "show_only_contacts_with_numbers"
const val IGNORED_CONTACT_SOURCES = "ignored_contact_sources_2"
const val LAST_USED_CONTACT_SOURCE = "last_used_contact_source"
const val ON_CONTACT_CLICK = "on_contact_click"
const val SHOW_CONTACT_FIELDS = "show_contact_fields"
const val SHOW_TABS = "show_tabs"
const val SHOW_DIALPAD_BUTTON = "show_dialpad_button"
const val SPEED_DIAL = "speed_dial"
const val LAST_EXPORT_PATH = "last_export_path"
const val WAS_LOCAL_ACCOUNT_INITIALIZED = "was_local_account_initialized"
const val SHOW_PRIVATE_CONTACTS = "show_private_contacts"
const val MERGE_DUPLICATE_CONTACTS = "merge_duplicate_contacts"
const val FAVORITES_CONTACTS_ORDER = "favorites_contacts_order"
const val FAVORITES_CUSTOM_ORDER_SELECTED = "favorites_custom_order_selected"
const val GROUP = "group" const val GROUP = "group"
const val IS_FROM_SIMPLE_CONTACTS = "is_from_simple_contacts" const val IS_FROM_SIMPLE_CONTACTS = "is_from_simple_contacts"
@ -44,20 +23,12 @@ const val LOCATION_FAVORITES_TAB = 1
const val LOCATION_GROUP_CONTACTS = 2 const val LOCATION_GROUP_CONTACTS = 2
const val LOCATION_INSERT_OR_EDIT = 3 const val LOCATION_INSERT_OR_EDIT = 3
const val ALL_TABS_MASK = TAB_CONTACTS or TAB_FAVORITES or TAB_GROUPS
val tabsList = arrayListOf( val tabsList = arrayListOf(
TAB_CONTACTS, TAB_CONTACTS,
TAB_FAVORITES, TAB_FAVORITES,
TAB_GROUPS TAB_GROUPS
) )
// contact photo changes
const val PHOTO_ADDED = 1
const val PHOTO_REMOVED = 2
const val PHOTO_CHANGED = 3
const val PHOTO_UNCHANGED = 4
// phone number/email types // phone number/email types
const val CELL = "CELL" const val CELL = "CELL"
const val WORK = "WORK" const val WORK = "WORK"
@ -76,77 +47,8 @@ const val HANGOUTS = "Hangouts"
const val QQ = "QQ" const val QQ = "QQ"
const val JABBER = "Jabber" const val JABBER = "Jabber"
const val ON_CLICK_CALL_CONTACT = 1
const val ON_CLICK_VIEW_CONTACT = 2
const val ON_CLICK_EDIT_CONTACT = 3
// visible fields filtering
const val SHOW_PREFIX_FIELD = 1
const val SHOW_FIRST_NAME_FIELD = 2
const val SHOW_MIDDLE_NAME_FIELD = 4
const val SHOW_SURNAME_FIELD = 8
const val SHOW_SUFFIX_FIELD = 16
const val SHOW_PHONE_NUMBERS_FIELD = 32
const val SHOW_EMAILS_FIELD = 64
const val SHOW_ADDRESSES_FIELD = 128
const val SHOW_EVENTS_FIELD = 256
const val SHOW_NOTES_FIELD = 512
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 SHOW_IMS_FIELD = 32768
const val SHOW_RINGTONE_FIELD = 65536
const val DEFAULT_EMAIL_TYPE = CommonDataKinds.Email.TYPE_HOME
const val DEFAULT_PHONE_NUMBER_TYPE = CommonDataKinds.Phone.TYPE_MOBILE
const val DEFAULT_ADDRESS_TYPE = CommonDataKinds.StructuredPostal.TYPE_HOME
const val DEFAULT_EVENT_TYPE = CommonDataKinds.Event.TYPE_BIRTHDAY
const val DEFAULT_ORGANIZATION_TYPE = CommonDataKinds.Organization.TYPE_WORK
const val DEFAULT_WEBSITE_TYPE = CommonDataKinds.Website.TYPE_HOMEPAGE
const val DEFAULT_IM_TYPE = CommonDataKinds.Im.PROTOCOL_SKYPE
const val DEFAULT_MIMETYPE = CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
// apps with special handling
const val TELEGRAM_PACKAGE = "org.telegram.messenger"
const val SIGNAL_PACKAGE = "org.thoughtcrime.securesms"
const val WHATSAPP_PACKAGE = "com.whatsapp"
const val VIBER_PACKAGE = "com.viber.voip"
const val THREEMA_PACKAGE = "ch.threema.app"
const val WHATSAPP = "whatsapp" const val WHATSAPP = "whatsapp"
const val SIGNAL = "signal" const val SIGNAL = "signal"
const val VIBER = "viber" const val VIBER = "viber"
const val TELEGRAM = "telegram" const val TELEGRAM = "telegram"
const val THREEMA = "threema" const val THREEMA = "threema"
const val SOCIAL_VOICE_CALL = 0
const val SOCIAL_VIDEO_CALL = 1
const val SOCIAL_MESSAGE = 2
fun getEmptyLocalContact() = LocalContact(
0,
"",
"",
"",
"",
"",
"",
null,
"",
ArrayList(),
ArrayList(),
ArrayList(),
0,
ArrayList(),
"",
ArrayList(),
"",
"",
ArrayList(),
ArrayList(),
null
)
fun getProperText(text: String, shouldNormalize: Boolean) = if (shouldNormalize) text.normalizeString() else text

View File

@ -1,76 +0,0 @@
package com.simplemobiletools.contacts.pro.helpers
import androidx.room.TypeConverter
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.simplemobiletools.commons.models.PhoneNumber
import com.simplemobiletools.contacts.pro.models.*
class Converters {
private val gson = Gson()
private val longType = object : TypeToken<List<Long>>() {}.type
private val stringType = object : TypeToken<List<String>>() {}.type
private val numberType = object : TypeToken<List<PhoneNumber>>() {}.type
private val numberConverterType = object : TypeToken<List<PhoneNumberConverter>>() {}.type
private val emailType = object : TypeToken<List<Email>>() {}.type
private val addressType = object : TypeToken<List<Address>>() {}.type
private val eventType = object : TypeToken<List<Event>>() {}.type
private val imType = object : TypeToken<List<IM>>() {}.type
@TypeConverter
fun jsonToStringList(value: String) = gson.fromJson<ArrayList<String>>(value, stringType)
@TypeConverter
fun stringListToJson(list: ArrayList<String>) = gson.toJson(list)
@TypeConverter
fun jsonToLongList(value: String) = gson.fromJson<ArrayList<Long>>(value, longType)
@TypeConverter
fun longListToJson(list: ArrayList<Long>) = gson.toJson(list)
// some hacky converting is needed since PhoneNumber model has been added to proguard rules, but obfuscated json was stored in database
// convert [{"a":"678910","b":2,"c":"","d":"678910","e":false}] to PhoneNumber(value=678910, type=2, label=, normalizedNumber=678910, isPrimary=false)
@TypeConverter
fun jsonToPhoneNumberList(value: String): ArrayList<PhoneNumber> {
val numbers = gson.fromJson<ArrayList<PhoneNumber>>(value, numberType)
return if (numbers.any { it.value == null }) {
val phoneNumbers = ArrayList<PhoneNumber>()
val numberConverters = gson.fromJson<ArrayList<PhoneNumberConverter>>(value, numberConverterType)
numberConverters.forEach { converter ->
val phoneNumber = PhoneNumber(converter.a, converter.b, converter.c, converter.d, converter.e)
phoneNumbers.add(phoneNumber)
}
phoneNumbers
} else {
numbers
}
}
@TypeConverter
fun phoneNumberListToJson(list: ArrayList<PhoneNumber>) = gson.toJson(list)
@TypeConverter
fun jsonToEmailList(value: String) = gson.fromJson<ArrayList<Email>>(value, emailType)
@TypeConverter
fun emailListToJson(list: ArrayList<Email>) = gson.toJson(list)
@TypeConverter
fun jsonToAddressList(value: String) = gson.fromJson<ArrayList<Address>>(value, addressType)
@TypeConverter
fun addressListToJson(list: ArrayList<Address>) = gson.toJson(list)
@TypeConverter
fun jsonToEventList(value: String) = gson.fromJson<ArrayList<Event>>(value, eventType)
@TypeConverter
fun eventListToJson(list: ArrayList<Event>) = gson.toJson(list)
@TypeConverter
fun jsonToIMsList(value: String) = gson.fromJson<ArrayList<IM>>(value, imType)
@TypeConverter
fun IMsListToJson(list: ArrayList<IM>) = gson.toJson(list)
}

View File

@ -1,173 +0,0 @@
package com.simplemobiletools.contacts.pro.helpers
import android.content.Context
import android.graphics.BitmapFactory
import android.net.Uri
import android.provider.ContactsContract.CommonDataKinds.Event
import android.provider.MediaStore
import com.simplemobiletools.commons.extensions.getByteArray
import com.simplemobiletools.commons.helpers.SMT_PRIVATE
import com.simplemobiletools.commons.models.SimpleContact
import com.simplemobiletools.contacts.pro.extensions.contactsDB
import com.simplemobiletools.contacts.pro.extensions.getEmptyContact
import com.simplemobiletools.contacts.pro.models.Contact
import com.simplemobiletools.contacts.pro.models.Group
import com.simplemobiletools.contacts.pro.models.LocalContact
import com.simplemobiletools.contacts.pro.models.Organization
class LocalContactsHelper(val context: Context) {
fun getAllContacts(favoritesOnly: Boolean = false): ArrayList<Contact> {
val contacts = if (favoritesOnly) context.contactsDB.getFavoriteContacts() else context.contactsDB.getContacts()
val storedGroups = ContactsHelper(context).getStoredGroupsSync()
return contacts.map { convertLocalContactToContact(it, storedGroups) }.toMutableList() as ArrayList<Contact>
}
fun getContactWithId(id: Int): Contact? {
val storedGroups = ContactsHelper(context).getStoredGroupsSync()
return convertLocalContactToContact(context.contactsDB.getContactWithId(id), storedGroups)
}
fun insertOrUpdateContact(contact: Contact): Boolean {
val localContact = convertContactToLocalContact(contact)
return context.contactsDB.insertOrUpdate(localContact) > 0
}
fun addContactsToGroup(contacts: ArrayList<Contact>, groupId: Long) {
contacts.forEach {
val localContact = convertContactToLocalContact(it)
val newGroups = localContact.groups
newGroups.add(groupId)
newGroups.distinct()
localContact.groups = newGroups
context.contactsDB.insertOrUpdate(localContact)
}
}
fun removeContactsFromGroup(contacts: ArrayList<Contact>, groupId: Long) {
contacts.forEach {
val localContact = convertContactToLocalContact(it)
val newGroups = localContact.groups
newGroups.remove(groupId)
localContact.groups = newGroups
context.contactsDB.insertOrUpdate(localContact)
}
}
fun deleteContactIds(ids: MutableList<Long>) {
ids.chunked(30).forEach {
context.contactsDB.deleteContactIds(it)
}
}
fun toggleFavorites(ids: Array<Int>, addToFavorites: Boolean) {
val isStarred = if (addToFavorites) 1 else 0
ids.forEach {
context.contactsDB.updateStarred(isStarred, it)
}
}
fun updateRingtone(id: Int, ringtone: String) {
context.contactsDB.updateRingtone(ringtone, id)
}
private fun getPhotoByteArray(uri: String): ByteArray {
if (uri.isEmpty()) {
return ByteArray(0)
}
val photoUri = Uri.parse(uri)
val bitmap = MediaStore.Images.Media.getBitmap(context.contentResolver, photoUri)
val fullSizePhotoData = bitmap.getByteArray()
bitmap.recycle()
return fullSizePhotoData
}
private fun convertLocalContactToContact(localContact: LocalContact?, storedGroups: ArrayList<Group>): Contact? {
if (localContact == null) {
return null
}
val contactPhoto = if (localContact.photo == null) {
null
} else {
try {
BitmapFactory.decodeByteArray(localContact.photo, 0, localContact.photo!!.size)
} catch (e: OutOfMemoryError) {
null
}
}
return context.getEmptyContact().apply {
id = localContact.id!!
prefix = localContact.prefix
firstName = localContact.firstName
middleName = localContact.middleName
surname = localContact.surname
suffix = localContact.suffix
nickname = localContact.nickname
phoneNumbers = localContact.phoneNumbers
emails = localContact.emails
addresses = localContact.addresses
events = localContact.events
source = SMT_PRIVATE
starred = localContact.starred
contactId = localContact.id!!
thumbnailUri = ""
photo = contactPhoto
photoUri = localContact.photoUri
notes = localContact.notes
groups = storedGroups.filter { localContact.groups.contains(it.id) } as ArrayList<Group>
organization = Organization(localContact.company, localContact.jobPosition)
websites = localContact.websites
IMs = localContact.IMs
ringtone = localContact.ringtone
}
}
private fun convertContactToLocalContact(contact: Contact): LocalContact {
val photoByteArray = if (contact.photoUri.isNotEmpty()) {
getPhotoByteArray(contact.photoUri)
} else {
contact.photo?.getByteArray()
}
return getEmptyLocalContact().apply {
id = if (contact.id <= FIRST_CONTACT_ID) null else contact.id
prefix = contact.prefix
firstName = contact.firstName
middleName = contact.middleName
surname = contact.surname
suffix = contact.suffix
nickname = contact.nickname
photo = photoByteArray
phoneNumbers = contact.phoneNumbers
emails = contact.emails
events = contact.events
starred = contact.starred
addresses = contact.addresses
notes = contact.notes
groups = contact.groups.map { it.id }.toMutableList() as ArrayList<Long>
company = contact.organization.company
jobPosition = contact.organization.jobPosition
websites = contact.websites
IMs = contact.IMs
ringtone = contact.ringtone
}
}
private fun convertContactToSimpleContact(contact: Contact?, withPhoneNumbersOnly: Boolean): SimpleContact? {
return if (contact == null || (withPhoneNumbersOnly && contact.phoneNumbers.isEmpty())) {
null
} else {
val birthdays = contact.events.filter { it.type == Event.TYPE_BIRTHDAY }.map { it.value }.toMutableList() as ArrayList<String>
val anniversaries = contact.events.filter { it.type == Event.TYPE_ANNIVERSARY }.map { it.value }.toMutableList() as ArrayList<String>
SimpleContact(contact.id, contact.id, contact.getNameToDisplay(), contact.photoUri, contact.phoneNumbers, birthdays, anniversaries)
}
}
fun getPrivateSimpleContactsSync(favoritesOnly: Boolean, withPhoneNumbersOnly: Boolean) = getAllContacts(favoritesOnly).mapNotNull {
convertContactToSimpleContact(it, withPhoneNumbersOnly)
}
}

View File

@ -12,9 +12,9 @@ import com.simplemobiletools.commons.extensions.getByteArray
import com.simplemobiletools.commons.extensions.getDateTimeFromDateString import com.simplemobiletools.commons.extensions.getDateTimeFromDateString
import com.simplemobiletools.commons.extensions.showErrorToast import com.simplemobiletools.commons.extensions.showErrorToast
import com.simplemobiletools.commons.extensions.toast import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.models.contacts.Contact
import com.simplemobiletools.contacts.pro.R import com.simplemobiletools.contacts.pro.R
import com.simplemobiletools.contacts.pro.helpers.VcfExporter.ExportResult.EXPORT_FAIL import com.simplemobiletools.contacts.pro.helpers.VcfExporter.ExportResult.EXPORT_FAIL
import com.simplemobiletools.contacts.pro.models.Contact
import ezvcard.Ezvcard import ezvcard.Ezvcard
import ezvcard.VCard import ezvcard.VCard
import ezvcard.VCardVersion import ezvcard.VCardVersion

View File

@ -7,17 +7,19 @@ import android.provider.ContactsContract.CommonDataKinds.Im
import android.provider.ContactsContract.CommonDataKinds.Phone import android.provider.ContactsContract.CommonDataKinds.Phone
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal import android.provider.ContactsContract.CommonDataKinds.StructuredPostal
import android.widget.Toast import android.widget.Toast
import com.simplemobiletools.commons.extensions.groupsDB
import com.simplemobiletools.commons.extensions.normalizePhoneNumber import com.simplemobiletools.commons.extensions.normalizePhoneNumber
import com.simplemobiletools.commons.extensions.showErrorToast import com.simplemobiletools.commons.extensions.showErrorToast
import com.simplemobiletools.commons.models.PhoneNumber import com.simplemobiletools.commons.extensions.getCachePhoto
import com.simplemobiletools.contacts.pro.activities.SimpleActivity
import com.simplemobiletools.contacts.pro.extensions.getCachePhoto
import com.simplemobiletools.contacts.pro.extensions.getCachePhotoUri import com.simplemobiletools.contacts.pro.extensions.getCachePhotoUri
import com.simplemobiletools.contacts.pro.extensions.groupsDB import com.simplemobiletools.commons.helpers.ContactsHelper
import com.simplemobiletools.commons.helpers.DEFAULT_MIMETYPE
import com.simplemobiletools.commons.models.PhoneNumber
import com.simplemobiletools.commons.models.contacts.*
import com.simplemobiletools.contacts.pro.activities.SimpleActivity
import com.simplemobiletools.contacts.pro.helpers.VcfImporter.ImportResult.IMPORT_FAIL import com.simplemobiletools.contacts.pro.helpers.VcfImporter.ImportResult.IMPORT_FAIL
import com.simplemobiletools.contacts.pro.helpers.VcfImporter.ImportResult.IMPORT_OK import com.simplemobiletools.contacts.pro.helpers.VcfImporter.ImportResult.IMPORT_OK
import com.simplemobiletools.contacts.pro.helpers.VcfImporter.ImportResult.IMPORT_PARTIAL import com.simplemobiletools.contacts.pro.helpers.VcfImporter.ImportResult.IMPORT_PARTIAL
import com.simplemobiletools.contacts.pro.models.*
import ezvcard.Ezvcard import ezvcard.Ezvcard
import ezvcard.VCard import ezvcard.VCard
import ezvcard.util.PartialDate import ezvcard.util.PartialDate

View File

@ -1,37 +0,0 @@
package com.simplemobiletools.contacts.pro.interfaces
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.simplemobiletools.contacts.pro.models.LocalContact
@Dao
interface ContactsDao {
@Query("SELECT * FROM contacts")
fun getContacts(): List<LocalContact>
@Query("SELECT * FROM contacts WHERE starred = 1")
fun getFavoriteContacts(): List<LocalContact>
@Query("SELECT * FROM contacts WHERE id = :id")
fun getContactWithId(id: Int): LocalContact?
@Query("SELECT * FROM contacts WHERE phone_numbers LIKE :number")
fun getContactWithNumber(number: String): LocalContact?
@Query("UPDATE contacts SET starred = :isStarred WHERE id = :id")
fun updateStarred(isStarred: Int, id: Int)
@Query("UPDATE contacts SET ringtone = :ringtone WHERE id = :id")
fun updateRingtone(ringtone: String, id: Int)
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertOrUpdate(contact: LocalContact): Long
@Query("DELETE FROM contacts WHERE id = :id")
fun deleteContactId(id: Int)
@Query("DELETE FROM contacts WHERE id IN (:ids)")
fun deleteContactIds(ids: List<Long>)
}

View File

@ -1,19 +0,0 @@
package com.simplemobiletools.contacts.pro.interfaces
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.simplemobiletools.contacts.pro.models.Group
@Dao
interface GroupsDao {
@Query("SELECT * FROM groups")
fun getGroups(): List<Group>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertOrUpdate(group: Group): Long
@Query("DELETE FROM groups WHERE id = :id")
fun deleteGroupId(id: Long)
}

View File

@ -1,6 +1,6 @@
package com.simplemobiletools.contacts.pro.interfaces package com.simplemobiletools.contacts.pro.interfaces
import com.simplemobiletools.contacts.pro.models.Contact import com.simplemobiletools.commons.models.contacts.*
interface RefreshContactsListener { interface RefreshContactsListener {
fun refreshContacts(refreshTabsMask: Int) fun refreshContacts(refreshTabsMask: Int)

View File

@ -1,6 +1,6 @@
package com.simplemobiletools.contacts.pro.interfaces package com.simplemobiletools.contacts.pro.interfaces
import com.simplemobiletools.contacts.pro.models.Contact import com.simplemobiletools.commons.models.contacts.*
interface RemoveFromGroupListener { interface RemoveFromGroupListener {
fun removeFromGroup(contacts: ArrayList<Contact>) fun removeFromGroup(contacts: ArrayList<Contact>)

View File

@ -1,3 +0,0 @@
package com.simplemobiletools.contacts.pro.models
data class Address(var value: String, var type: Int, var label: String)

View File

@ -1,180 +0,0 @@
package com.simplemobiletools.contacts.pro.models
import android.graphics.Bitmap
import com.simplemobiletools.commons.extensions.normalizeString
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.PhoneNumber
data class Contact(
var id: Int, var prefix: String, var firstName: String, var middleName: String, var surname: String, var suffix: String, var nickname: String,
var photoUri: String, var phoneNumbers: ArrayList<PhoneNumber>, var emails: ArrayList<Email>, var addresses: ArrayList<Address>,
var events: ArrayList<Event>, var source: String, var starred: Int, var contactId: Int, var thumbnailUri: String, var photo: Bitmap?, var notes: String,
var groups: ArrayList<Group>, var organization: Organization, var websites: ArrayList<String>, var IMs: ArrayList<IM>, var mimetype: String,
var ringtone: String?
) :
Comparable<Contact> {
companion object {
var sorting = 0
var startWithSurname = false
}
override fun compareTo(other: Contact): Int {
var result = when {
sorting and SORT_BY_FIRST_NAME != 0 -> {
val firstString = firstName.normalizeString()
val secondString = other.firstName.normalizeString()
compareUsingStrings(firstString, secondString, other)
}
sorting and SORT_BY_MIDDLE_NAME != 0 -> {
val firstString = middleName.normalizeString()
val secondString = other.middleName.normalizeString()
compareUsingStrings(firstString, secondString, other)
}
sorting and SORT_BY_SURNAME != 0 -> {
val firstString = surname.normalizeString()
val secondString = other.surname.normalizeString()
compareUsingStrings(firstString, secondString, other)
}
sorting and SORT_BY_FULL_NAME != 0 -> {
val firstString = getNameToDisplay().normalizeString()
val secondString = other.getNameToDisplay().normalizeString()
compareUsingStrings(firstString, secondString, other)
}
else -> compareUsingIds(other)
}
if (sorting and SORT_DESCENDING != 0) {
result *= -1
}
return result
}
private fun compareUsingStrings(firstString: String, secondString: String, other: Contact): Int {
var firstValue = firstString
var secondValue = secondString
if (firstValue.isEmpty() && firstName.isEmpty() && middleName.isEmpty() && surname.isEmpty()) {
val fullCompany = getFullCompany()
if (fullCompany.isNotEmpty()) {
firstValue = fullCompany.normalizeString()
} else if (emails.isNotEmpty()) {
firstValue = emails.first().value
}
}
if (secondValue.isEmpty() && other.firstName.isEmpty() && other.middleName.isEmpty() && other.surname.isEmpty()) {
val otherFullCompany = other.getFullCompany()
if (otherFullCompany.isNotEmpty()) {
secondValue = otherFullCompany.normalizeString()
} else if (other.emails.isNotEmpty()) {
secondValue = other.emails.first().value
}
}
return if (firstValue.firstOrNull()?.isLetter() == true && secondValue.firstOrNull()?.isLetter() == false) {
-1
} else if (firstValue.firstOrNull()?.isLetter() == false && secondValue.firstOrNull()?.isLetter() == true) {
1
} else {
if (firstValue.isEmpty() && secondValue.isNotEmpty()) {
1
} else if (firstValue.isNotEmpty() && secondValue.isEmpty()) {
-1
} else {
if (firstValue.equals(secondValue, ignoreCase = true)) {
getNameToDisplay().compareTo(other.getNameToDisplay(), true)
} else {
firstValue.compareTo(secondValue, true)
}
}
}
}
private fun compareUsingIds(other: Contact): Int {
val firstId = id
val secondId = other.id
return firstId.compareTo(secondId)
}
fun getBubbleText() = when {
sorting and SORT_BY_FIRST_NAME != 0 -> firstName
sorting and SORT_BY_MIDDLE_NAME != 0 -> middleName
else -> surname
}
fun getNameToDisplay(): String {
val firstMiddle = "$firstName $middleName".trim()
val firstPart = if (startWithSurname) {
if (surname.isNotEmpty() && firstMiddle.isNotEmpty()) {
"$surname,"
} else {
surname
}
} else {
firstMiddle
}
val lastPart = if (startWithSurname) firstMiddle else surname
val suffixComma = if (suffix.isEmpty()) "" else ", $suffix"
val fullName = "$prefix $firstPart $lastPart$suffixComma".trim()
return if (fullName.isEmpty()) {
if (organization.isNotEmpty()) {
getFullCompany()
} else {
emails.firstOrNull()?.value?.trim() ?: ""
}
} else {
fullName
}
}
// photos stored locally always have different hashcodes. Avoid constantly refreshing the contact lists as the app thinks something changed.
fun getHashWithoutPrivatePhoto(): Int {
val photoToUse = if (isPrivate()) null else photo
return copy(photo = photoToUse).hashCode()
}
fun getStringToCompare(): String {
val photoToUse = if (isPrivate()) null else photo
return copy(
id = 0,
prefix = "",
firstName = getNameToDisplay().toLowerCase(),
middleName = "",
surname = "",
suffix = "",
nickname = "",
photoUri = "",
phoneNumbers = ArrayList(),
emails = ArrayList(),
events = ArrayList(),
source = "",
addresses = ArrayList(),
starred = 0,
contactId = 0,
thumbnailUri = "",
photo = photoToUse,
notes = "",
groups = ArrayList(),
websites = ArrayList(),
organization = Organization("", ""),
IMs = ArrayList(),
ringtone = ""
).toString()
}
fun getHashToCompare() = getStringToCompare().hashCode()
fun getFullCompany(): String {
var fullOrganization = if (organization.company.isEmpty()) "" else "${organization.company}, "
fullOrganization += organization.jobPosition
return fullOrganization.trim().trimEnd(',')
}
fun isABusinessContact() =
prefix.isEmpty() && firstName.isEmpty() && middleName.isEmpty() && surname.isEmpty() && suffix.isEmpty() && organization.isNotEmpty()
fun isPrivate() = source == SMT_PRIVATE
fun getSignatureKey() = if (photoUri.isNotEmpty()) photoUri else hashCode()
}

View File

@ -1,13 +0,0 @@
package com.simplemobiletools.contacts.pro.models
import com.simplemobiletools.commons.helpers.SMT_PRIVATE
data class ContactSource(var name: String, var type: String, var publicName: String, var count: Int = 0) {
fun getFullIdentifier(): String {
return if (type == SMT_PRIVATE) {
type
} else {
"$name:$type"
}
}
}

View File

@ -1,3 +0,0 @@
package com.simplemobiletools.contacts.pro.models
data class Email(var value: String, var type: Int, var label: String)

View File

@ -1,3 +0,0 @@
package com.simplemobiletools.contacts.pro.models
data class Event(var value: String, var type: Int)

View File

@ -1,21 +0,0 @@
package com.simplemobiletools.contacts.pro.models
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
import com.simplemobiletools.contacts.pro.helpers.FIRST_GROUP_ID
import java.io.Serializable
@Entity(tableName = "groups", indices = [(Index(value = ["id"], unique = true))])
data class Group(
@PrimaryKey(autoGenerate = true) var id: Long?,
@ColumnInfo(name = "title") var title: String,
@ColumnInfo(name = "contacts_count") var contactsCount: Int = 0) : Serializable {
fun addContact() = contactsCount++
fun getBubbleText() = title
fun isPrivateSecretGroup() = id ?: 0 >= FIRST_GROUP_ID
}

View File

@ -1,3 +0,0 @@
package com.simplemobiletools.contacts.pro.models
data class IM(var value: String, var type: Int, var label: String)

View File

@ -1,36 +0,0 @@
package com.simplemobiletools.contacts.pro.models
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
import com.simplemobiletools.commons.models.PhoneNumber
@Entity(tableName = "contacts", indices = [(Index(value = ["id"], unique = true))])
data class LocalContact(
@PrimaryKey(autoGenerate = true) var id: Int?,
@ColumnInfo(name = "prefix") var prefix: String,
@ColumnInfo(name = "first_name") var firstName: String,
@ColumnInfo(name = "middle_name") var middleName: String,
@ColumnInfo(name = "surname") var surname: String,
@ColumnInfo(name = "suffix") var suffix: String,
@ColumnInfo(name = "nickname") var nickname: String,
@ColumnInfo(name = "photo", typeAffinity = ColumnInfo.BLOB) var photo: ByteArray?,
@ColumnInfo(name = "photo_uri") var photoUri: String,
@ColumnInfo(name = "phone_numbers") var phoneNumbers: ArrayList<PhoneNumber>,
@ColumnInfo(name = "emails") var emails: ArrayList<Email>,
@ColumnInfo(name = "events") var events: ArrayList<Event>,
@ColumnInfo(name = "starred") var starred: Int,
@ColumnInfo(name = "addresses") var addresses: ArrayList<Address>,
@ColumnInfo(name = "notes") var notes: String,
@ColumnInfo(name = "groups") var groups: ArrayList<Long>,
@ColumnInfo(name = "company") var company: String,
@ColumnInfo(name = "job_position") var jobPosition: String,
@ColumnInfo(name = "websites") var websites: ArrayList<String>,
@ColumnInfo(name = "ims") var IMs: ArrayList<IM>,
@ColumnInfo(name = "ringtone") var ringtone: String?
) {
override fun equals(other: Any?) = id == (other as? LocalContact?)?.id
override fun hashCode() = id ?: 0
}

View File

@ -1,7 +0,0 @@
package com.simplemobiletools.contacts.pro.models
data class Organization(var company: String, var jobPosition: String) {
fun isEmpty() = company.isEmpty() && jobPosition.isEmpty()
fun isNotEmpty() = !isEmpty()
}

View File

@ -1,4 +0,0 @@
package com.simplemobiletools.contacts.pro.models
// need for hacky parsing of no longer minified PhoneNumber model in Converters.kt
data class PhoneNumberConverter(var a: String, var b: Int, var c: String, var d: String, var e: Boolean = false)

View File

@ -1,3 +0,0 @@
package com.simplemobiletools.contacts.pro.models
data class SocialAction(var actionId: Int, var type: Int, var label: String, var mimetype: String, val dataId: Long, val packageName: String)