feat: implement generic <Avatar> component
This commit is contained in:
parent
f4ddcf9d8d
commit
f98e8c6110
5 changed files with 82 additions and 6 deletions
37
components/Avatar.vue
Normal file
37
components/Avatar.vue
Normal file
|
@ -0,0 +1,37 @@
|
|||
<template>
|
||||
<Icon v-if="canvasBlocked"
|
||||
name="lucide:user" />
|
||||
<NuxtImg v-else
|
||||
:src="displayAvatar"
|
||||
:alt="displayName" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { NuxtImg } from '#components';
|
||||
import type { GuildMemberResponse, UserResponse } from '~/types/interfaces';
|
||||
|
||||
const props = defineProps<{
|
||||
user?: UserResponse,
|
||||
member?: GuildMemberResponse,
|
||||
}>();
|
||||
|
||||
|
||||
let displayName: string
|
||||
let displayAvatar: string
|
||||
let canvasBlocked = false
|
||||
|
||||
const user = props.user || props.member?.user
|
||||
|
||||
if (user) {
|
||||
displayName = props.member?.nickname
|
||||
|| user.display_name
|
||||
|| user.username
|
||||
|
||||
if (user.avatar) {
|
||||
displayAvatar = user.avatar
|
||||
} else {
|
||||
displayAvatar = generateDefaultIcon(displayName, user.uuid)
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<NuxtLink class="user-item" :href="`/me/${user.uuid}`" tabindex="0">
|
||||
<img v-if="props.user.avatar" class="user-avatar" :src="props.user.avatar" :alt="props.user.display_name ?? props.user.username" />
|
||||
<Icon v-else class="user-avatar" name="lucide:user" />
|
||||
<span class="user-display-name">{{ props.user.display_name || props.user.username }}</span>
|
||||
<Avatar :user="props.user" class="user-avatar"/>
|
||||
|
||||
<span class="user-display-name">{{ displayName }}</span>
|
||||
</NuxtLink>
|
||||
</template>
|
||||
|
||||
|
@ -12,6 +12,8 @@ import type { UserResponse } from '~/types/interfaces';
|
|||
const props = defineProps<{
|
||||
user: UserResponse
|
||||
}>();
|
||||
|
||||
const displayName = props.user.display_name || props.user.username
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<template>
|
||||
<div id="profile-popup">
|
||||
<img v-if="props.user.avatar" id="avatar" :src="props.user.avatar" alt="profile avatar">
|
||||
<Icon v-else id="avatar" name="lucide:user" />
|
||||
<Avatar :user="props.user" id="avatar"/>
|
||||
|
||||
<div id="cover-color"></div>
|
||||
<div id="main-body">
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<div class="left-column-segment" id="left-column-middle">
|
||||
<NuxtLink v-for="guild of guilds" :href="`/servers/${guild.uuid}`">
|
||||
<NuxtImg v-if="guild.icon" class="sidebar-icon" :src="guild.icon" :alt="guild.name"/>
|
||||
<Icon v-else name="lucide:server" class="sidebar-icon white" :alt="guild.name" />
|
||||
<NuxtImg v-else class="sidebar-icon" :src="generateDefaultIcon(guild.name, guild.uuid)" :alt="guild.name"/>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
<VerticalSpacer />
|
||||
|
|
38
utils/generateDefaultIcon.ts
Normal file
38
utils/generateDefaultIcon.ts
Normal file
|
@ -0,0 +1,38 @@
|
|||
export default (name: string, seed: string): string => {
|
||||
const canvas = document.createElement("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
if (canvas && ctx) {
|
||||
canvas.width = 256;
|
||||
canvas.height = 256;
|
||||
|
||||
// get the first char from every word in the guild name
|
||||
let previewName = "";
|
||||
if (name.length > 3) {
|
||||
let guildName: string[] = name.split(' ')
|
||||
for (let i = 0; i < 3; i ++) {
|
||||
if (guildName.length > i) {
|
||||
previewName += guildName[i].charAt(0)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
previewName = name
|
||||
}
|
||||
|
||||
// fill background using seeded colour
|
||||
ctx.fillStyle = generateIrcColor(seed, 50)
|
||||
ctx.fillRect(0, 0, 256, 256)
|
||||
|
||||
ctx.fillStyle = 'white'
|
||||
ctx.textAlign = 'center'
|
||||
ctx.textBaseline = 'middle'
|
||||
ctx.font = 'bold 96px Arial, Helvetica, sans-serif'
|
||||
// 136 isn't actually centered, but it *looks* centered
|
||||
ctx.fillText(previewName, 128, 136)
|
||||
|
||||
return canvas.toDataURL("image/png");
|
||||
}
|
||||
|
||||
return "https://tenor.com/view/dame-da-ne-guy-kiryukazuma-kiryu-yakuza-yakuza-0-gif-14355451116903905918"
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue