kopia lustrzana https://github.com/ryukoposting/Signal-Android
385 wiersze
14 KiB
Kotlin
385 wiersze
14 KiB
Kotlin
package org.thoughtcrime.securesms.components.settings.app.internal
|
|
|
|
import android.content.ClipData
|
|
import android.content.ClipboardManager
|
|
import android.content.Context
|
|
import android.content.DialogInterface
|
|
import android.widget.Toast
|
|
import androidx.lifecycle.ViewModelProvider
|
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
import org.signal.core.util.concurrent.SignalExecutors
|
|
import org.thoughtcrime.securesms.BuildConfig
|
|
import org.thoughtcrime.securesms.R
|
|
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
|
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
|
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
|
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
|
import org.thoughtcrime.securesms.components.settings.configure
|
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
|
import org.thoughtcrime.securesms.database.LocalMetricsDatabase
|
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
|
import org.thoughtcrime.securesms.jobs.RefreshAttributesJob
|
|
import org.thoughtcrime.securesms.jobs.RefreshOwnProfileJob
|
|
import org.thoughtcrime.securesms.jobs.RemoteConfigRefreshJob
|
|
import org.thoughtcrime.securesms.jobs.RotateProfileKeyJob
|
|
import org.thoughtcrime.securesms.jobs.StorageForcePushJob
|
|
import org.thoughtcrime.securesms.payments.DataExportUtil
|
|
import org.thoughtcrime.securesms.util.ConversationUtil
|
|
import org.thoughtcrime.securesms.util.concurrent.SimpleTask
|
|
|
|
class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__internal_preferences) {
|
|
|
|
private lateinit var viewModel: InternalSettingsViewModel
|
|
|
|
override fun bindAdapter(adapter: DSLSettingsAdapter) {
|
|
val repository = InternalSettingsRepository(requireContext())
|
|
val factory = InternalSettingsViewModel.Factory(repository)
|
|
viewModel = ViewModelProvider(this, factory)[InternalSettingsViewModel::class.java]
|
|
|
|
viewModel.state.observe(viewLifecycleOwner) {
|
|
adapter.submitList(getConfiguration(it).toMappingModelList())
|
|
}
|
|
}
|
|
|
|
private fun getConfiguration(state: InternalSettingsState): DSLConfiguration {
|
|
return configure {
|
|
sectionHeaderPref(R.string.preferences__internal_payments)
|
|
|
|
clickPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_payment_copy_data),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_payment_copy_data_description),
|
|
onClick = {
|
|
copyPaymentsDataToClipboard()
|
|
}
|
|
)
|
|
|
|
dividerPref()
|
|
|
|
sectionHeaderPref(R.string.preferences__internal_account)
|
|
|
|
clickPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_refresh_attributes),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_refresh_attributes_description),
|
|
onClick = {
|
|
refreshAttributes()
|
|
}
|
|
)
|
|
|
|
clickPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_rotate_profile_key),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_rotate_profile_key_description),
|
|
onClick = {
|
|
rotateProfileKey()
|
|
}
|
|
)
|
|
|
|
clickPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_refresh_remote_config),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_refresh_remote_config_description),
|
|
onClick = {
|
|
refreshRemoteValues()
|
|
}
|
|
)
|
|
|
|
dividerPref()
|
|
|
|
sectionHeaderPref(R.string.preferences__internal_misc)
|
|
|
|
switchPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_user_details),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_user_details_description),
|
|
isChecked = state.seeMoreUserDetails,
|
|
onClick = {
|
|
viewModel.setSeeMoreUserDetails(!state.seeMoreUserDetails)
|
|
}
|
|
)
|
|
|
|
switchPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_shake_to_report),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_shake_to_report_description),
|
|
isChecked = state.shakeToReport,
|
|
onClick = {
|
|
viewModel.setShakeToReport(!state.shakeToReport)
|
|
}
|
|
)
|
|
|
|
dividerPref()
|
|
|
|
sectionHeaderPref(R.string.preferences__internal_storage_service)
|
|
|
|
clickPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_force_storage_service_sync),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_force_storage_service_sync_description),
|
|
onClick = {
|
|
forceStorageServiceSync()
|
|
}
|
|
)
|
|
|
|
dividerPref()
|
|
|
|
sectionHeaderPref(R.string.preferences__internal_preferences_groups_v2)
|
|
|
|
switchPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_do_not_create_gv2),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_do_not_create_gv2_description),
|
|
isChecked = state.gv2doNotCreateGv2Groups,
|
|
onClick = {
|
|
viewModel.setGv2DoNotCreateGv2Groups(!state.gv2doNotCreateGv2Groups)
|
|
}
|
|
)
|
|
|
|
switchPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_force_gv2_invites),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_force_gv2_invites_description),
|
|
isChecked = state.gv2forceInvites,
|
|
onClick = {
|
|
viewModel.setGv2ForceInvites(!state.gv2forceInvites)
|
|
}
|
|
)
|
|
|
|
switchPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_ignore_gv2_server_changes),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_ignore_gv2_server_changes_description),
|
|
isChecked = state.gv2ignoreServerChanges,
|
|
onClick = {
|
|
viewModel.setGv2IgnoreServerChanges(!state.gv2ignoreServerChanges)
|
|
}
|
|
)
|
|
|
|
switchPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_ignore_gv2_p2p_changes),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_ignore_gv2_server_changes_description),
|
|
isChecked = state.gv2ignoreP2PChanges,
|
|
onClick = {
|
|
viewModel.setGv2IgnoreP2PChanges(!state.gv2ignoreP2PChanges)
|
|
}
|
|
)
|
|
|
|
dividerPref()
|
|
|
|
sectionHeaderPref(R.string.preferences__internal_preferences_groups_v1_migration)
|
|
|
|
switchPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_do_not_initiate_automigrate),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_do_not_initiate_automigrate_description),
|
|
isChecked = state.disableAutoMigrationInitiation,
|
|
onClick = {
|
|
viewModel.setDisableAutoMigrationInitiation(!state.disableAutoMigrationInitiation)
|
|
}
|
|
)
|
|
|
|
switchPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_do_not_notify_automigrate),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_do_not_notify_automigrate_description),
|
|
isChecked = state.disableAutoMigrationNotification,
|
|
onClick = {
|
|
viewModel.setDisableAutoMigrationNotification(!state.disableAutoMigrationNotification)
|
|
}
|
|
)
|
|
|
|
dividerPref()
|
|
|
|
sectionHeaderPref(R.string.preferences__internal_network)
|
|
|
|
switchPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_force_censorship),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_force_censorship_description),
|
|
isChecked = state.forceCensorship,
|
|
onClick = {
|
|
viewModel.setForceCensorship(!state.forceCensorship)
|
|
}
|
|
)
|
|
|
|
dividerPref()
|
|
|
|
sectionHeaderPref(R.string.preferences__internal_conversations_and_shortcuts)
|
|
|
|
clickPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_delete_all_dynamic_shortcuts),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_click_to_delete_all_dynamic_shortcuts),
|
|
onClick = {
|
|
deleteAllDynamicShortcuts()
|
|
}
|
|
)
|
|
|
|
dividerPref()
|
|
|
|
sectionHeaderPref(R.string.preferences__internal_emoji)
|
|
|
|
val emojiSummary = if (state.emojiVersion == null) {
|
|
getString(R.string.preferences__internal_use_built_in_emoji_set)
|
|
} else {
|
|
getString(
|
|
R.string.preferences__internal_current_version_d_at_density_s,
|
|
state.emojiVersion.version,
|
|
state.emojiVersion.density
|
|
)
|
|
}
|
|
|
|
switchPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_use_built_in_emoji_set),
|
|
summary = DSLSettingsText.from(emojiSummary),
|
|
isChecked = state.useBuiltInEmojiSet,
|
|
onClick = {
|
|
viewModel.setUseBuiltInEmoji(!state.useBuiltInEmojiSet)
|
|
}
|
|
)
|
|
|
|
dividerPref()
|
|
|
|
sectionHeaderPref(R.string.preferences__internal_sender_key)
|
|
|
|
clickPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_clear_all_state),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_click_to_delete_all_sender_key_state),
|
|
onClick = {
|
|
clearAllSenderKeyState()
|
|
}
|
|
)
|
|
|
|
clickPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_clear_shared_state),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_click_to_delete_all_sharing_state),
|
|
onClick = {
|
|
clearAllSenderKeySharedState()
|
|
}
|
|
)
|
|
|
|
switchPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_remove_two_person_minimum),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_remove_the_requirement_that_you_need),
|
|
isChecked = state.removeSenderKeyMinimium,
|
|
onClick = {
|
|
viewModel.setRemoveSenderKeyMinimum(!state.removeSenderKeyMinimium)
|
|
}
|
|
)
|
|
|
|
switchPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_delay_resends),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_delay_resending_messages_in_response_to_retry_receipts),
|
|
isChecked = state.delayResends,
|
|
onClick = {
|
|
viewModel.setDelayResends(!state.delayResends)
|
|
}
|
|
)
|
|
|
|
dividerPref()
|
|
|
|
sectionHeaderPref(R.string.preferences__internal_local_metrics)
|
|
|
|
clickPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_clear_local_metrics),
|
|
summary = DSLSettingsText.from(R.string.preferences__internal_click_to_clear_all_local_metrics_state),
|
|
onClick = {
|
|
clearAllLocalMetricsState()
|
|
}
|
|
)
|
|
|
|
dividerPref()
|
|
|
|
sectionHeaderPref(R.string.preferences__internal_calling)
|
|
|
|
radioPref(
|
|
title = DSLSettingsText.from(R.string.preferences__internal_calling_default),
|
|
summary = DSLSettingsText.from(BuildConfig.SIGNAL_SFU_URL),
|
|
isChecked = state.callingServer == BuildConfig.SIGNAL_SFU_URL,
|
|
onClick = {
|
|
viewModel.setInternalGroupCallingServer(null)
|
|
}
|
|
)
|
|
|
|
BuildConfig.SIGNAL_SFU_INTERNAL_NAMES.zip(BuildConfig.SIGNAL_SFU_INTERNAL_URLS)
|
|
.forEach { (name, server) ->
|
|
radioPref(
|
|
title = DSLSettingsText.from(requireContext().getString(R.string.preferences__internal_calling_s_server, name)),
|
|
summary = DSLSettingsText.from(server),
|
|
isChecked = state.callingServer == server,
|
|
onClick = {
|
|
viewModel.setInternalGroupCallingServer(server)
|
|
}
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun copyPaymentsDataToClipboard() {
|
|
MaterialAlertDialogBuilder(requireContext())
|
|
.setMessage(
|
|
"""
|
|
Local payments history will be copied to the clipboard.
|
|
It may therefore compromise privacy.
|
|
However, no private keys will be copied.
|
|
""".trimIndent()
|
|
)
|
|
.setPositiveButton(
|
|
"Copy"
|
|
) { _: DialogInterface?, _: Int ->
|
|
SimpleTask.run<Any?>(
|
|
SignalExecutors.UNBOUNDED,
|
|
{
|
|
val context: Context = ApplicationDependencies.getApplication()
|
|
val clipboard =
|
|
context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
val tsv = DataExportUtil.createTsv()
|
|
val clip = ClipData.newPlainText(context.getString(R.string.app_name), tsv)
|
|
clipboard.setPrimaryClip(clip)
|
|
null
|
|
},
|
|
{
|
|
Toast.makeText(
|
|
context,
|
|
"Payments have been copied",
|
|
Toast.LENGTH_SHORT
|
|
).show()
|
|
}
|
|
)
|
|
}
|
|
.setNegativeButton(android.R.string.cancel, null)
|
|
.show()
|
|
}
|
|
|
|
private fun refreshAttributes() {
|
|
ApplicationDependencies.getJobManager()
|
|
.startChain(RefreshAttributesJob())
|
|
.then(RefreshOwnProfileJob())
|
|
.enqueue()
|
|
Toast.makeText(context, "Scheduled attribute refresh", Toast.LENGTH_SHORT).show()
|
|
}
|
|
|
|
private fun rotateProfileKey() {
|
|
ApplicationDependencies.getJobManager().add(RotateProfileKeyJob())
|
|
Toast.makeText(context, "Scheduled profile key rotation", Toast.LENGTH_SHORT).show()
|
|
}
|
|
|
|
private fun refreshRemoteValues() {
|
|
ApplicationDependencies.getJobManager().add(RemoteConfigRefreshJob())
|
|
Toast.makeText(context, "Scheduled remote config refresh", Toast.LENGTH_SHORT).show()
|
|
}
|
|
|
|
private fun forceStorageServiceSync() {
|
|
ApplicationDependencies.getJobManager().add(StorageForcePushJob())
|
|
Toast.makeText(context, "Scheduled storage force push", Toast.LENGTH_SHORT).show()
|
|
}
|
|
|
|
private fun deleteAllDynamicShortcuts() {
|
|
ConversationUtil.clearAllShortcuts(requireContext())
|
|
Toast.makeText(context, "Deleted all dynamic shortcuts.", Toast.LENGTH_SHORT).show()
|
|
}
|
|
|
|
private fun clearAllSenderKeyState() {
|
|
DatabaseFactory.getSenderKeyDatabase(requireContext()).deleteAll()
|
|
DatabaseFactory.getSenderKeySharedDatabase(requireContext()).deleteAll()
|
|
Toast.makeText(context, "Deleted all sender key state.", Toast.LENGTH_SHORT).show()
|
|
}
|
|
|
|
private fun clearAllSenderKeySharedState() {
|
|
DatabaseFactory.getSenderKeySharedDatabase(requireContext()).deleteAll()
|
|
Toast.makeText(context, "Deleted all sender key shared state.", Toast.LENGTH_SHORT).show()
|
|
}
|
|
|
|
private fun clearAllLocalMetricsState() {
|
|
LocalMetricsDatabase.getInstance(ApplicationDependencies.getApplication()).clear()
|
|
Toast.makeText(context, "Cleared all local metrics state.", Toast.LENGTH_SHORT).show()
|
|
}
|
|
}
|