• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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