1 /* <lambda>null2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.keyboard.shortcut.data.repository 18 19 import android.view.KeyboardShortcutGroup 20 import android.view.KeyboardShortcutInfo 21 import com.android.systemui.dagger.SysUISingleton 22 import com.android.systemui.dagger.qualifiers.Background 23 import com.android.systemui.keyboard.shortcut.data.model.InternalKeyboardShortcutGroup 24 import com.android.systemui.keyboard.shortcut.data.model.InternalKeyboardShortcutInfo 25 import com.android.systemui.keyboard.shortcut.data.source.KeyboardShortcutGroupsSource 26 import com.android.systemui.keyboard.shortcut.qualifiers.AccessibilityShortcuts 27 import com.android.systemui.keyboard.shortcut.qualifiers.AppCategoriesShortcuts 28 import com.android.systemui.keyboard.shortcut.qualifiers.CurrentAppShortcuts 29 import com.android.systemui.keyboard.shortcut.qualifiers.InputShortcuts 30 import com.android.systemui.keyboard.shortcut.qualifiers.MultitaskingShortcuts 31 import com.android.systemui.keyboard.shortcut.qualifiers.SystemShortcuts 32 import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategory 33 import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType 34 import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.Accessibility 35 import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.AppCategories 36 import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.CurrentApp 37 import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.InputMethodEditor 38 import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.MultiTasking 39 import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.System 40 import javax.inject.Inject 41 import kotlinx.coroutines.CoroutineScope 42 import kotlinx.coroutines.flow.Flow 43 import kotlinx.coroutines.flow.SharingStarted 44 import kotlinx.coroutines.flow.map 45 import kotlinx.coroutines.flow.stateIn 46 47 @SysUISingleton 48 class DefaultShortcutCategoriesRepository 49 @Inject 50 constructor( 51 @Background private val backgroundScope: CoroutineScope, 52 @SystemShortcuts systemShortcutsSource: KeyboardShortcutGroupsSource, 53 @MultitaskingShortcuts multitaskingShortcutsSource: KeyboardShortcutGroupsSource, 54 @AppCategoriesShortcuts appCategoriesShortcutsSource: KeyboardShortcutGroupsSource, 55 @InputShortcuts inputShortcutsSource: KeyboardShortcutGroupsSource, 56 @CurrentAppShortcuts currentAppShortcutsSource: KeyboardShortcutGroupsSource, 57 @AccessibilityShortcuts accessibilityShortcutsSource: KeyboardShortcutGroupsSource, 58 inputDeviceRepository: ShortcutHelperInputDeviceRepository, 59 shortcutCategoriesUtils: ShortcutCategoriesUtils, 60 ) : ShortcutCategoriesRepository { 61 62 private val sources = 63 listOf( 64 InternalGroupsSource(source = systemShortcutsSource, typeProvider = { System }), 65 InternalGroupsSource( 66 source = multitaskingShortcutsSource, 67 typeProvider = { MultiTasking }, 68 ), 69 InternalGroupsSource( 70 source = appCategoriesShortcutsSource, 71 typeProvider = { AppCategories }, 72 ), 73 InternalGroupsSource( 74 source = inputShortcutsSource, 75 typeProvider = { InputMethodEditor }, 76 ), 77 InternalGroupsSource( 78 source = accessibilityShortcutsSource, 79 typeProvider = { Accessibility }, 80 ), 81 InternalGroupsSource( 82 source = currentAppShortcutsSource, 83 typeProvider = { groups -> getCurrentAppShortcutCategoryType(groups) }, 84 ), 85 ) 86 87 override val categories: Flow<List<ShortcutCategory>> = 88 inputDeviceRepository.activeInputDevice 89 .map { inputDevice -> 90 if (inputDevice == null) { 91 return@map emptyList() 92 } 93 val groupsFromAllSources = 94 sources.map { 95 toInternalKeyboardShortcutGroups(it.source.shortcutGroups(inputDevice.id)) 96 } 97 val supportedKeyCodes = 98 shortcutCategoriesUtils.fetchSupportedKeyCodes( 99 inputDevice.id, 100 groupsFromAllSources, 101 ) 102 return@map sources.mapIndexedNotNull { index, internalGroupsSource -> 103 shortcutCategoriesUtils.fetchShortcutCategory( 104 internalGroupsSource.typeProvider(groupsFromAllSources[index]), 105 groupsFromAllSources[index], 106 inputDevice, 107 supportedKeyCodes, 108 ) 109 } 110 } 111 .stateIn( 112 scope = backgroundScope, 113 started = SharingStarted.Lazily, 114 initialValue = emptyList(), 115 ) 116 117 private fun toInternalKeyboardShortcutGroups( 118 keyboardShortcutGroups: List<KeyboardShortcutGroup> 119 ): List<InternalKeyboardShortcutGroup> { 120 return keyboardShortcutGroups.map { group -> 121 InternalKeyboardShortcutGroup( 122 label = group.label.toString(), 123 items = group.items.map { toInternalKeyboardShortcutInfo(it) }, 124 packageName = group.packageName?.toString(), 125 ) 126 } 127 } 128 129 private fun toInternalKeyboardShortcutInfo( 130 keyboardShortcutInfo: KeyboardShortcutInfo 131 ): InternalKeyboardShortcutInfo { 132 return InternalKeyboardShortcutInfo( 133 label = keyboardShortcutInfo.label!!.toString(), 134 keycode = keyboardShortcutInfo.keycode, 135 modifiers = keyboardShortcutInfo.modifiers, 136 baseCharacter = keyboardShortcutInfo.baseCharacter, 137 icon = keyboardShortcutInfo.icon, 138 ) 139 } 140 141 private fun getCurrentAppShortcutCategoryType( 142 shortcutGroups: List<InternalKeyboardShortcutGroup> 143 ): ShortcutCategoryType? { 144 val packageName = shortcutGroups.firstOrNull()?.packageName ?: return null 145 return CurrentApp(packageName) 146 } 147 148 private class InternalGroupsSource( 149 val source: KeyboardShortcutGroupsSource, 150 val typeProvider: (groups: List<InternalKeyboardShortcutGroup>) -> ShortcutCategoryType?, 151 ) 152 } 153