From b86126f13481facc9fd83546369bba6076fb2e70 Mon Sep 17 00:00:00 2001 From: Daniel Mader Date: Wed, 30 Oct 2024 22:46:24 +0100 Subject: [PATCH 1/2] fix: use colored background when icon fallback is displayed --- unime/src/lib/components/ListItemCard.svelte | 13 ++++++------- unime/src/lib/components/image/Image.svelte | 3 +++ .../routes/credentials/[id]/CredentialHeader.svelte | 6 ++++-- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/unime/src/lib/components/ListItemCard.svelte b/unime/src/lib/components/ListItemCard.svelte index d7f00052..21863eb1 100644 --- a/unime/src/lib/components/ListItemCard.svelte +++ b/unime/src/lib/components/ListItemCard.svelte @@ -10,6 +10,8 @@ export let description: string | undefined = undefined; export let type: 'data' | 'badge' = 'data'; export let isTempAsset = false; + + let useFallback = false; -
- +
+
diff --git a/unime/src/lib/components/image/Image.svelte b/unime/src/lib/components/image/Image.svelte index 902cd70d..6e6e13ae 100644 --- a/unime/src/lib/components/image/Image.svelte +++ b/unime/src/lib/components/image/Image.svelte @@ -20,6 +20,9 @@ export let isTempAsset = false; let assetUrl: string | null = null; + export let useFallback: boolean = false; + $: useFallback = assetUrl === null; + async function loadImage() { getImageAsset(id, isTempAsset).then((url) => { assetUrl = url; diff --git a/unime/src/routes/credentials/[id]/CredentialHeader.svelte b/unime/src/routes/credentials/[id]/CredentialHeader.svelte index 52362d94..96f9ab41 100644 --- a/unime/src/routes/credentials/[id]/CredentialHeader.svelte +++ b/unime/src/routes/credentials/[id]/CredentialHeader.svelte @@ -4,7 +4,7 @@ import type { DisplayCredential } from '@bindings/credentials/DisplayCredential'; import { dispatch } from '$lib/dispatcher'; - import { CertificateLightIcon, HeartStraightFillIcon, HeartStraightRegularIcon } from '$lib/icons'; + import { CertificateLightIcon, HeartStraightFillIcon, HeartStraightRegularIcon, UserLightIcon } from '$lib/icons'; import { getImageAsset } from '$lib/utils'; import CredentialHeaderMenu from './CredentialHeaderMenu.svelte'; @@ -26,8 +26,10 @@ {#if credentialLogoUrl} Credential logo - {:else} + {:else if credential.data.type.includes('OpenBadgeCredential')} + {:else} + {/if}
From 304018041fcc6ad8168339334bd381aebf4af558 Mon Sep 17 00:00:00 2001 From: Daniel Mader Date: Thu, 31 Oct 2024 13:42:13 +0100 Subject: [PATCH 2/2] fix: use hash-based image identifier to prevent caching --- .../reducers/send_credential_request.rs | 121 ++++++++++-------- .../qr_code/reducers/read_credential_offer.rs | 8 +- .../prompt/credential-offer/+page.svelte | 4 +- 3 files changed, 70 insertions(+), 63 deletions(-) diff --git a/identity-wallet/src/state/credentials/reducers/send_credential_request.rs b/identity-wallet/src/state/credentials/reducers/send_credential_request.rs index e7261464..d8ec6b90 100644 --- a/identity-wallet/src/state/credentials/reducers/send_credential_request.rs +++ b/identity-wallet/src/state/credentials/reducers/send_credential_request.rs @@ -135,61 +135,71 @@ pub async fn send_credential_request(state: AppState, action: Action) -> Result< credential_configuration_ids.contains(credential_configuration_id) }); - let credentials: Vec<(String, serde_json::Value)> = match credential_configuration_ids.len() { - 0 => vec![], - 1 => { - let credential_configuration_id = credential_configuration_ids[0].clone(); - - let credential_configuration = credential_configurations_supported - .get(&credential_configuration_id) - .ok_or(UnknownCredentialConfigurationIdError( - credential_configuration_id.clone(), - ))?; - - // Get the credential. - let credential_response = wallet - .get_credential(credential_issuer_metadata, &token_response, credential_configuration) - .await - .map_err(GetCredentialError)?; - - let credential = match credential_response.credential { - CredentialResponseType::Immediate { credential, .. } => credential, - _ => panic!("Credential was not a jwt_vc_json."), - }; - - vec![(credential_configuration_id, credential)] - } - _batch => { - let (credential_configuration_ids, credential_configurations): (Vec<_>, Vec<_>) = - credential_configurations_supported.clone().into_iter().unzip(); - - let batch_credential_response = wallet - .get_batch_credential(credential_issuer_metadata, &token_response, &credential_configurations) - .await - .map_err(GetBatchCredentialError)?; - - credential_configuration_ids - .into_iter() - .zip(batch_credential_response.credential_responses.into_iter()) - .filter_map( - |(credential_configuration_id, credential_response)| match credential_response { - CredentialResponseType::Immediate { credential, .. } => { - Some((credential_configuration_id, credential)) - } - // TODO: add support for deffered credentials. - CredentialResponseType::Deferred { .. } => None, - }, - ) - .collect() - } - }; + let credentials: Vec<(String, serde_json::Value, Vec)> = + match credential_configuration_ids.len() { + 0 => vec![], + 1 => { + let credential_configuration_id = credential_configuration_ids[0].clone(); + + let credential_configuration = credential_configurations_supported + .get(&credential_configuration_id) + .ok_or(UnknownCredentialConfigurationIdError( + credential_configuration_id.clone(), + ))?; + + // Get the credential. + let credential_response = wallet + .get_credential(credential_issuer_metadata, &token_response, credential_configuration) + .await + .map_err(GetCredentialError)?; + + let credential = match credential_response.credential { + CredentialResponseType::Immediate { credential, .. } => credential, + _ => panic!("Credential was not a jwt_vc_json."), + }; + + vec![( + credential_configuration_id, + credential, + credential_configuration.display.clone(), + )] + } + _batch => { + let (credential_configuration_ids, credential_configurations): (Vec<_>, Vec<_>) = + credential_configurations_supported.clone().into_iter().unzip(); + + let batch_credential_response = wallet + .get_batch_credential(credential_issuer_metadata, &token_response, &credential_configurations) + .await + .map_err(GetBatchCredentialError)?; + + credential_configuration_ids + .into_iter() + .zip(batch_credential_response.credential_responses.into_iter()) + .zip(credential_configurations.into_iter()) + .filter_map( + |((credential_configuration_id, credential_response), credential_configuration)| { + match credential_response { + CredentialResponseType::Immediate { credential, .. } => Some(( + credential_configuration_id, + credential, + credential_configuration.display, + )), + // TODO: add support for deferred credentials. + CredentialResponseType::Deferred { .. } => None, + } + }, + ) + .collect() + } + }; info!("credentials: {:?}", credentials); let mut history_credentials = vec![]; - for (credential_configuration_id, credential) in credentials.into_iter() { - let mut verifiable_credential_record: VerifiableCredentialRecord = credential.try_into()?; + for (credential_configuration_id, credential, display) in credentials.into_iter() { + let mut verifiable_credential_record: VerifiableCredentialRecord = credential.clone().try_into()?; verifiable_credential_record .display_credential .issuer_name @@ -211,11 +221,12 @@ pub async fn send_credential_request(state: AppState, action: Action) -> Result< info!("generated hash-key: {:?}", key); - persist_asset( - format!("credential_{credential_configuration_id}").as_str(), - key.to_string().as_str(), - ) - .ok(); + display + .first() + .and_then(|display| display.get("logo")) + .and_then(|logo| logo.get("uri").or_else(|| logo.get("url"))) + .and_then(|uri| uri.as_str()) + .and_then(|uri| persist_asset(&hash(uri), key.to_string().as_str()).ok()); // Remove the old credential from the stronghold if it exists. stronghold_manager.remove(key).map_err(StrongholdDeletionError)?; diff --git a/identity-wallet/src/state/qr_code/reducers/read_credential_offer.rs b/identity-wallet/src/state/qr_code/reducers/read_credential_offer.rs index e15f1708..3c40813d 100644 --- a/identity-wallet/src/state/qr_code/reducers/read_credential_offer.rs +++ b/identity-wallet/src/state/qr_code/reducers/read_credential_offer.rs @@ -144,7 +144,7 @@ pub async fn read_credential_offer(state: AppState, action: Action) -> Result, ) { - for (credential_configuration_id, credential_configuration) in credential_configurations.iter() { + for (_, credential_configuration) in credential_configurations.iter() { let credential_logo_uri = credential_configuration .display .first() @@ -158,11 +158,7 @@ async fn download_credential_logos( format!("Downloading credential logo from URI: {}", credential_logo_uri) ); if let Ok(credential_logo_uri) = credential_logo_uri.parse::() { - let _ = download_asset( - credential_logo_uri, - format!("credential_{}", credential_configuration_id).as_str(), - ) - .await; + let _ = download_asset(credential_logo_uri.clone(), &hash(credential_logo_uri.as_str())).await; } else { debug!("Failed to parse credential logo URI: {}", credential_logo_uri); } diff --git a/unime/src/routes/prompt/credential-offer/+page.svelte b/unime/src/routes/prompt/credential-offer/+page.svelte index ffcfebbd..21552d70 100644 --- a/unime/src/routes/prompt/credential-offer/+page.svelte +++ b/unime/src/routes/prompt/credential-offer/+page.svelte @@ -67,10 +67,10 @@
- {#each Object.entries(credential_configurations) as [credential_configuration_id, credential_configuration]} + {#each Object.values(credential_configurations) as credential_configuration}