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

Commit ecfe1370 authored by Chris Göllner's avatar Chris Göllner Committed by Android (Google) Code Review
Browse files

Merge "Shortcut Helper - Add "Default apps" shortcuts" into main

parents dfe94e4b 5ab886bd
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -20,10 +20,12 @@ import android.app.Activity
import com.android.systemui.CoreStartable
import com.android.systemui.Flags.keyboardShortcutHelperRewrite
import com.android.systemui.keyboard.shortcut.data.repository.ShortcutHelperStateRepository
import com.android.systemui.keyboard.shortcut.data.source.AppCategoriesShortcutsSource
import com.android.systemui.keyboard.shortcut.data.source.InputShortcutsSource
import com.android.systemui.keyboard.shortcut.data.source.KeyboardShortcutGroupsSource
import com.android.systemui.keyboard.shortcut.data.source.MultitaskingShortcutsSource
import com.android.systemui.keyboard.shortcut.data.source.SystemShortcutsSource
import com.android.systemui.keyboard.shortcut.qualifiers.AppCategoriesShortcuts
import com.android.systemui.keyboard.shortcut.qualifiers.InputShortcuts
import com.android.systemui.keyboard.shortcut.qualifiers.MultitaskingShortcuts
import com.android.systemui.keyboard.shortcut.qualifiers.SystemShortcuts
@@ -56,6 +58,12 @@ interface ShortcutHelperModule {
    @InputShortcuts
    fun inputShortcutsSources(impl: InputShortcutsSource): KeyboardShortcutGroupsSource

    @Binds
    @AppCategoriesShortcuts
    fun appCategoriesShortcutsSource(
        impl: AppCategoriesShortcutsSource
    ): KeyboardShortcutGroupsSource

    companion object {
        @Provides
        @IntoMap
+54 −10
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.keyboard.shortcut.data.repository

import android.content.Context
import android.graphics.drawable.Icon
import android.hardware.input.InputManager
import android.util.Log
import android.view.KeyCharacterMap
@@ -26,17 +27,20 @@ import android.view.KeyboardShortcutInfo
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.keyboard.shortcut.data.source.KeyboardShortcutGroupsSource
import com.android.systemui.keyboard.shortcut.qualifiers.AppCategoriesShortcuts
import com.android.systemui.keyboard.shortcut.qualifiers.InputShortcuts
import com.android.systemui.keyboard.shortcut.qualifiers.MultitaskingShortcuts
import com.android.systemui.keyboard.shortcut.qualifiers.SystemShortcuts
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.ShortcutCategoryType
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.APP_CATEGORIES
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.IME
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.MULTI_TASKING
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.SYSTEM
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCommand
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutHelperState.Active
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutIcon
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutSubCategory
import javax.inject.Inject
@@ -52,6 +56,7 @@ constructor(
    @Background private val backgroundDispatcher: CoroutineDispatcher,
    @SystemShortcuts private val systemShortcutsSource: KeyboardShortcutGroupsSource,
    @MultitaskingShortcuts private val multitaskingShortcutsSource: KeyboardShortcutGroupsSource,
    @AppCategoriesShortcuts private val appCategoriesShortcutsSource: KeyboardShortcutGroupsSource,
    @InputShortcuts private val inputShortcutsSource: KeyboardShortcutGroupsSource,
    private val inputManager: InputManager,
    stateRepository: ShortcutHelperStateRepository
@@ -72,7 +77,8 @@ constructor(
                toShortcutCategory(
                    it.keyCharacterMap,
                    SYSTEM,
                    systemShortcutsSource.shortcutGroups(it.id)
                    systemShortcutsSource.shortcutGroups(it.id),
                    keepIcons = true,
                )
            } else {
                null
@@ -85,7 +91,22 @@ constructor(
                toShortcutCategory(
                    it.keyCharacterMap,
                    MULTI_TASKING,
                    multitaskingShortcutsSource.shortcutGroups(it.id)
                    multitaskingShortcutsSource.shortcutGroups(it.id),
                    keepIcons = true,
                )
            } else {
                null
            }
        }

    val appCategoriesShortcutsCategory =
        activeInputDevice.map {
            if (it != null) {
                toShortcutCategory(
                    it.keyCharacterMap,
                    APP_CATEGORIES,
                    appCategoriesShortcutsSource.shortcutGroups(it.id),
                    keepIcons = true,
                )
            } else {
                null
@@ -98,7 +119,8 @@ constructor(
                toShortcutCategory(
                    it.keyCharacterMap,
                    IME,
                    inputShortcutsSource.shortcutGroups(it.id)
                    inputShortcutsSource.shortcutGroups(it.id),
                    keepIcons = false,
                )
            } else {
                null
@@ -109,13 +131,14 @@ constructor(
        keyCharacterMap: KeyCharacterMap,
        type: ShortcutCategoryType,
        shortcutGroups: List<KeyboardShortcutGroup>,
        keepIcons: Boolean,
    ): ShortcutCategory? {
        val subCategories =
            shortcutGroups
                .map { shortcutGroup ->
                    ShortcutSubCategory(
                        shortcutGroup.label.toString(),
                        toShortcuts(keyCharacterMap, shortcutGroup.items)
                        toShortcuts(keyCharacterMap, shortcutGroup.items, keepIcons)
                    )
                }
                .filter { it.shortcuts.isNotEmpty() }
@@ -129,16 +152,37 @@ constructor(

    private fun toShortcuts(
        keyCharacterMap: KeyCharacterMap,
        infoList: List<KeyboardShortcutInfo>
    ) = infoList.mapNotNull { toShortcut(keyCharacterMap, it) }
        infoList: List<KeyboardShortcutInfo>,
        keepIcons: Boolean,
    ) = infoList.mapNotNull { toShortcut(keyCharacterMap, it, keepIcons) }

    private fun toShortcut(
        keyCharacterMap: KeyCharacterMap,
        shortcutInfo: KeyboardShortcutInfo
        shortcutInfo: KeyboardShortcutInfo,
        keepIcon: Boolean,
    ): Shortcut? {
        val shortcutCommand = toShortcutCommand(keyCharacterMap, shortcutInfo)
        return if (shortcutCommand == null) null
        else Shortcut(label = shortcutInfo.label!!.toString(), commands = listOf(shortcutCommand))
        val shortcutCommand = toShortcutCommand(keyCharacterMap, shortcutInfo) ?: return null
        return Shortcut(
            label = shortcutInfo.label!!.toString(),
            icon = toShortcutIcon(keepIcon, shortcutInfo),
            commands = listOf(shortcutCommand)
        )
    }

    private fun toShortcutIcon(
        keepIcon: Boolean,
        shortcutInfo: KeyboardShortcutInfo
    ): ShortcutIcon? {
        if (!keepIcon) {
            return null
        }
        val icon = shortcutInfo.icon ?: return null
        // For now only keep icons of type resource, which is what the "default apps" shortcuts
        // provide.
        if (icon.type != Icon.TYPE_RESOURCE || icon.resPackage.isNullOrEmpty() || icon.resId <= 0) {
            return null
        }
        return ShortcutIcon(packageName = icon.resPackage, resourceId = icon.resId)
    }

    private fun toShortcutCommand(
+107 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.keyboard.shortcut.data.source

import android.content.Intent
import android.content.res.Resources
import android.view.KeyEvent
import android.view.KeyboardShortcutGroup
import android.view.KeyboardShortcutInfo
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.res.R
import com.android.systemui.util.icons.AppCategoryIconProvider
import javax.inject.Inject

class AppCategoriesShortcutsSource
@Inject
constructor(
    private val appCategoryIconProvider: AppCategoryIconProvider,
    @Main private val resources: Resources,
) : KeyboardShortcutGroupsSource {

    override suspend fun shortcutGroups(deviceId: Int) =
        listOf(
            KeyboardShortcutGroup(
                /* label = */ resources.getString(R.string.keyboard_shortcut_group_applications),
                /* items = */ shortcuts()
            )
        )

    private suspend fun shortcuts(): List<KeyboardShortcutInfo> =
        listOfNotNull(
                assistantAppShortcutInfo(),
                appCategoryShortcutInfo(
                    Intent.CATEGORY_APP_BROWSER,
                    R.string.keyboard_shortcut_group_applications_browser,
                    KeyEvent.KEYCODE_B
                ),
                appCategoryShortcutInfo(
                    Intent.CATEGORY_APP_CONTACTS,
                    R.string.keyboard_shortcut_group_applications_contacts,
                    KeyEvent.KEYCODE_C
                ),
                appCategoryShortcutInfo(
                    Intent.CATEGORY_APP_EMAIL,
                    R.string.keyboard_shortcut_group_applications_email,
                    KeyEvent.KEYCODE_E
                ),
                appCategoryShortcutInfo(
                    Intent.CATEGORY_APP_CALENDAR,
                    R.string.keyboard_shortcut_group_applications_calendar,
                    KeyEvent.KEYCODE_K
                ),
                appCategoryShortcutInfo(
                    Intent.CATEGORY_APP_MAPS,
                    R.string.keyboard_shortcut_group_applications_maps,
                    KeyEvent.KEYCODE_M
                ),
                appCategoryShortcutInfo(
                    Intent.CATEGORY_APP_MUSIC,
                    R.string.keyboard_shortcut_group_applications_music,
                    KeyEvent.KEYCODE_P
                ),
                appCategoryShortcutInfo(
                    Intent.CATEGORY_APP_MESSAGING,
                    R.string.keyboard_shortcut_group_applications_sms,
                    KeyEvent.KEYCODE_S
                ),
                appCategoryShortcutInfo(
                    Intent.CATEGORY_APP_CALCULATOR,
                    R.string.keyboard_shortcut_group_applications_calculator,
                    KeyEvent.KEYCODE_U
                ),
            )
            .sortedBy { it.label!!.toString().lowercase() }

    private suspend fun assistantAppShortcutInfo(): KeyboardShortcutInfo? {
        val assistantIcon = appCategoryIconProvider.assistantAppIcon() ?: return null
        return KeyboardShortcutInfo(
            /* label = */ resources.getString(R.string.keyboard_shortcut_group_applications_assist),
            /* icon = */ assistantIcon,
            /* keycode = */ KeyEvent.KEYCODE_A,
            /* modifiers = */ KeyEvent.META_META_ON,
        )
    }

    private suspend fun appCategoryShortcutInfo(category: String, labelResId: Int, keycode: Int) =
        KeyboardShortcutInfo(
            /* label = */ resources.getString(labelResId),
            /* icon = */ appCategoryIconProvider.categoryAppIcon(category),
            /* keycode = */ keycode,
            /* modifiers = */ KeyEvent.META_META_ON,
        )
}
+11 −8
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import com.android.systemui.keyboard.shortcut.shared.model.ShortcutSubCategory
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map

@SysUISingleton
class ShortcutHelperCategoriesInteractor
@@ -33,13 +32,13 @@ constructor(
    categoriesRepository: ShortcutHelperCategoriesRepository,
) {

    private val systemsShortcutCategory = categoriesRepository.systemShortcutsCategory
    private val multitaskingShortcutsCategory = categoriesRepository.multitaskingShortcutsCategory
    private val imeShortcutsCategory = categoriesRepository.imeShortcutsCategory

    val shortcutCategories: Flow<List<ShortcutCategory>> =
        combine(systemsShortcutCategory, multitaskingShortcutsCategory, imeShortcutsCategory) {
            shortcutCategories ->
        combine(
            categoriesRepository.systemShortcutsCategory,
            categoriesRepository.multitaskingShortcutsCategory,
            categoriesRepository.imeShortcutsCategory,
            categoriesRepository.appCategoriesShortcutsCategory,
        ) { shortcutCategories ->
            shortcutCategories.filterNotNull().map { groupSubCategoriesInCategory(it) }
        }

@@ -62,6 +61,10 @@ constructor(
            .groupBy { it.label }
            .entries
            .map { (commonLabel, groupedShortcuts) ->
                Shortcut(label = commonLabel, commands = groupedShortcuts.flatMap { it.commands })
                Shortcut(
                    label = commonLabel,
                    icon = groupedShortcuts.firstOrNull()?.icon,
                    commands = groupedShortcuts.flatMap { it.commands }
                )
            }
}
+21 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.keyboard.shortcut.qualifiers

import javax.inject.Qualifier

@Qualifier annotation class AppCategoriesShortcuts
Loading