improvement: Show category in passkeys directory and correctly select items with the same name

This commit is contained in:
Artem Chepurnoy 2024-03-30 13:12:11 +02:00
parent b402e038bc
commit e0949a7042
No known key found for this signature in database
GPG Key ID: FAC37D0CF674043E
8 changed files with 618 additions and 107 deletions

View File

@ -1,6 +1,7 @@
import json import json
import requests import requests
import argparse import argparse
import hashlib
parser = argparse.ArgumentParser("update_passkeys") parser = argparse.ArgumentParser("update_passkeys")
parser.add_argument("api_key", help="An API Key to access the https://passkeys.directory/ backend.", type=str) parser.add_argument("api_key", help="An API Key to access the https://passkeys.directory/ backend.", type=str)
@ -23,8 +24,14 @@ response = requests.get(
aggr = [] aggr = []
for site in response.json(): for site in response.json():
# generate a unique id
id_str = site['name'] + '|' + site['domain'] + '|' + (site.get('created_at') or '')
id = hashlib\
.md5(id_str.encode('utf-8'))\
.hexdigest()
features = [] features = []
entry = { entry = {
'id': id,
'name': site['name'], 'name': site['name'],
'domain': site['domain'], 'domain': site['domain'],
'features': features, 'features': features,
@ -36,6 +43,8 @@ for site in response.json():
append_if_not_empty('documentation_link', 'documentation') append_if_not_empty('documentation_link', 'documentation')
append_if_not_empty('setup_link', 'setup') append_if_not_empty('setup_link', 'setup')
append_if_not_empty('category', 'category')
append_if_not_empty('created_at', 'created_at')
append_if_not_empty('notes', 'notes') append_if_not_empty('notes', 'notes')
# convert features to a list # convert features to a list

View File

@ -1,11 +1,16 @@
package com.artemchep.keyguard.common.service.passkey package com.artemchep.keyguard.common.service.passkey
import kotlinx.datetime.Instant
data class PassKeyServiceInfo( data class PassKeyServiceInfo(
val id: String,
val name: String, val name: String,
val domain: String, val domain: String,
val domains: Set<String> = emptySet(), val domains: Set<String> = emptySet(),
val setup: String? = null, val setup: String? = null,
val documentation: String? = null, val documentation: String? = null,
val notes: String? = null, val notes: String? = null,
val category: String? = null,
val addedAt: Instant? = null,
val features: Set<String> = emptySet(), val features: Set<String> = emptySet(),
) )

View File

@ -8,6 +8,7 @@ import com.artemchep.keyguard.common.service.passkey.PassKeyServiceInfo
import com.artemchep.keyguard.common.service.text.TextService import com.artemchep.keyguard.common.service.text.TextService
import com.artemchep.keyguard.common.service.text.readFromResourcesAsText import com.artemchep.keyguard.common.service.text.readFromResourcesAsText
import com.artemchep.keyguard.res.Res import com.artemchep.keyguard.res.Res
import kotlinx.datetime.Instant
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
@ -16,6 +17,7 @@ import org.kodein.di.instance
@Serializable @Serializable
data class PassKeyEntity( data class PassKeyEntity(
val id: String,
val name: String, val name: String,
val domain: String, val domain: String,
@SerialName("additional-domains") @SerialName("additional-domains")
@ -23,17 +25,23 @@ data class PassKeyEntity(
val setup: String? = null, val setup: String? = null,
val documentation: String? = null, val documentation: String? = null,
val notes: String? = null, val notes: String? = null,
val category: String? = null,
@SerialName("created_at")
val createdAt: Instant? = null,
val features: Set<String> = emptySet(), val features: Set<String> = emptySet(),
) )
fun PassKeyEntity.toDomain() = kotlin.run { fun PassKeyEntity.toDomain() = kotlin.run {
PassKeyServiceInfo( PassKeyServiceInfo(
id = id,
name = name, name = name,
domain = domain, domain = domain,
domains = domains + domain, domains = domains + domain,
setup = setup, setup = setup,
documentation = documentation, documentation = documentation,
notes = notes, notes = notes,
category = category,
addedAt = createdAt,
features = features, features = features,
) )
} }

View File

@ -258,7 +258,7 @@ private fun AppItem(
val nextEntry = navigationNextEntryOrNull() val nextEntry = navigationNextEntryOrNull()
val nextRoute = nextEntry?.route as? PasskeysServiceViewFullRoute val nextRoute = nextEntry?.route as? PasskeysServiceViewFullRoute
val selected = nextRoute?.args?.model?.name == item.name.text val selected = nextRoute?.args?.model?.id == item.data.id
if (selected) { if (selected) {
return@run MaterialTheme.colorScheme.selectedContainer return@run MaterialTheme.colorScheme.selectedContainer
} }

View File

@ -82,10 +82,10 @@ fun producePasskeysListState(
.map { serviceInfo -> .map { serviceInfo ->
val key = kotlin.run { val key = kotlin.run {
val newNameCollisionCounter = nameCollisions val newNameCollisionCounter = nameCollisions
.getOrDefault(serviceInfo.name, 0) + 1 .getOrDefault(serviceInfo.id, 0) + 1
nameCollisions[serviceInfo.name] = nameCollisions[serviceInfo.id] =
newNameCollisionCounter newNameCollisionCounter
serviceInfo.name + ":" + newNameCollisionCounter serviceInfo.id + ":" + newNameCollisionCounter
} }
val faviconUrl = serviceInfo.documentation?.let { url -> val faviconUrl = serviceInfo.documentation?.let { url ->
FaviconUrl( FaviconUrl(

View File

@ -29,6 +29,7 @@ import androidx.compose.ui.unit.dp
import com.artemchep.keyguard.common.model.Loadable import com.artemchep.keyguard.common.model.Loadable
import com.artemchep.keyguard.common.model.getOrNull import com.artemchep.keyguard.common.model.getOrNull
import com.artemchep.keyguard.feature.dialog.Dialog import com.artemchep.keyguard.feature.dialog.Dialog
import com.artemchep.keyguard.feature.home.vault.component.Section
import com.artemchep.keyguard.feature.navigation.NavigationIcon import com.artemchep.keyguard.feature.navigation.NavigationIcon
import com.artemchep.keyguard.feature.tfa.directory.FlatLaunchBrowserItem import com.artemchep.keyguard.feature.tfa.directory.FlatLaunchBrowserItem
import com.artemchep.keyguard.res.Res import com.artemchep.keyguard.res.Res
@ -194,14 +195,26 @@ fun ColumnScope.Content(
.padding(horizontal = Dimens.horizontalPadding), .padding(horizontal = Dimens.horizontalPadding),
markdown = notes, markdown = notes,
) )
Spacer( }
val category = state?.model?.category
if (category != null) {
Section(
text = stringResource(Res.strings.category),
)
Text(
modifier = Modifier modifier = Modifier
.height(16.dp), .padding(horizontal = Dimens.horizontalPadding),
text = category,
) )
} }
val documentationUrl = state?.model?.documentation val documentationUrl = state?.model?.documentation
if (documentationUrl != null) { if (documentationUrl != null) {
Spacer(
modifier = Modifier
.height(16.dp),
)
FlatLaunchBrowserItem( FlatLaunchBrowserItem(
title = stringResource(Res.strings.uri_action_launch_docs_title), title = stringResource(Res.strings.uri_action_launch_docs_title),
url = documentationUrl, url = documentationUrl,

View File

@ -89,6 +89,7 @@
<string name="organizations">Organizations</string> <string name="organizations">Organizations</string>
<string name="organizations_empty_label">No organizations</string> <string name="organizations_empty_label">No organizations</string>
<string name="misc">Miscellaneous</string> <string name="misc">Miscellaneous</string>
<string name="category">Category</string>
<string name="command">Command</string> <string name="command">Command</string>
<string name="execute_command">Execute</string> <string name="execute_command">Execute</string>
<!-- Add (something) --> <!-- Add (something) -->

File diff suppressed because it is too large Load Diff