Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 30b70077 authored by Pat Manning's avatar Pat Manning
Browse files

Generate content description for shortcut label and actions together.

Fix: 373261052
Test: ShortcutHelperCategoriesInteractorTest
Test: ShortcutHelperViewModelTest
Test: Manual. Talkback.
Flag: EXEMPT Bugfix.
Change-Id: I8d6b0e999e8f5a4a890be941240f579c860b7636
parent 91860244
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -87,6 +87,10 @@ object TestShortcuts {
                key("Shift")
                key("M")
            }
            contentDescription {
                "${shortcutInfoWithRepeatedLabel.label}, " +
                    "Press key Meta plus H, or Meta plus L, or Shift plus M"
            }
        }

    private val goHomeShortcutInfo =
@@ -109,6 +113,7 @@ object TestShortcuts {
                key(R.drawable.ic_ksh_key_meta)
                key("N")
            }
            contentDescription { "${standardShortcutInfo1.label}, Press key Meta plus N" }
        }

    private val customGoHomeShortcut =
@@ -119,6 +124,7 @@ object TestShortcuts {
                key("A")
                isCustom(true)
            }
            contentDescription { "Go to home screen, Press key Ctrl plus Alt plus A" }
        }

    private val standardShortcutInfo2 =
@@ -135,6 +141,7 @@ object TestShortcuts {
                key("Shift")
                key("Z")
            }
            contentDescription { "${standardShortcutInfo2.label}, Press key Alt plus Shift plus Z" }
        }

    private val standardShortcutInfo3 =
@@ -150,6 +157,7 @@ object TestShortcuts {
                key("Ctrl")
                key("J")
            }
            contentDescription { "${standardShortcutInfo3.label}, Press key Ctrl plus J" }
        }

    private val shortcutInfoWithUnsupportedModifiers =
@@ -205,6 +213,7 @@ object TestShortcuts {
                key("Ctrl")
                key("Space")
            }
            contentDescription { "Switch to next language, Press key Ctrl plus Space" }
        }

    private val switchToPreviousLanguageShortcut =
@@ -214,6 +223,9 @@ object TestShortcuts {
                key("Shift")
                key("Space")
            }
            contentDescription {
                "Switch to previous language, Press key Ctrl plus Shift plus Space"
            }
        }

    private val subCategoryForInputLanguageSwitchShortcuts =
@@ -292,6 +304,10 @@ object TestShortcuts {
                            key("A")
                            isCustom(true)
                        }
                        contentDescription {
                            "Go to home screen, Press key Ctrl plus Alt plus B, " +
                                "or Ctrl plus Alt plus A"
                        }
                    }
                ),
        )
+36 −0
Original line number Diff line number Diff line
@@ -333,6 +333,42 @@ class ShortcutHelperCategoriesInteractorTest : SysuiTestCase() {
        }
    }

    @Test
    fun categories_addsSameContentDescriptionForShortcutsOfSameType() {
        testScope.runTest {
            setCustomInputGestures(listOf(customInputGestureTypeHome))
            systemShortcutsSource.setGroups(groupWithGoHomeShortcutInfo)
            helper.showFromActivity()

            val categories by collectLastValue(interactor.shortcutCategories)
            val contentDescriptions =
                categories?.flatMap {
                    it.subCategories.flatMap { it.shortcuts.map { it.contentDescription } }
                }

            assertThat(contentDescriptions)
                .containsExactly(
                    "Go to home screen, Press key Ctrl plus Alt plus B, or Ctrl plus Alt plus A",
                    "Standard shortcut 3, Press key Ctrl plus J",
                    "Standard shortcut 2, Press key Alt plus Shift plus Z",
                    "Standard shortcut 1, Press key Meta plus N",
                    "Standard shortcut 1, Press key Meta plus N",
                    "Standard shortcut 2, Press key Alt plus Shift plus Z",
                    "Standard shortcut 3, Press key Ctrl plus J",
                    "Switch to next language, Press key Ctrl plus Space",
                    "Switch to previous language, Press key Ctrl plus Shift plus Space",
                    "Standard shortcut 1, Press key Meta plus N",
                    "Standard shortcut 2, Press key Alt plus Shift plus Z",
                    "Standard shortcut 3, Press key Ctrl plus J",
                    "Standard shortcut 3, Press key Ctrl plus J",
                    "Standard shortcut 2, Press key Alt plus Shift plus Z",
                    "Standard shortcut 1, Press key Meta plus N",
                    "Standard shortcut 2, Press key Alt plus Shift plus Z",
                    "Standard shortcut 1, Press key Meta plus N",
                )
        }
    }

    private fun setCustomInputGestures(customInputGestures: List<InputGestureData>) {
        whenever(fakeInputManager.inputManager.getCustomInputGestures(/* filter= */ anyOrNull()))
            .thenReturn(customInputGestures)
+8 −0
Original line number Diff line number Diff line
@@ -3816,6 +3816,14 @@
         [CHAR LIMIT=NONE]
          -->
    <string name="shortcut_helper_key_combinations_or_separator">or</string>
    <!-- Word that combines different possible key combinations of a shortcut. For example the
         "Go to home screen" shortcut could be triggered using "ctrl" plus "h".
         This is only used for accessibility content descriptions of the key combinations.
         [CHAR LIMIT=NONE] -->
    <string name="shortcut_helper_key_combinations_and_conjunction">plus</string>
    <!-- Word that represents the forward slash character "/". To be used only in accessibility
         content descriptions. [CHAR LIMIT=NONE] -->
    <string name="shortcut_helper_key_combinations_forward_slash">forward slash</string>
    <!-- Content description of the drag handle that allows to swipe to dismiss the shortcut helper.
         The helper is a  component that shows the  user which keyboard shortcuts they can
         use. The helper shows shortcuts in categories, which can be collapsed or expanded.
+1 −0
Original line number Diff line number Diff line
@@ -140,6 +140,7 @@ object ShortcutHelperKeys {
        mapOf<Int, (Context) -> String>(
            KEYCODE_HOME to { context -> context.getString(R.string.keyboard_key_home) },
            KEYCODE_BACK to { context -> context.getString(R.string.keyboard_key_back) },
            KEYCODE_RECENT_APPS to { context -> context.getString(R.string.accessibility_recent) },
            KEYCODE_DPAD_UP to { context -> context.getString(R.string.keyboard_key_dpad_up) },
            KEYCODE_DPAD_DOWN to { context -> context.getString(R.string.keyboard_key_dpad_down) },
            KEYCODE_DPAD_LEFT to { context -> context.getString(R.string.keyboard_key_dpad_left) },
+57 −0
Original line number Diff line number Diff line
@@ -16,14 +16,22 @@

package com.android.systemui.keyboard.shortcut.domain.interactor

import android.content.Context
import android.view.KeyEvent.META_META_ON
import com.android.systemui.Flags.keyboardShortcutHelperShortcutCustomizer
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyboard.shortcut.data.repository.ShortcutCategoriesRepository
import com.android.systemui.keyboard.shortcut.data.repository.ShortcutHelperKeys
import com.android.systemui.keyboard.shortcut.data.repository.ShortcutHelperKeys.metaModifierIconResId
import com.android.systemui.keyboard.shortcut.qualifiers.CustomShortcutCategories
import com.android.systemui.keyboard.shortcut.qualifiers.DefaultShortcutCategories
import com.android.systemui.keyboard.shortcut.shared.model.Shortcut
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategory
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCommand
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutSubCategory
import com.android.systemui.res.R
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
@@ -34,6 +42,7 @@ import kotlinx.coroutines.flow.flowOf
class ShortcutHelperCategoriesInteractor
@Inject
constructor(
    @Application private val context: Context,
    @DefaultShortcutCategories defaultCategoriesRepository: ShortcutCategoriesRepository,
    @CustomShortcutCategories customCategoriesRepositoryLazy: Lazy<ShortcutCategoriesRepository>,
) {
@@ -87,6 +96,54 @@ constructor(
                    label = commonLabel,
                    icon = groupedShortcuts.firstOrNull()?.icon,
                    commands = groupedShortcuts.flatMap { it.commands },
                    contentDescription =
                        toContentDescription(commonLabel, groupedShortcuts.flatMap { it.commands }),
                )
            }

    private fun toContentDescription(label: String, commands: List<ShortcutCommand>): String {
        val pressKey = context.getString(R.string.shortcut_helper_add_shortcut_dialog_placeholder)
        val andConjunction =
            context.getString(R.string.shortcut_helper_key_combinations_and_conjunction)
        val orConjunction =
            context.getString(R.string.shortcut_helper_key_combinations_or_separator)
        val forwardSlash =
            context.getString(R.string.shortcut_helper_key_combinations_forward_slash)
        return buildString {
            append("$label, $pressKey")
            commands.forEachIndexed { i, shortcutCommand ->
                if (i > 0) {
                    append(", $orConjunction")
                }
                shortcutCommand.keys.forEachIndexed { j, shortcutKey ->
                    if (j > 0) {
                        append(" $andConjunction")
                    }
                    if (shortcutKey is ShortcutKey.Text) {
                        // Special handling for "/" as TalkBack will not read punctuation by
                        // default.
                        if (shortcutKey.value.equals("/")) {
                            append(" $forwardSlash")
                        } else {
                            append(" ${shortcutKey.value}")
                        }
                    } else if (shortcutKey is ShortcutKey.Icon.ResIdIcon) {
                        val keyLabel =
                            if (shortcutKey.drawableResId == metaModifierIconResId) {
                                ShortcutHelperKeys.modifierLabels[META_META_ON]
                            } else {
                                val keyCode =
                                    ShortcutHelperKeys.keyIcons.entries
                                        .firstOrNull { it.value == shortcutKey.drawableResId }
                                        ?.key
                                ShortcutHelperKeys.specialKeyLabels[keyCode]
                            }
                        if (keyLabel != null) {
                            append(" ${keyLabel.invoke(context)}")
                        }
                    } // No-Op when shortcutKey is ShortcutKey.Icon.DrawableIcon
                }
            }
        }
    }
}
Loading