Skip to content

Commit

Permalink
fix: use hash-based image identifier to prevent caching, use colored …
Browse files Browse the repository at this point in the history
…background for icon fallback (#396)

* fix: use colored background when icon fallback is displayed

* fix: use hash-based image identifier to prevent caching
  • Loading branch information
daniel-mader authored Oct 31, 2024
1 parent 2bfd1b6 commit fafc458
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<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,
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
Expand All @@ -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)?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ pub async fn read_credential_offer(state: AppState, action: Action) -> Result<Ap
async fn download_credential_logos(
credential_configurations: &HashMap<String, CredentialConfigurationsSupportedObject>,
) {
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()
Expand All @@ -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::<reqwest::Url>() {
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);
}
Expand Down
13 changes: 6 additions & 7 deletions unime/src/lib/components/ListItemCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
export let description: string | undefined = undefined;
export let type: 'data' | 'badge' = 'data';
export let isTempAsset = false;
let useFallback = false;
</script>

<!--
Expand Down Expand Up @@ -42,13 +44,10 @@ Can be used for credentials, connections, etc.
<!-- Image or icon -->
<slot name="image">
<!-- TODO: fix: should be `bg-white` only when Image is present, else `bg-silver dark:bg-navy` -->
<div class="mr-4 flex h-12 w-12 min-w-[48px] items-center justify-center overflow-hidden rounded-lg bg-white p-1">
<Image
{id}
iconFallback={type === 'data' ? 'User' : 'Certificate'}
{isTempAsset}
iconClass="dark:text-slate-800"
/>
<div
class={`mr-4 flex h-12 w-12 min-w-[48px] items-center justify-center overflow-hidden rounded-lg p-1 ${useFallback ? 'bg-silver dark:bg-navy' : 'bg-white'}`}
>
<Image {id} iconFallback={type === 'data' ? 'User' : 'Certificate'} {isTempAsset} bind:useFallback />
</div>
</slot>
<!-- Text -->
Expand Down
3 changes: 3 additions & 0 deletions unime/src/lib/components/image/Image.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 4 additions & 2 deletions unime/src/routes/credentials/[id]/CredentialHeader.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -26,8 +26,10 @@
{#if credentialLogoUrl}
<!-- Fit image of unknown dimensions into available space with `contain` (not `cover`). -->
<img src={credentialLogoUrl} alt="Credential logo" class="h-32 w-32 object-contain" />
{:else}
{:else if credential.data.type.includes('OpenBadgeCredential')}
<CertificateLightIcon class="h-10 w-10 text-text-alt" />
{:else}
<UserLightIcon class="h-10 w-10 text-text-alt" />
{/if}
</div>

Expand Down
4 changes: 2 additions & 2 deletions unime/src/routes/prompt/credential-offer/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@
<div
class="mt-3 w-full rounded-[20px] border border-slate-200 bg-white p-[10px] dark:border-slate-600 dark:bg-dark"
>
{#each Object.entries(credential_configurations) as [credential_configuration_id, credential_configuration]}
{#each Object.values(credential_configurations) as credential_configuration}
<!-- TODO: bug: long list is not correctly displayed -->
<ListItemCard
id={`credential_${credential_configuration_id}`}
id={hash(credential_configuration.display?.at(0)?.logo?.uri ?? '')}
title={credential_configuration.display?.at(0)?.name ??
credential_configuration.credential_definition.type.at(-1)}
isTempAsset={true}
Expand Down

0 comments on commit fafc458

Please sign in to comment.