Replace time duration picker dialog for screen lock timeout.

This commit is contained in:
Cody Henthorne
2023-02-06 16:14:26 -05:00
committed by Greyson Parrelli
parent db65edb7df
commit 23050152de
10 changed files with 220 additions and 48 deletions

View File

@@ -0,0 +1,101 @@
package org.thoughtcrime.securesms.components
import android.app.Dialog
import android.os.Bundle
import androidx.core.os.bundleOf
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.setFragmentResult
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.databinding.TimeDurationPickerDialogBinding
import kotlin.time.Duration
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.minutes
/**
* Time duration dialog for selection a duration of hours and minutes. Currently
* designed specifically for screen lock but could easily be generalized in the future
* if needed.
*
* Uses [setFragmentResult] to pass the provided duration back in milliseconds.
*/
class TimeDurationPickerDialog : DialogFragment(), NumericKeyboardView.Listener {
private var _binding: TimeDurationPickerDialogBinding? = null
private val binding: TimeDurationPickerDialogBinding
get() = _binding!!
private var duration: String = "0000"
private var full: Boolean = false
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
_binding = TimeDurationPickerDialogBinding.inflate(layoutInflater)
binding.durationKeyboard.listener = this
setDuration(requireArguments().getLong(ARGUMENT_DURATION).milliseconds)
return MaterialAlertDialogBuilder(requireContext())
.setView(binding.root)
.setPositiveButton(R.string.TimeDurationPickerDialog_positive_button) { _, _ ->
setFragmentResult(
RESULT_DURATION,
bundleOf(
RESULT_KEY_DURATION_MILLISECONDS to getDuration().inWholeMilliseconds
)
)
}
.setNegativeButton(android.R.string.cancel, null)
.show()
}
override fun onKeyPress(keyCode: Int) {
if (full && keyCode != -1) {
return
}
duration = if (keyCode == -1) {
"0" + duration.substring(0, 3)
} else {
duration.substring(1) + keyCode
}
updateDuration()
}
private fun updateDuration() {
binding.durationHour.text = duration.substring(0, 2)
binding.durationMinute.text = duration.substring(2)
full = duration.toInt() > 1000
}
private fun setDuration(duration: Duration) {
val hour = duration.inWholeMinutes / 60
val minute = duration.inWholeMinutes.mod(60)
this.duration = String.format("%02d%02d", hour, minute)
updateDuration()
}
private fun getDuration(): Duration {
val hours = duration.substring(0, 2).toInt()
val minutes = duration.substring(2).toInt()
return hours.hours.plus(minutes.minutes)
}
companion object {
const val RESULT_DURATION = "RESULT_DURATION"
const val RESULT_KEY_DURATION_MILLISECONDS = "RESULT_KEY_DURATION_MILLISECONDS"
private const val ARGUMENT_DURATION = "ARGUMENT_DURATION"
fun create(duration: Duration): TimeDurationPickerDialog {
return TimeDurationPickerDialog().apply {
arguments = bundleOf(
ARGUMENT_DURATION to duration.inWholeMilliseconds
)
}
}
}
}

View File

@@ -23,17 +23,15 @@ import androidx.core.content.ContextCompat
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.Navigation
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import androidx.preference.PreferenceManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import mobi.upod.timedurationpicker.TimeDurationPicker
import mobi.upod.timedurationpicker.TimeDurationPickerDialog
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.BiometricDeviceAuthentication
import org.thoughtcrime.securesms.BiometricDeviceLockContract
import org.thoughtcrime.securesms.PassphraseChangeActivity
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.TimeDurationPickerDialog
import org.thoughtcrime.securesms.components.settings.ClickPreference
import org.thoughtcrime.securesms.components.settings.ClickPreferenceViewHolder
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
@@ -56,8 +54,9 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
import org.thoughtcrime.securesms.util.navigation.safeNavigate
import java.lang.Integer.max
import java.util.concurrent.TimeUnit
import kotlin.math.max
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
private val TAG = Log.tag(PrivacySettingsFragment::class.java)
@@ -257,15 +256,13 @@ class PrivacySettingsFragment : DSLSettingsFragment(R.string.preferences__privac
clickPref(
title = DSLSettingsText.from(R.string.preferences__inactivity_timeout_interval),
onClick = {
TimeDurationPickerDialog(
context,
{ _: TimeDurationPicker?, duration: Long ->
val timeoutMinutes = max(TimeUnit.MILLISECONDS.toMinutes(duration).toInt(), 1)
viewModel.setObsoletePasswordTimeout(timeoutMinutes)
},
0,
TimeDurationPicker.HH_MM
).show()
childFragmentManager.clearFragmentResult(TimeDurationPickerDialog.RESULT_DURATION)
childFragmentManager.clearFragmentResultListener(TimeDurationPickerDialog.RESULT_DURATION)
childFragmentManager.setFragmentResultListener(TimeDurationPickerDialog.RESULT_DURATION, this@PrivacySettingsFragment) { _, bundle ->
val timeout = bundle.getLong(TimeDurationPickerDialog.RESULT_KEY_DURATION_MILLISECONDS).milliseconds.inWholeMinutes.toInt()
viewModel.setObsoletePasswordTimeout(max(timeout, 1))
}
TimeDurationPickerDialog.create(state.screenLockActivityTimeout.seconds).show(childFragmentManager, null)
}
)
} else {
@@ -292,15 +289,12 @@ class PrivacySettingsFragment : DSLSettingsFragment(R.string.preferences__privac
summary = DSLSettingsText.from(getScreenLockInactivityTimeoutSummary(state.screenLockActivityTimeout)),
isEnabled = isKeyguardSecure && state.screenLock,
onClick = {
TimeDurationPickerDialog(
context,
{ _: TimeDurationPicker?, duration: Long ->
val timeoutSeconds = TimeUnit.MILLISECONDS.toSeconds(duration)
viewModel.setScreenLockTimeout(timeoutSeconds)
},
0,
TimeDurationPicker.HH_MM
).show()
childFragmentManager.clearFragmentResult(TimeDurationPickerDialog.RESULT_DURATION)
childFragmentManager.clearFragmentResultListener(TimeDurationPickerDialog.RESULT_DURATION)
childFragmentManager.setFragmentResultListener(TimeDurationPickerDialog.RESULT_DURATION, this@PrivacySettingsFragment) { _, bundle ->
viewModel.setScreenLockTimeout(bundle.getLong(TimeDurationPickerDialog.RESULT_KEY_DURATION_MILLISECONDS).milliseconds.inWholeSeconds)
}
TimeDurationPickerDialog.create(state.screenLockActivityTimeout.seconds).show(childFragmentManager, null)
}
)
}