add image fallback

This commit is contained in:
pa
2026-02-26 20:32:49 +09:00
committed by Natsumi
parent 69cd330257
commit 1f253fafaf
3 changed files with 45 additions and 25 deletions
+8 -1
View File
@@ -4,13 +4,20 @@
v-if="image.frames" v-if="image.frames"
class="avatar" class="avatar"
:style="generateEmojiStyle(imageUrl, image.framesOverTime, image.frames, image.loopStyle, size)"></div> :style="generateEmojiStyle(imageUrl, image.framesOverTime, image.frames, image.loopStyle, size)"></div>
<img v-else :src="imageUrl" class="avatar" :style="{ width: size + 'px', height: size + 'px' }" /> <Avatar v-else class="rounded" :style="{ width: size + 'px', height: size + 'px' }">
<AvatarImage :src="imageUrl" class="object-cover" />
<AvatarFallback class="rounded">
<ImageOff class="size-4 text-muted-foreground" />
</AvatarFallback>
</Avatar>
</div> </div>
</template> </template>
<script setup> <script setup>
import { onMounted, ref, watch } from 'vue'; import { onMounted, ref, watch } from 'vue';
import { ImageOff } from 'lucide-vue-next';
import { Avatar, AvatarFallback, AvatarImage } from './ui/avatar';
import { extractFileId, generateEmojiStyle } from '../shared/utils'; import { extractFileId, generateEmojiStyle } from '../shared/utils';
import { useGalleryStore } from '../stores'; import { useGalleryStore } from '../stores';
+28 -11
View File
@@ -1,4 +1,9 @@
import Location from '../../components/Location.vue'; import Location from '../../components/Location.vue';
import {
Avatar,
AvatarFallback,
AvatarImage
} from '../../components/ui/avatar';
import { Badge } from '../../components/ui/badge'; import { Badge } from '../../components/ui/badge';
import { Button } from '../../components/ui/button'; import { Button } from '../../components/ui/button';
import { import {
@@ -12,6 +17,7 @@ import {
Ban, Ban,
BellOff, BellOff,
Check, Check,
ImageOff,
Link, Link,
MessageCircle, MessageCircle,
Reply, Reply,
@@ -403,32 +409,43 @@ export const createColumns = ({
} }
if (original.details?.imageUrl) { if (original.details?.imageUrl) {
return ( const detailsUrl = getSmallThumbnailUrl(
<img
class="cursor-pointer h-7.5 w-7.5 rounded object-cover"
src={getSmallThumbnailUrl(
original.details.imageUrl original.details.imageUrl
)} );
return (
<Avatar
class="cursor-pointer size-7.5 rounded"
onClick={() => onClick={() =>
showFullscreenImageDialog( showFullscreenImageDialog(
original.details.imageUrl original.details.imageUrl
) )
} }
loading="lazy" >
<AvatarImage
src={detailsUrl}
class="object-cover"
/> />
<AvatarFallback class="rounded">
<ImageOff class="size-4 text-muted-foreground" />
</AvatarFallback>
</Avatar>
); );
} }
if (original.imageUrl) { if (original.imageUrl) {
const imgUrl = getSmallThumbnailUrl(original.imageUrl);
return ( return (
<img <Avatar
class="cursor-pointer h-7.5 w-7.5 rounded object-cover" class="cursor-pointer size-7.5 rounded"
src={getSmallThumbnailUrl(original.imageUrl)}
onClick={() => onClick={() =>
showFullscreenImageDialog(original.imageUrl) showFullscreenImageDialog(original.imageUrl)
} }
loading="lazy" >
/> <AvatarImage src={imgUrl} class="object-cover" />
<AvatarFallback class="rounded">
<ImageOff class="size-4 text-muted-foreground" />
</AvatarFallback>
</Avatar>
); );
} }
+8 -12
View File
@@ -4,7 +4,12 @@
<div <div
class="avatar" class="avatar"
:class="isFriendActiveOrOffline ? undefined : userStatusClass(friend.ref, friend.pendingOffline)"> :class="isFriendActiveOrOffline ? undefined : userStatusClass(friend.ref, friend.pendingOffline)">
<img :src="userImage(friend.ref, true)" loading="lazy" /> <Avatar class="size-full rounded-full">
<AvatarImage :src="userImage(friend.ref, true)" class="object-cover" />
<AvatarFallback>
<User class="size-5 text-muted-foreground" />
</AvatarFallback>
</Avatar>
</div> </div>
<div class="detail h-9 flex flex-col justify-between"> <div class="detail h-9 flex flex-col justify-between">
<span v-if="!hideNicknames && friend.$nickName" class="name" :style="{ color: friend.ref.$userColour }"> <span v-if="!hideNicknames && friend.$nickName" class="name" :style="{ color: friend.ref.$userColour }">
@@ -48,23 +53,14 @@
><Trash2 class="h-4 w-4" /> ><Trash2 class="h-4 w-4" />
</Button> </Button>
</template> </template>
<!-- <div v-else class="skeleton" aria-busy="true" aria-label="Loading">
<div>
<Skeleton class="h-10 w-10 rounded-full" />
<div>
<Skeleton class="h-3.5 w-1/2" />
<Skeleton class="mt-1.5 h-3 w-full" />
</div>
</div>
</div> -->
</div> </div>
</template> </template>
<script setup> <script setup>
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Trash2, User } from 'lucide-vue-next';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Spinner } from '@/components/ui/spinner'; import { Spinner } from '@/components/ui/spinner';
import { Trash2 } from 'lucide-vue-next';
import { computed } from 'vue'; import { computed } from 'vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';