Optimized avatars and added avatar auto-fixer when cache is old.

This commit is contained in:
zenodeapp 2023-12-01 14:26:49 +01:00
parent aa17be0839
commit 727979bf20
2 changed files with 93 additions and 47 deletions

View File

@ -79,6 +79,7 @@ const selfRate = computed(() => {
} }
return '-'; return '-';
}); });
const logo = (identity?: string) => { const logo = (identity?: string) => {
if (!identity) return ''; if (!identity) return '';
const url = avatars.value[identity] || ''; const url = avatars.value[identity] || '';
@ -86,25 +87,43 @@ const logo = (identity?: string) => {
? url ? url
: `https://s3.amazonaws.com/keybase_processed_uploads/${url}`; : `https://s3.amazonaws.com/keybase_processed_uploads/${url}`;
}; };
onMounted(() => {
if (validator) { const fetchAvatar = (identity: string) => {
staking.fetchValidator(validator).then((res) => { // fetch avatar from keybase
v.value = res.validator; return new Promise<void>((resolve) => {
identity.value = res.validator?.description?.identity || ''; staking
if (identity.value && !avatars.value[identity.value]) { .keybase(identity)
staking.keybase(identity.value).then((d) => { .then((d) => {
if (Array.isArray(d.them) && d.them.length > 0) { if (Array.isArray(d.them) && d.them.length > 0) {
const uri = String(d.them[0]?.pictures?.primary?.url).replace( const uri = String(d.them[0]?.pictures?.primary?.url).replace(
'https://s3.amazonaws.com/keybase_processed_uploads/', 'https://s3.amazonaws.com/keybase_processed_uploads/',
'' ''
); );
if (uri) {
avatars.value[identity.value] = uri; avatars.value[identity] = uri;
localStorage.setItem('avatars', JSON.stringify(avatars.value)); resolve();
} } else throw new Error(`failed to fetch avatar for ${identity}.`);
} })
.catch((error) => {
// console.error(error); // uncomment this if you want the user to see if the avatar failed to load.
resolve();
}); });
} });
};
const loadAvatar = () => {
fetchAvatar(identity.value).then(() => {
localStorage.setItem('avatars', JSON.stringify(avatars.value));
});
};
onMounted(() => {
if (validator) {
staking.fetchValidator(validator).then((res) => {
v.value = res.validator;
identity.value = res.validator?.description?.identity || '';
if (identity.value && !avatars.value[identity.value]) loadAvatar();
const prefix = valoperToPrefix(v.value.operator_address) || '<Invalid>'; const prefix = valoperToPrefix(v.value.operator_address) || '<Invalid>';
addresses.value.hex = consensusPubkeyToHexAddress( addresses.value.hex = consensusPubkeyToHexAddress(
v.value.consensus_pubkey v.value.consensus_pubkey
@ -187,6 +206,13 @@ function pageload(p: number) {
v-if="avatars[identity] !== 'undefined'" v-if="avatars[identity] !== 'undefined'"
v-lazy="logo(identity)" v-lazy="logo(identity)"
class="object-contain" class="object-contain"
@error="
(e) => {
if (identity) {
loadAvatar();
}
}
"
/> />
<Icon <Icon
v-else v-else

View File

@ -141,39 +141,54 @@ const list = computed(() => {
return unbondList.value.map((x, i) => ({v: x, rank: 'primary', logo: logo(x.description.identity)})); return unbondList.value.map((x, i) => ({v: x, rank: 'primary', logo: logo(x.description.identity)}));
}); });
const loadAvatars = () => { const fetchAvatar = (identity: string) => {
// fetch avatar from keybase // fetch avatar from keybase
let promise = Promise.resolve(); return new Promise<void>((resolve) => {
staking.validators.forEach((item) => { staking
promise = promise.then( .keybase(identity)
() => .then((d) => {
new Promise((resolve) => {
const identity = item.description?.identity;
if (identity && !avatars.value[identity]) {
staking.keybase(identity).then((d) => {
if (Array.isArray(d.them) && d.them.length > 0) { if (Array.isArray(d.them) && d.them.length > 0) {
const uri = String( const uri = String(d.them[0]?.pictures?.primary?.url).replace(
d.them[0]?.pictures?.primary?.url
).replace(
'https://s3.amazonaws.com/keybase_processed_uploads/', 'https://s3.amazonaws.com/keybase_processed_uploads/',
'' ''
); );
if (uri) {
avatars.value[identity] = uri; avatars.value[identity] = uri;
localStorage.setItem(
'avatars',
JSON.stringify(avatars.value)
);
}
}
resolve(); resolve();
}); } else throw new Error(`failed to fetch avatar for ${identity}`);
} else {
resolve();
}
}) })
); .catch((error) => {
// console.error(error); // uncomment this if you want the user to see which avatars failed to load.
resolve();
}); });
});
};
const loadAvatar = (validator: Validator) => {
const identity = validator.description?.identity;
if (identity) {
fetchAvatar(identity).then(() => {
localStorage.setItem('avatars', JSON.stringify(avatars.value));
});
}
};
const loadAvatars = () => {
const promises = staking.validators.map((validator) => {
const identity = validator.description?.identity;
// Here we also check whether we haven't already fetched the avatar
if (identity && !avatars.value[identity]) {
return fetchAvatar(identity);
} else {
return Promise.resolve();
}
});
Promise.all(promises).then(() =>
localStorage.setItem('avatars', JSON.stringify(avatars.value))
);
}; };
const logo = (identity?: string) => { const logo = (identity?: string) => {
@ -313,7 +328,7 @@ loadAvatars();
style="max-width: 300px" style="max-width: 300px"
> >
<div <div
class="avatar mr-4 relative w-8 h-8 rounded-full overflow-hidden" class="avatar mr-4 relative w-8 h-8 rounded-full"
> >
<div <div
class="w-8 h-8 rounded-full bg-gray-400 absolute opacity-10" class="w-8 h-8 rounded-full bg-gray-400 absolute opacity-10"
@ -323,6 +338,11 @@ loadAvatars();
v-if="logo" v-if="logo"
:src="logo" :src="logo"
class="object-contain" class="object-contain"
@error="
(e) => {
loadAvatar(v);
}
"
/> />
<Icon <Icon
v-else v-else