mirror of
https://github.com/SimpleMobileTools/Simple-Contacts.git
synced 2025-06-05 21:59:27 +02:00
460 lines
17 KiB
Kotlin
460 lines
17 KiB
Kotlin
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.net.Uri
|
|
import android.os.Bundle
|
|
import android.support.v4.app.ActivityCompat
|
|
import android.support.v4.content.ContextCompat
|
|
import android.support.v4.view.MenuItemCompat
|
|
import android.support.v4.view.ViewPager
|
|
import android.support.v7.widget.SearchView
|
|
import android.view.Menu
|
|
import android.view.MenuItem
|
|
import com.simplemobiletools.commons.dialogs.FilePickerDialog
|
|
import com.simplemobiletools.commons.extensions.*
|
|
import com.simplemobiletools.commons.helpers.*
|
|
import com.simplemobiletools.commons.models.FAQItem
|
|
import com.simplemobiletools.commons.models.Release
|
|
import com.simplemobiletools.contacts.BuildConfig
|
|
import com.simplemobiletools.contacts.R
|
|
import com.simplemobiletools.contacts.adapters.ViewPagerAdapter
|
|
import com.simplemobiletools.contacts.dialogs.ChangeSortingDialog
|
|
import com.simplemobiletools.contacts.dialogs.ExportContactsDialog
|
|
import com.simplemobiletools.contacts.dialogs.FilterContactSourcesDialog
|
|
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.helpers.*
|
|
import com.simplemobiletools.contacts.interfaces.RefreshContactsListener
|
|
import com.simplemobiletools.contacts.models.Contact
|
|
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 java.io.FileOutputStream
|
|
|
|
class MainActivity : SimpleActivity(), RefreshContactsListener {
|
|
private var isSearchOpen = false
|
|
private var searchMenuItem: MenuItem? = null
|
|
private var werePermissionsHandled = false
|
|
private var isFirstResume = true
|
|
private var isGettingContacts = false
|
|
|
|
private var storedTextColor = 0
|
|
private var storedBackgroundColor = 0
|
|
private var storedPrimaryColor = 0
|
|
private var storedShowContactThumbnails = false
|
|
private var storedShowPhoneNumbers = false
|
|
private var storedStartNameWithSurname = false
|
|
private var storedFilterDuplicates = true
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
super.onCreate(savedInstanceState)
|
|
setContentView(R.layout.activity_main)
|
|
appLaunched(BuildConfig.APPLICATION_ID)
|
|
setupTabColors()
|
|
|
|
// just get a reference to the database to make sure it is created properly
|
|
dbHelper
|
|
|
|
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)
|
|
}
|
|
|
|
storeLocalAccountData()
|
|
initFragments()
|
|
}
|
|
} else {
|
|
storeLocalAccountData()
|
|
initFragments()
|
|
}
|
|
}
|
|
storeStateVariables()
|
|
checkWhatsNewDialog()
|
|
}
|
|
|
|
override fun onResume() {
|
|
super.onResume()
|
|
if (storedShowPhoneNumbers != config.showPhoneNumbers) {
|
|
System.exit(0)
|
|
return
|
|
}
|
|
|
|
val configShowContactThumbnails = config.showContactThumbnails
|
|
if (storedShowContactThumbnails != configShowContactThumbnails) {
|
|
getAllFragments().forEach {
|
|
it?.showContactThumbnailsChanged(configShowContactThumbnails)
|
|
}
|
|
}
|
|
|
|
val configTextColor = config.textColor
|
|
if (storedTextColor != configTextColor) {
|
|
getInactiveTabIndexes(viewpager.currentItem).forEach {
|
|
main_tabs_holder.getTabAt(it)?.icon?.applyColorFilter(configTextColor)
|
|
}
|
|
getAllFragments().forEach {
|
|
it?.textColorChanged(configTextColor)
|
|
}
|
|
}
|
|
|
|
val configBackgroundColor = config.backgroundColor
|
|
if (storedBackgroundColor != configBackgroundColor) {
|
|
main_tabs_holder.background = ColorDrawable(configBackgroundColor)
|
|
}
|
|
|
|
val configPrimaryColor = config.primaryColor
|
|
if (storedPrimaryColor != configPrimaryColor) {
|
|
main_tabs_holder.setSelectedTabIndicatorColor(getAdjustedPrimaryColor())
|
|
main_tabs_holder.getTabAt(viewpager.currentItem)?.icon?.applyColorFilter(getAdjustedPrimaryColor())
|
|
getAllFragments().forEach {
|
|
it?.primaryColorChanged()
|
|
}
|
|
}
|
|
|
|
val configStartNameWithSurname = config.startNameWithSurname
|
|
if (storedStartNameWithSurname != configStartNameWithSurname) {
|
|
contacts_fragment?.startNameWithSurnameChanged(configStartNameWithSurname)
|
|
favorites_fragment?.startNameWithSurnameChanged(configStartNameWithSurname)
|
|
}
|
|
|
|
if (storedFilterDuplicates != config.filterDuplicates) {
|
|
refreshContacts(ALL_TABS_MASK)
|
|
}
|
|
|
|
if (werePermissionsHandled && !isFirstResume) {
|
|
if (viewpager.adapter == null) {
|
|
initFragments()
|
|
} else {
|
|
refreshContacts(ALL_TABS_MASK)
|
|
}
|
|
|
|
getAllFragments().forEach {
|
|
it?.onActivityResume()
|
|
}
|
|
}
|
|
isFirstResume = false
|
|
}
|
|
|
|
override fun onPause() {
|
|
super.onPause()
|
|
storeStateVariables()
|
|
}
|
|
|
|
override fun onDestroy() {
|
|
super.onDestroy()
|
|
config.lastUsedViewPagerPage = viewpager.currentItem
|
|
}
|
|
|
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
|
menuInflater.inflate(R.menu.menu, menu)
|
|
val currentPage = viewpager?.currentItem
|
|
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
|
|
}
|
|
setupSearch(menu)
|
|
return true
|
|
}
|
|
|
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
when (item.itemId) {
|
|
R.id.sort -> showSortingDialog()
|
|
R.id.filter -> showFilterDialog()
|
|
R.id.import_contacts -> tryImportContacts()
|
|
R.id.export_contacts -> tryExportContacts()
|
|
R.id.settings -> startActivity(Intent(applicationContext, SettingsActivity::class.java))
|
|
R.id.about -> launchAbout()
|
|
else -> return super.onOptionsItemSelected(item)
|
|
}
|
|
return true
|
|
}
|
|
|
|
private fun storeStateVariables() {
|
|
config.apply {
|
|
storedTextColor = textColor
|
|
storedBackgroundColor = backgroundColor
|
|
storedPrimaryColor = primaryColor
|
|
storedShowContactThumbnails = showContactThumbnails
|
|
storedShowPhoneNumbers = showPhoneNumbers
|
|
storedStartNameWithSurname = startNameWithSurname
|
|
storedFilterDuplicates = filterDuplicates
|
|
}
|
|
}
|
|
|
|
private fun setupSearch(menu: Menu) {
|
|
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
|
|
searchMenuItem = menu.findItem(R.id.search)
|
|
(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)
|
|
setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
|
override fun onQueryTextSubmit(query: String) = false
|
|
|
|
override fun onQueryTextChange(newText: String): Boolean {
|
|
if (isSearchOpen) {
|
|
getCurrentFragment()?.onSearchQueryChanged(newText)
|
|
}
|
|
return true
|
|
}
|
|
})
|
|
}
|
|
|
|
MenuItemCompat.setOnActionExpandListener(searchMenuItem, object : MenuItemCompat.OnActionExpandListener {
|
|
override fun onMenuItemActionExpand(item: MenuItem?): Boolean {
|
|
getCurrentFragment()?.onSearchOpened()
|
|
isSearchOpen = true
|
|
return true
|
|
}
|
|
|
|
override fun onMenuItemActionCollapse(item: MenuItem?): Boolean {
|
|
getCurrentFragment()?.onSearchClosed()
|
|
isSearchOpen = false
|
|
return true
|
|
}
|
|
})
|
|
}
|
|
|
|
private fun getCurrentFragment() = when (viewpager.currentItem) {
|
|
0 -> contacts_fragment
|
|
1 -> favorites_fragment
|
|
else -> groups_fragment
|
|
}
|
|
|
|
private fun setupTabColors() {
|
|
val lastUsedPage = config.lastUsedViewPagerPage
|
|
main_tabs_holder.apply {
|
|
background = ColorDrawable(config.backgroundColor)
|
|
setSelectedTabIndicatorColor(getAdjustedPrimaryColor())
|
|
getTabAt(lastUsedPage)?.select()
|
|
getTabAt(lastUsedPage)?.icon?.applyColorFilter(getAdjustedPrimaryColor())
|
|
|
|
getInactiveTabIndexes(lastUsedPage).forEach {
|
|
getTabAt(it)?.icon?.applyColorFilter(config.textColor)
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun storeLocalAccountData() {
|
|
if (config.localAccountType == "-1") {
|
|
ContactsHelper(this).getContactSources {
|
|
var localAccountType = ""
|
|
var localAccountName = ""
|
|
it.forEach {
|
|
if (localAccountTypes.contains(it.type)) {
|
|
localAccountType = it.type
|
|
localAccountName = it.name
|
|
}
|
|
}
|
|
|
|
config.localAccountType = localAccountType
|
|
config.localAccountName = localAccountName
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun getInactiveTabIndexes(activeIndex: Int) = arrayListOf(0, 1, 2).filter { it != activeIndex }
|
|
|
|
private fun initFragments() {
|
|
refreshContacts(ALL_TABS_MASK)
|
|
viewpager.offscreenPageLimit = 2
|
|
viewpager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
|
override fun onPageScrollStateChanged(state: Int) {
|
|
if (isSearchOpen) {
|
|
getCurrentFragment()?.onSearchQueryChanged("")
|
|
searchMenuItem?.collapseActionView()
|
|
}
|
|
}
|
|
|
|
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
|
}
|
|
|
|
override fun onPageSelected(position: Int) {
|
|
main_tabs_holder.getTabAt(position)?.select()
|
|
getAllFragments().forEach {
|
|
it?.finishActMode()
|
|
}
|
|
invalidateOptionsMenu()
|
|
}
|
|
})
|
|
|
|
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())
|
|
}
|
|
)
|
|
|
|
if (intent?.action == Intent.ACTION_VIEW && intent.data != null) {
|
|
tryImportContactsFromFile(intent.data)
|
|
intent.data = null
|
|
}
|
|
}
|
|
|
|
private fun showSortingDialog() {
|
|
ChangeSortingDialog(this) {
|
|
refreshContacts(CONTACTS_TAB_MASK or FAVORITES_TAB_MASK)
|
|
}
|
|
}
|
|
|
|
fun showFilterDialog() {
|
|
FilterContactSourcesDialog(this) {
|
|
contacts_fragment?.forceListRedraw = true
|
|
refreshContacts(CONTACTS_TAB_MASK)
|
|
}
|
|
}
|
|
|
|
private fun tryImportContacts() {
|
|
handlePermission(PERMISSION_READ_STORAGE) {
|
|
if (it) {
|
|
importContacts()
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun importContacts() {
|
|
FilePickerDialog(this) {
|
|
showImportContactsDialog(it)
|
|
}
|
|
}
|
|
|
|
private fun showImportContactsDialog(path: String) {
|
|
ImportContactsDialog(this, path) {
|
|
if (it) {
|
|
runOnUiThread {
|
|
refreshContacts(ALL_TABS_MASK)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun tryImportContactsFromFile(uri: Uri) {
|
|
when {
|
|
uri.scheme == "file" -> showImportContactsDialog(uri.path)
|
|
uri.scheme == "content" -> {
|
|
val tempFile = getTempFile()
|
|
if (tempFile == null) {
|
|
toast(R.string.unknown_error_occurred)
|
|
return
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
private fun tryExportContacts() {
|
|
handlePermission(PERMISSION_WRITE_STORAGE) {
|
|
if (it) {
|
|
exportContacts()
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun exportContacts() {
|
|
FilePickerDialog(this, pickFile = false, showFAB = true) {
|
|
ExportContactsDialog(this, it) { file, contactSources ->
|
|
Thread {
|
|
ContactsHelper(this).getContacts {
|
|
val contacts = it.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.ExportResult.EXPORT_OK -> R.string.exporting_successful
|
|
VcfExporter.ExportResult.EXPORT_PARTIAL -> R.string.exporting_some_entries_failed
|
|
else -> R.string.exporting_failed
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}.start()
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun launchAbout() {
|
|
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)
|
|
}
|
|
|
|
override fun refreshContacts(refreshTabsMask: Int) {
|
|
if (isActivityDestroyed() || isGettingContacts) {
|
|
return
|
|
}
|
|
|
|
isGettingContacts = true
|
|
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)
|
|
}
|
|
|
|
if (refreshTabsMask and FAVORITES_TAB_MASK != 0) {
|
|
favorites_fragment?.refreshContacts(it)
|
|
}
|
|
|
|
if (refreshTabsMask and GROUPS_TAB_MASK != 0) {
|
|
if (refreshTabsMask == GROUPS_TAB_MASK) {
|
|
groups_fragment.skipHashComparing = true
|
|
}
|
|
groups_fragment?.refreshContacts(it)
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun getAllFragments() = arrayListOf(contacts_fragment, favorites_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))
|
|
checkWhatsNew(this, BuildConfig.VERSION_CODE)
|
|
}
|
|
}
|
|
}
|