Simple-Dialer/app/src/main/kotlin/com/simplemobiletools/dialer/activities/SettingsActivity.kt

383 lines
14 KiB
Kotlin

package com.simplemobiletools.dialer.activities
import android.annotation.TargetApi
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.view.Menu
import androidx.activity.result.contract.ActivityResultContracts
import com.simplemobiletools.commons.activities.ManageBlockedNumbersActivity
import com.simplemobiletools.commons.dialogs.ChangeDateTimeFormatDialog
import com.simplemobiletools.commons.dialogs.FeatureLockedDialog
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.databinding.ActivitySettingsBinding
import com.simplemobiletools.dialer.dialogs.ExportCallHistoryDialog
import com.simplemobiletools.dialer.dialogs.ManageVisibleTabsDialog
import com.simplemobiletools.dialer.extensions.config
import com.simplemobiletools.dialer.helpers.RecentsHelper
import com.simplemobiletools.dialer.models.RecentCall
import kotlinx.serialization.SerializationException
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.util.*
import kotlin.system.exitProcess
class SettingsActivity : SimpleActivity() {
companion object {
private const val CALL_HISTORY_FILE_TYPE = "application/json"
}
private val binding by viewBinding(ActivitySettingsBinding::inflate)
private val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
if (uri != null) {
toast(R.string.importing)
importCallHistory(uri)
}
}
private val saveDocument = registerForActivityResult(ActivityResultContracts.CreateDocument(CALL_HISTORY_FILE_TYPE)) { uri ->
if (uri != null) {
toast(R.string.exporting)
RecentsHelper(this).getRecentCalls(false, Int.MAX_VALUE) { recents ->
exportCallHistory(recents, uri)
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.apply {
updateMaterialActivityViews(settingsCoordinator, settingsHolder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(settingsNestedScrollview, settingsToolbar)
}
}
override fun onResume() {
super.onResume()
setupToolbar(binding.settingsToolbar, NavigationIcon.Arrow)
setupPurchaseThankYou()
setupCustomizeColors()
setupUseEnglish()
setupLanguage()
setupManageBlockedNumbers()
setupManageSpeedDial()
setupChangeDateTimeFormat()
setupFontSize()
setupManageShownTabs()
setupDefaultTab()
setupDialPadOpen()
setupGroupSubsequentCalls()
setupStartNameWithSurname()
setupDialpadVibrations()
setupDialpadNumbers()
setupDialpadBeeps()
setupShowCallConfirmation()
setupDisableProximitySensor()
setupDisableSwipeToAnswer()
setupAlwaysShowFullscreen()
setupCallsExport()
setupCallsImport()
updateTextColors(binding.settingsHolder)
binding.apply {
arrayOf(
settingsColorCustomizationSectionLabel,
settingsGeneralSettingsLabel,
settingsStartupLabel,
settingsCallsLabel,
settingsMigrationSectionLabel
).forEach {
it.setTextColor(getProperPrimaryColor())
}
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
updateMenuItemColors(menu)
return super.onCreateOptionsMenu(menu)
}
private fun setupPurchaseThankYou() {
binding.settingsPurchaseThankYouHolder.beGoneIf(isOrWasThankYouInstalled())
binding.settingsPurchaseThankYouHolder.setOnClickListener {
launchPurchaseThankYouIntent()
}
}
private fun setupCustomizeColors() {
binding.settingsColorCustomizationLabel.text = getCustomizeColorsString()
binding.settingsColorCustomizationHolder.setOnClickListener {
handleCustomizeColorsClick()
}
}
private fun setupUseEnglish() {
binding.apply {
settingsUseEnglishHolder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus())
settingsUseEnglish.isChecked = config.useEnglish
settingsUseEnglishHolder.setOnClickListener {
settingsUseEnglish.toggle()
config.useEnglish = settingsUseEnglish.isChecked
exitProcess(0)
}
}
}
private fun setupLanguage() {
binding.apply {
settingsLanguage.text = Locale.getDefault().displayLanguage
settingsLanguageHolder.beVisibleIf(isTiramisuPlus())
settingsLanguageHolder.setOnClickListener {
launchChangeAppLanguageIntent()
}
}
}
// support for device-wise blocking came on Android 7, rely only on that
@TargetApi(Build.VERSION_CODES.N)
private fun setupManageBlockedNumbers() {
binding.apply {
settingsManageBlockedNumbersLabel.text = addLockedLabelIfNeeded(R.string.manage_blocked_numbers)
settingsManageBlockedNumbersHolder.beVisibleIf(isNougatPlus())
settingsManageBlockedNumbersHolder.setOnClickListener {
if (isOrWasThankYouInstalled()) {
Intent(this@SettingsActivity, ManageBlockedNumbersActivity::class.java).apply {
startActivity(this)
}
} else {
FeatureLockedDialog(this@SettingsActivity) { }
}
}
}
}
private fun setupManageSpeedDial() {
binding.settingsManageSpeedDialHolder.setOnClickListener {
Intent(this, ManageSpeedDialActivity::class.java).apply {
startActivity(this)
}
}
}
private fun setupChangeDateTimeFormat() {
binding.settingsChangeDateTimeFormatHolder.setOnClickListener {
ChangeDateTimeFormatDialog(this) {}
}
}
private fun setupFontSize() {
binding.settingsFontSize.text = getFontSizeText()
binding.settingsFontSizeHolder.setOnClickListener {
val items = arrayListOf(
RadioItem(FONT_SIZE_SMALL, getString(R.string.small)),
RadioItem(FONT_SIZE_MEDIUM, getString(R.string.medium)),
RadioItem(FONT_SIZE_LARGE, getString(R.string.large)),
RadioItem(FONT_SIZE_EXTRA_LARGE, getString(R.string.extra_large))
)
RadioGroupDialog(this@SettingsActivity, items, config.fontSize) {
config.fontSize = it as Int
binding.settingsFontSize.text = getFontSizeText()
}
}
}
private fun setupManageShownTabs() {
binding.settingsManageTabsHolder.setOnClickListener {
ManageVisibleTabsDialog(this)
}
}
private fun setupDefaultTab() {
binding.settingsDefaultTab.text = getDefaultTabText()
binding.settingsDefaultTabHolder.setOnClickListener {
val items = arrayListOf(
RadioItem(TAB_CONTACTS, getString(R.string.contacts_tab)),
RadioItem(TAB_FAVORITES, getString(R.string.favorites_tab)),
RadioItem(TAB_CALL_HISTORY, getString(R.string.call_history_tab)),
RadioItem(TAB_LAST_USED, getString(R.string.last_used_tab))
)
RadioGroupDialog(this@SettingsActivity, items, config.defaultTab) {
config.defaultTab = it as Int
binding.settingsDefaultTab.text = getDefaultTabText()
}
}
}
private fun getDefaultTabText() = getString(
when (baseConfig.defaultTab) {
TAB_CONTACTS -> R.string.contacts_tab
TAB_FAVORITES -> R.string.favorites_tab
TAB_CALL_HISTORY -> R.string.call_history_tab
else -> R.string.last_used_tab
}
)
private fun setupDialPadOpen() {
binding.apply {
settingsOpenDialpadAtLaunch.isChecked = config.openDialPadAtLaunch
settingsOpenDialpadAtLaunchHolder.setOnClickListener {
settingsOpenDialpadAtLaunch.toggle()
config.openDialPadAtLaunch = settingsOpenDialpadAtLaunch.isChecked
}
}
}
private fun setupGroupSubsequentCalls() {
binding.apply {
settingsGroupSubsequentCalls.isChecked = config.groupSubsequentCalls
settingsGroupSubsequentCallsHolder.setOnClickListener {
settingsGroupSubsequentCalls.toggle()
config.groupSubsequentCalls = settingsGroupSubsequentCalls.isChecked
}
}
}
private fun setupStartNameWithSurname() {
binding.apply {
settingsStartNameWithSurname.isChecked = config.startNameWithSurname
settingsStartNameWithSurnameHolder.setOnClickListener {
settingsStartNameWithSurname.toggle()
config.startNameWithSurname = settingsStartNameWithSurname.isChecked
}
}
}
private fun setupDialpadVibrations() {
binding.apply {
settingsDialpadVibration.isChecked = config.dialpadVibration
settingsDialpadVibrationHolder.setOnClickListener {
settingsDialpadVibration.toggle()
config.dialpadVibration = settingsDialpadVibration.isChecked
}
}
}
private fun setupDialpadNumbers() {
binding.apply {
settingsHideDialpadNumbers.isChecked = config.hideDialpadNumbers
settingsHideDialpadNumbersHolder.setOnClickListener {
settingsHideDialpadNumbers.toggle()
config.hideDialpadNumbers = settingsHideDialpadNumbers.isChecked
}
}
}
private fun setupDialpadBeeps() {
binding.apply {
settingsDialpadBeeps.isChecked = config.dialpadBeeps
settingsDialpadBeepsHolder.setOnClickListener {
settingsDialpadBeeps.toggle()
config.dialpadBeeps = settingsDialpadBeeps.isChecked
}
}
}
private fun setupShowCallConfirmation() {
binding.apply {
settingsShowCallConfirmation.isChecked = config.showCallConfirmation
settingsShowCallConfirmationHolder.setOnClickListener {
settingsShowCallConfirmation.toggle()
config.showCallConfirmation = settingsShowCallConfirmation.isChecked
}
}
}
private fun setupDisableProximitySensor() {
binding.apply {
settingsDisableProximitySensor.isChecked = config.disableProximitySensor
settingsDisableProximitySensorHolder.setOnClickListener {
settingsDisableProximitySensor.toggle()
config.disableProximitySensor = settingsDisableProximitySensor.isChecked
}
}
}
private fun setupDisableSwipeToAnswer() {
binding.apply {
settingsDisableSwipeToAnswer.isChecked = config.disableSwipeToAnswer
settingsDisableSwipeToAnswerHolder.setOnClickListener {
settingsDisableSwipeToAnswer.toggle()
config.disableSwipeToAnswer = settingsDisableSwipeToAnswer.isChecked
}
}
}
private fun setupAlwaysShowFullscreen() {
binding.apply {
settingsAlwaysShowFullscreen.isChecked = config.alwaysShowFullscreen
settingsAlwaysShowFullscreenHolder.setOnClickListener {
settingsAlwaysShowFullscreen.toggle()
config.alwaysShowFullscreen = settingsAlwaysShowFullscreen.isChecked
}
}
}
private fun setupCallsExport() {
binding.settingsExportCallsHolder.setOnClickListener {
ExportCallHistoryDialog(this) { filename ->
saveDocument.launch(filename)
}
}
}
private fun setupCallsImport() {
binding.settingsImportCallsHolder.setOnClickListener {
getContent.launch(CALL_HISTORY_FILE_TYPE)
}
}
private fun importCallHistory(uri: Uri) {
try {
val jsonString = contentResolver.openInputStream(uri)!!.use { inputStream ->
inputStream.bufferedReader().readText()
}
val objects = Json.decodeFromString<List<RecentCall>>(jsonString)
if (objects.isEmpty()) {
toast(R.string.no_entries_for_importing)
return
}
RecentsHelper(this).restoreRecentCalls(this, objects) {
toast(R.string.importing_successful)
}
} catch (_: SerializationException) {
toast(R.string.invalid_file_format)
} catch (_: IllegalArgumentException) {
toast(R.string.invalid_file_format)
} catch (e: Exception) {
showErrorToast(e)
}
}
private fun exportCallHistory(recents: List<RecentCall>, uri: Uri) {
if (recents.isEmpty()) {
toast(R.string.no_entries_for_exporting)
} else {
try {
val outputStream = contentResolver.openOutputStream(uri)!!
val jsonString = Json.encodeToString(recents)
outputStream.use {
it.write(jsonString.toByteArray())
}
toast(R.string.exporting_successful)
} catch (e: Exception) {
showErrorToast(e)
}
}
}
}