1 /*
<lambda>null2  * Copyright (C) 2023 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.0N
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.credentialmanager.ui.mappers
18 
19 import android.graphics.drawable.Drawable
20 import com.android.credentialmanager.model.Request
21 import com.android.credentialmanager.CredentialSelectorUiState
22 import com.android.credentialmanager.CredentialSelectorUiState.Get.MultipleEntry.PerNameEntries
23 import com.android.credentialmanager.model.CredentialType
24 import com.android.credentialmanager.model.get.CredentialEntryInfo
25 import java.time.Instant
26 
27 fun Request.Get.toGet(isPrimary: Boolean): CredentialSelectorUiState.Get {
28 
29     val accounts = providerInfos
30         .flatMap { it.credentialEntryList }
31         .groupBy {
32             if (it.displayName.isNullOrBlank()) it.userName else checkNotNull(it.displayName)
33         }
34         .entries
35         .toList()
36 
37     return if (isPrimary) {
38         if (accounts.size == 1) {
39             CredentialSelectorUiState.Get.SingleEntry(
40                 entry = accounts[0].value.minWith(comparator)
41             )
42         } else {
43             val sortedEntries = accounts.map {
44                 it.value.minWith(comparator)
45             }.sortedWith(comparator)
46 
47             var icon: Drawable? = null
48             // provide icon if all entries have the same provider
49             if (sortedEntries.isNotEmpty() &&
50                 sortedEntries.all {it.providerId == sortedEntries[0].providerId}) {
51                 icon = providerInfos[0].icon
52             }
53 
54             CredentialSelectorUiState.Get.MultipleEntryPrimaryScreen(
55                 sortedEntries = sortedEntries,
56                 icon = icon,
57                 authenticationEntryList = providerInfos.flatMap { it.authenticationEntryList }
58             )
59         }
60     } else {
61         CredentialSelectorUiState.Get.MultipleEntry(
62             accounts = accounts.map { PerNameEntries(
63                 it.key,
64                 it.value.sortedWith(comparator)
65             )
66             },
67             actionEntryList = providerInfos.flatMap { it.actionEntryList },
68             authenticationEntryList = providerInfos.flatMap { it.authenticationEntryList }
69         )
70     }
71 }
entryInfonull72 val comparator = compareBy<CredentialEntryInfo> { entryInfo ->
73     // Passkey type always go first
74     entryInfo.credentialType.let { if (it == CredentialType.PASSKEY) 0 else 1 }
75 }.thenByDescending { it.lastUsedTimeMillis ?: Instant.EPOCH }
76