mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-08-05 12:07:22 -04:00
54 lines
1.4 KiB
Vue
54 lines
1.4 KiB
Vue
<script setup lang="ts">
|
|
import { computedAsync } from '@vueuse/core';
|
|
|
|
import { fallbackAvatar, gravatar } from '~/src/helpers.ts';
|
|
import type { User } from '~/src/user.ts';
|
|
|
|
interface AvatarUser extends Pick<User, 'username' | 'emailHash'> {
|
|
email?: User['email'];
|
|
avatar?: string;
|
|
avatarSource?: User['avatarSource'];
|
|
}
|
|
|
|
const props = withDefaults(defineProps<{
|
|
user: AvatarUser;
|
|
src?: string;
|
|
size?: number;
|
|
dsize?: string;
|
|
validate?: boolean;
|
|
}>(), {
|
|
size: 128,
|
|
dsize: '6rem',
|
|
});
|
|
|
|
const failedToLoad = ref(false);
|
|
|
|
const resolvedSrc = computedAsync(async () => {
|
|
return props.src ||
|
|
props.user.avatar ||
|
|
(props.user.avatarSource === 'gravatar' && props.user.email !== undefined
|
|
? await gravatar(props.user as AvatarUser & Required<Pick<AvatarUser, 'email'>>, props.size)
|
|
: fallbackAvatar(props.user, props.size));
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<span>
|
|
<img
|
|
:src="resolvedSrc"
|
|
alt=""
|
|
class="rounded-circle"
|
|
:style="`width: ${dsize};height: ${dsize};`"
|
|
@error="failedToLoad = true"
|
|
>
|
|
<small v-if="validate && failedToLoad" class="failed-to-load small text-danger"><T>user.avatar.failed</T></small>
|
|
</span>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
.failed-to-load {
|
|
max-width: 200px;
|
|
display: inline-block;
|
|
}
|
|
</style>
|