1
0
Fork 0

For #7970: Updates snackbars for accessibility

master
Sawyer Blatz 2020-01-30 11:27:16 +01:00
parent 82c698c818
commit 1372ed5837
3 changed files with 25 additions and 34 deletions

View File

@ -75,6 +75,7 @@ class FenixSnackbar private constructor(
companion object { companion object {
const val LENGTH_LONG = Snackbar.LENGTH_LONG const val LENGTH_LONG = Snackbar.LENGTH_LONG
const val LENGTH_SHORT = Snackbar.LENGTH_SHORT const val LENGTH_SHORT = Snackbar.LENGTH_SHORT
const val LENGTH_ACCESSIBLE = 15000 /* 15 seconds in ms */
const val LENGTH_INDEFINITE = Snackbar.LENGTH_INDEFINITE const val LENGTH_INDEFINITE = Snackbar.LENGTH_INDEFINITE
private const val minTextSize = 12 private const val minTextSize = 12
@ -82,6 +83,10 @@ class FenixSnackbar private constructor(
private const val actionButtonIncreaseDps = 16 private const val actionButtonIncreaseDps = 16
private const val stepGranularity = 1 private const val stepGranularity = 1
/**
* Display a snackbar in the given view with duration and proper normal/error styling.
* Note: Duration is overriden for users with accessibility settings enabled
*/
fun make(view: View, duration: Int, isError: Boolean = false): FenixSnackbar { fun make(view: View, duration: Int, isError: Boolean = false): FenixSnackbar {
val parent = findSuitableParent(view) ?: run { val parent = findSuitableParent(view) ?: run {
throw IllegalArgumentException( throw IllegalArgumentException(
@ -92,9 +97,15 @@ class FenixSnackbar private constructor(
val inflater = LayoutInflater.from(parent.context) val inflater = LayoutInflater.from(parent.context)
val content = inflater.inflate(R.layout.fenix_snackbar, parent, false) val content = inflater.inflate(R.layout.fenix_snackbar, parent, false)
val durationOrAccessibleDuration = if (parent.context.settings().accessibilityServicesEnabled) {
LENGTH_ACCESSIBLE
} else {
duration
}
val callback = FenixSnackbarCallback(content) val callback = FenixSnackbarCallback(content)
return FenixSnackbar(parent, content, callback, isError).also { return FenixSnackbar(parent, content, callback, isError).also {
it.duration = duration it.duration = durationOrAccessibleDuration
} }
} }

View File

@ -274,6 +274,9 @@ class Settings private constructor(
return accessibilityManager?.isTouchExplorationEnabled ?: false return accessibilityManager?.isTouchExplorationEnabled ?: false
} }
val accessibilityServicesEnabled: Boolean
get() { return touchExplorationIsEnabled || switchServiceIsEnabled }
val toolbarSettingString: String val toolbarSettingString: String
get() = when { get() = when {
shouldUseBottomToolbar -> appContext.getString(R.string.preference_bottom_toolbar) shouldUseBottomToolbar -> appContext.getString(R.string.preference_bottom_toolbar)

View File

@ -10,13 +10,11 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.FenixSnackbar
import android.app.AlertDialog import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.R
import android.content.Context
import android.view.accessibility.AccessibilityManager
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
internal const val UNDO_DELAY = 3000L internal const val UNDO_DELAY = 3000L
internal const val ACCESSIBLE_UNDO_DELAY = 15000L
/** /**
* Runs [operation] after giving user time (see [UNDO_DELAY]) to cancel it. * Runs [operation] after giving user time (see [UNDO_DELAY]) to cancel it.
@ -44,22 +42,6 @@ fun CoroutineScope.allowUndo(
// writing a volatile variable. // writing a volatile variable.
val requestedUndo = AtomicBoolean(false) val requestedUndo = AtomicBoolean(false)
fun showUndoDialog() {
val dialogBuilder = AlertDialog.Builder(view.context)
dialogBuilder.setMessage(message).setCancelable(false)
.setPositiveButton(R.string.a11y_dialog_deleted_confirm) { _, _ ->
launch {
operation.invoke()
}
}.setNegativeButton(R.string.a11y_dialog_deleted_undo) { _, _ ->
launch {
onCancel.invoke()
}
}
val alert = dialogBuilder.create()
alert.show()
}
fun showUndoSnackbar() { fun showUndoSnackbar() {
val snackbar = FenixSnackbar val snackbar = FenixSnackbar
.make(view, FenixSnackbar.LENGTH_INDEFINITE) .make(view, FenixSnackbar.LENGTH_INDEFINITE)
@ -77,7 +59,13 @@ fun CoroutineScope.allowUndo(
// Wait a bit, and if user didn't request cancellation, proceed with // Wait a bit, and if user didn't request cancellation, proceed with
// requested operation and hide the snackbar. // requested operation and hide the snackbar.
launch { launch {
delay(UNDO_DELAY) val lengthToDelay = if (view.context.settings().accessibilityServicesEnabled) {
ACCESSIBLE_UNDO_DELAY
} else {
UNDO_DELAY
}
delay(lengthToDelay)
if (!requestedUndo.get()) { if (!requestedUndo.get()) {
snackbar.dismiss() snackbar.dismiss()
@ -86,16 +74,5 @@ fun CoroutineScope.allowUndo(
} }
} }
// It is difficult to use our Snackbars quickly enough with showUndoSnackbar()
// Talkback enabled, so in that case we show a dialog instead
if (touchExplorationEnabled(view)) {
showUndoDialog()
} else {
showUndoSnackbar()
}
}
fun touchExplorationEnabled(view: View): Boolean {
val am = view.context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
return am.isTouchExplorationEnabled
} }