Simple-SMS-Messenger/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/SettingsActivity.kt

420 lines
17 KiB
Kotlin

package com.simplemobiletools.smsmessenger.activities
import android.annotation.TargetApi
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import androidx.activity.result.contract.ActivityResultContracts
import com.simplemobiletools.commons.activities.ManageBlockedNumbersActivity
import com.simplemobiletools.commons.dialogs.*
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.databinding.ActivitySettingsBinding
import com.simplemobiletools.smsmessenger.dialogs.ExportMessagesDialog
import com.simplemobiletools.smsmessenger.extensions.config
import com.simplemobiletools.smsmessenger.extensions.emptyMessagesRecycleBin
import com.simplemobiletools.smsmessenger.extensions.messagesDB
import com.simplemobiletools.smsmessenger.helpers.*
import com.simplemobiletools.smsmessenger.models.*
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.util.*
import kotlin.system.exitProcess
class SettingsActivity : SimpleActivity() {
private var blockedNumbersAtPause = -1
private var recycleBinMessages = 0
private val messagesFileType = "application/json"
private val messageImportFileTypes = listOf("application/json", "application/xml", "text/xml")
private val binding by viewBinding(ActivitySettingsBinding::inflate)
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(binding.root)
updateMaterialActivityViews(
mainCoordinatorLayout = binding.settingsCoordinator,
nestedView = binding.settingsHolder,
useTransparentNavigation = true,
useTopSearchMenu = false
)
setupMaterialScrollListener(scrollingView = binding.settingsNestedScrollview, toolbar = binding.settingsToolbar)
}
override fun onResume() {
super.onResume()
setupToolbar(binding.settingsToolbar, NavigationIcon.Arrow)
setupPurchaseThankYou()
setupCustomizeColors()
setupCustomizeNotifications()
setupUseEnglish()
setupLanguage()
setupManageBlockedNumbers()
setupManageBlockedKeywords()
setupChangeDateTimeFormat()
setupFontSize()
setupShowCharacterCounter()
setupUseSimpleCharacters()
setupSendOnEnter()
setupEnableDeliveryReports()
setupSendLongMessageAsMMS()
setupGroupMessageAsMMS()
setupLockScreenVisibility()
setupMMSFileSizeLimit()
setupUseRecycleBin()
setupEmptyRecycleBin()
setupAppPasswordProtection()
setupMessagesExport()
setupMessagesImport()
updateTextColors(binding.settingsNestedScrollview)
if (blockedNumbersAtPause != -1 && blockedNumbersAtPause != getBlockedNumbers().hashCode()) {
refreshMessages()
}
arrayOf(
binding.settingsColorCustomizationSectionLabel,
binding.settingsGeneralSettingsLabel,
binding.settingsOutgoingMessagesLabel,
binding.settingsNotificationsLabel,
binding.settingsEmptyRecycleBinLabel,
binding.settingsSecurityLabel,
binding.settingsMigratingLabel
).forEach {
it.setTextColor(getProperPrimaryColor())
}
}
private val getContent = registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri ->
if (uri != null) {
MessagesImporter(this).importMessages(uri)
}
}
private val saveDocument = registerForActivityResult(ActivityResultContracts.CreateDocument(messagesFileType)) { uri ->
if (uri != null) {
toast(com.simplemobiletools.commons.R.string.exporting)
exportMessages(uri)
}
}
private fun setupMessagesExport() {
binding.settingsExportMessagesHolder.setOnClickListener {
ExportMessagesDialog(this) { fileName ->
saveDocument.launch(fileName)
}
}
}
private fun setupMessagesImport() {
binding.settingsImportMessagesHolder.setOnClickListener {
getContent.launch(messageImportFileTypes.toTypedArray())
}
}
private fun exportMessages(uri: Uri) {
ensureBackgroundThread {
try {
MessagesReader(this).getMessagesToExport(config.exportSms, config.exportMms) { messagesToExport ->
if (messagesToExport.isEmpty()) {
toast(com.simplemobiletools.commons.R.string.no_entries_for_exporting)
return@getMessagesToExport
}
val json = Json { encodeDefaults = true }
val jsonString = json.encodeToString(messagesToExport)
val outputStream = contentResolver.openOutputStream(uri)!!
outputStream.use {
it.write(jsonString.toByteArray())
}
toast(com.simplemobiletools.commons.R.string.exporting_successful)
}
} catch (e: Exception) {
showErrorToast(e)
}
}
}
override fun onPause() {
super.onPause()
blockedNumbersAtPause = getBlockedNumbers().hashCode()
}
private fun setupPurchaseThankYou() = binding.apply {
settingsPurchaseThankYouHolder.beGoneIf(isOrWasThankYouInstalled())
settingsPurchaseThankYouHolder.setOnClickListener {
launchPurchaseThankYouIntent()
}
}
private fun setupCustomizeColors() = binding.apply {
settingsColorCustomizationLabel.text = getCustomizeColorsString()
settingsColorCustomizationHolder.setOnClickListener {
handleCustomizeColorsClick()
}
}
private fun setupCustomizeNotifications() = binding.apply {
settingsCustomizeNotificationsHolder.beVisibleIf(isOreoPlus())
settingsCustomizeNotificationsHolder.setOnClickListener {
launchCustomizeNotificationsIntent()
}
}
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 {
settingsManageBlockedNumbers.text = addLockedLabelIfNeeded(com.simplemobiletools.commons.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 setupManageBlockedKeywords() = binding.apply {
settingsManageBlockedKeywords.text = addLockedLabelIfNeeded(R.string.manage_blocked_keywords)
settingsManageBlockedKeywordsHolder.setOnClickListener {
if (isOrWasThankYouInstalled()) {
Intent(this@SettingsActivity, ManageBlockedKeywordsActivity::class.java).apply {
startActivity(this)
}
} else {
FeatureLockedDialog(this@SettingsActivity) { }
}
}
}
private fun setupChangeDateTimeFormat() = binding.apply {
settingsChangeDateTimeFormatHolder.setOnClickListener {
ChangeDateTimeFormatDialog(this@SettingsActivity) {
refreshMessages()
}
}
}
private fun setupFontSize() = binding.apply {
settingsFontSize.text = getFontSizeText()
settingsFontSizeHolder.setOnClickListener {
val items = arrayListOf(
RadioItem(FONT_SIZE_SMALL, getString(com.simplemobiletools.commons.R.string.small)),
RadioItem(FONT_SIZE_MEDIUM, getString(com.simplemobiletools.commons.R.string.medium)),
RadioItem(FONT_SIZE_LARGE, getString(com.simplemobiletools.commons.R.string.large)),
RadioItem(FONT_SIZE_EXTRA_LARGE, getString(com.simplemobiletools.commons.R.string.extra_large))
)
RadioGroupDialog(this@SettingsActivity, items, config.fontSize) {
config.fontSize = it as Int
settingsFontSize.text = getFontSizeText()
}
}
}
private fun setupShowCharacterCounter() = binding.apply {
settingsShowCharacterCounter.isChecked = config.showCharacterCounter
settingsShowCharacterCounterHolder.setOnClickListener {
settingsShowCharacterCounter.toggle()
config.showCharacterCounter = settingsShowCharacterCounter.isChecked
}
}
private fun setupUseSimpleCharacters() = binding.apply {
settingsUseSimpleCharacters.isChecked = config.useSimpleCharacters
settingsUseSimpleCharactersHolder.setOnClickListener {
settingsUseSimpleCharacters.toggle()
config.useSimpleCharacters = settingsUseSimpleCharacters.isChecked
}
}
private fun setupSendOnEnter() = binding.apply {
settingsSendOnEnter.isChecked = config.sendOnEnter
settingsSendOnEnterHolder.setOnClickListener {
settingsSendOnEnter.toggle()
config.sendOnEnter = settingsSendOnEnter.isChecked
}
}
private fun setupEnableDeliveryReports() = binding.apply {
settingsEnableDeliveryReports.isChecked = config.enableDeliveryReports
settingsEnableDeliveryReportsHolder.setOnClickListener {
settingsEnableDeliveryReports.toggle()
config.enableDeliveryReports = settingsEnableDeliveryReports.isChecked
}
}
private fun setupSendLongMessageAsMMS() = binding.apply {
settingsSendLongMessageMms.isChecked = config.sendLongMessageMMS
settingsSendLongMessageMmsHolder.setOnClickListener {
settingsSendLongMessageMms.toggle()
config.sendLongMessageMMS = settingsSendLongMessageMms.isChecked
}
}
private fun setupGroupMessageAsMMS() = binding.apply {
settingsSendGroupMessageMms.isChecked = config.sendGroupMessageMMS
settingsSendGroupMessageMmsHolder.setOnClickListener {
settingsSendGroupMessageMms.toggle()
config.sendGroupMessageMMS = settingsSendGroupMessageMms.isChecked
}
}
private fun setupLockScreenVisibility() = binding.apply {
settingsLockScreenVisibility.text = getLockScreenVisibilityText()
settingsLockScreenVisibilityHolder.setOnClickListener {
val items = arrayListOf(
RadioItem(LOCK_SCREEN_SENDER_MESSAGE, getString(R.string.sender_and_message)),
RadioItem(LOCK_SCREEN_SENDER, getString(R.string.sender_only)),
RadioItem(LOCK_SCREEN_NOTHING, getString(com.simplemobiletools.commons.R.string.nothing)),
)
RadioGroupDialog(this@SettingsActivity, items, config.lockScreenVisibilitySetting) {
config.lockScreenVisibilitySetting = it as Int
settingsLockScreenVisibility.text = getLockScreenVisibilityText()
}
}
}
private fun getLockScreenVisibilityText() = getString(
when (config.lockScreenVisibilitySetting) {
LOCK_SCREEN_SENDER_MESSAGE -> R.string.sender_and_message
LOCK_SCREEN_SENDER -> R.string.sender_only
else -> com.simplemobiletools.commons.R.string.nothing
}
)
private fun setupMMSFileSizeLimit() = binding.apply {
settingsMmsFileSizeLimit.text = getMMSFileLimitText()
settingsMmsFileSizeLimitHolder.setOnClickListener {
val items = arrayListOf(
RadioItem(7, getString(R.string.mms_file_size_limit_none), FILE_SIZE_NONE),
RadioItem(6, getString(R.string.mms_file_size_limit_2mb), FILE_SIZE_2_MB),
RadioItem(5, getString(R.string.mms_file_size_limit_1mb), FILE_SIZE_1_MB),
RadioItem(4, getString(R.string.mms_file_size_limit_600kb), FILE_SIZE_600_KB),
RadioItem(3, getString(R.string.mms_file_size_limit_300kb), FILE_SIZE_300_KB),
RadioItem(2, getString(R.string.mms_file_size_limit_200kb), FILE_SIZE_200_KB),
RadioItem(1, getString(R.string.mms_file_size_limit_100kb), FILE_SIZE_100_KB),
)
val checkedItemId = items.find { it.value == config.mmsFileSizeLimit }?.id ?: 7
RadioGroupDialog(this@SettingsActivity, items, checkedItemId) {
config.mmsFileSizeLimit = it as Long
settingsMmsFileSizeLimit.text = getMMSFileLimitText()
}
}
}
private fun setupUseRecycleBin() = binding.apply {
updateRecycleBinButtons()
settingsUseRecycleBin.isChecked = config.useRecycleBin
settingsUseRecycleBinHolder.setOnClickListener {
settingsUseRecycleBin.toggle()
config.useRecycleBin = settingsUseRecycleBin.isChecked
updateRecycleBinButtons()
}
}
private fun updateRecycleBinButtons() = binding.apply {
settingsEmptyRecycleBinHolder.beVisibleIf(config.useRecycleBin)
}
private fun setupEmptyRecycleBin() = binding.apply {
ensureBackgroundThread {
recycleBinMessages = messagesDB.getArchivedCount()
runOnUiThread {
settingsEmptyRecycleBinSize.text =
resources.getQuantityString(R.plurals.delete_messages, recycleBinMessages, recycleBinMessages)
}
}
settingsEmptyRecycleBinHolder.setOnClickListener {
if (recycleBinMessages == 0) {
toast(com.simplemobiletools.commons.R.string.recycle_bin_empty)
} else {
ConfirmationDialog(
activity = this@SettingsActivity,
message = "",
messageId = R.string.empty_recycle_bin_messages_confirmation,
positive = com.simplemobiletools.commons.R.string.yes,
negative = com.simplemobiletools.commons.R.string.no
) {
ensureBackgroundThread {
emptyMessagesRecycleBin()
}
recycleBinMessages = 0
settingsEmptyRecycleBinSize.text =
resources.getQuantityString(R.plurals.delete_messages, recycleBinMessages, recycleBinMessages)
}
}
}
}
private fun setupAppPasswordProtection() = binding.apply {
settingsAppPasswordProtection.isChecked = config.isAppPasswordProtectionOn
settingsAppPasswordProtectionHolder.setOnClickListener {
val tabToShow = if (config.isAppPasswordProtectionOn) config.appProtectionType else SHOW_ALL_TABS
SecurityDialog(this@SettingsActivity, config.appPasswordHash, tabToShow) { hash, type, success ->
if (success) {
val hasPasswordProtection = config.isAppPasswordProtectionOn
settingsAppPasswordProtection.isChecked = !hasPasswordProtection
config.isAppPasswordProtectionOn = !hasPasswordProtection
config.appPasswordHash = if (hasPasswordProtection) "" else hash
config.appProtectionType = type
if (config.isAppPasswordProtectionOn) {
val confirmationTextId = if (config.appProtectionType == PROTECTION_FINGERPRINT) {
com.simplemobiletools.commons.R.string.fingerprint_setup_successfully
} else {
com.simplemobiletools.commons.R.string.protection_setup_successfully
}
ConfirmationDialog(this@SettingsActivity, "", confirmationTextId, com.simplemobiletools.commons.R.string.ok, 0) { }
}
}
}
}
}
private fun getMMSFileLimitText() = getString(
when (config.mmsFileSizeLimit) {
FILE_SIZE_100_KB -> R.string.mms_file_size_limit_100kb
FILE_SIZE_200_KB -> R.string.mms_file_size_limit_200kb
FILE_SIZE_300_KB -> R.string.mms_file_size_limit_300kb
FILE_SIZE_600_KB -> R.string.mms_file_size_limit_600kb
FILE_SIZE_1_MB -> R.string.mms_file_size_limit_1mb
FILE_SIZE_2_MB -> R.string.mms_file_size_limit_2mb
else -> R.string.mms_file_size_limit_none
}
)
}