fix avatar dialog layout

This commit is contained in:
pa
2026-01-20 18:20:08 +09:00
committed by Natsumi
parent b2bd7693bb
commit 6dfea34dd2

View File

@@ -1,323 +1,327 @@
<template>
<div>
<div style="display: flex">
<img
:src="avatarDialog.ref.thumbnailImageUrl"
class="cursor-pointer"
@click="showFullscreenImageDialog(avatarDialog.ref.imageUrl)"
style="flex: none; width: 160px; height: 120px; border-radius: 12px"
loading="lazy" />
<div style="flex: 1; display: flex; align-items: center; margin-left: 15px">
<div style="flex: 1">
<div>
<span
class="font-bold"
style="margin-right: 5px; cursor: pointer"
v-text="avatarDialog.ref.name"
@click="copyToClipboard(avatarDialog.ref.name)"></span>
</div>
<div style="margin-top: 5px">
<span
class="cursor-pointer x-grey"
style="font-family: monospace"
@click="showUserDialog(avatarDialog.ref.authorId)"
v-text="avatarDialog.ref.authorName"></span>
</div>
<div>
<Badge
v-if="avatarDialog.ref.releaseStatus === 'public'"
variant="outline"
style="margin-right: 5px; margin-top: 5px">
{{ t('dialog.avatar.tags.public') }}
</Badge>
<Badge v-else variant="outline" style="margin-right: 5px; margin-top: 5px">
{{ t('dialog.avatar.tags.private') }}
</Badge>
<TooltipWrapper v-if="avatarDialog.isPC" side="top" content="PC">
<Badge
class="x-tag-platform-pc"
variant="outline"
style="margin-right: 5px; margin-top: 5px"
><Monitor class="h-4 w-4 x-tag-platform-pc" />
<span
v-if="avatarDialog.platformInfo.pc"
:class="['x-grey', 'x-tag-platform-pc', 'x-tag-border-left']"
>{{ avatarDialog.platformInfo.pc.performanceRating }}</span
>
<span
v-if="avatarDialog.bundleSizes['standalonewindows']"
:class="['x-grey', 'x-tag-platform-pc', 'x-tag-border-left']"
>{{ avatarDialog.bundleSizes['standalonewindows'].fileSize }}</span
>
</Badge>
</TooltipWrapper>
<TooltipWrapper v-if="avatarDialog.isQuest" side="top" content="Android">
<Badge
class="x-tag-platform-quest"
variant="outline"
style="margin-right: 5px; margin-top: 5px"
><Smartphone class="h-4 w-4 x-tag-platform-quest" />
<span
v-if="avatarDialog.platformInfo.android"
:class="['x-grey', 'x-tag-platform-quest', 'x-tag-border-left']"
>{{ avatarDialog.platformInfo.android.performanceRating }}</span
>
<span
v-if="avatarDialog.bundleSizes['android']"
:class="['x-grey', 'x-tag-platform-quest', 'x-tag-border-left']"
>{{ avatarDialog.bundleSizes['android'].fileSize }}</span
>
</Badge>
</TooltipWrapper>
<TooltipWrapper v-if="avatarDialog.isIos" side="top" content="iOS">
<Badge
class="text-[#8e8e93] border-[#8e8e93]"
variant="outline"
style="margin-right: 5px; margin-top: 5px"
><Apple class="h-4 w-4 text-[#8e8e93]" />
<span
v-if="avatarDialog.platformInfo.ios"
:class="['x-grey', 'x-tag-border-left', 'text-[#8e8e93]', 'border-[#8e8e93]']"
>{{ avatarDialog.platformInfo.ios.performanceRating }}</span
>
<span
v-if="avatarDialog.bundleSizes['ios']"
:class="['x-grey', 'x-tag-border-left', 'text-[#8e8e93]', 'border-[#8e8e93]']"
>{{ avatarDialog.bundleSizes['ios'].fileSize }}</span
>
</Badge>
</TooltipWrapper>
<Badge
v-if="avatarDialog.inCache"
variant="outline"
class="cursor-pointer"
style="margin-right: 5px; margin-top: 5px"
@click="openFolderGeneric(avatarDialog.cachePath)">
<span v-text="avatarDialog.cacheSize"></span>
&nbsp;{{ t('dialog.avatar.tags.cache') }}
</Badge>
<Badge
v-if="avatarDialog.ref.styles?.primary || avatarDialog.ref.styles?.secondary"
variant="outline"
style="margin-right: 5px; margin-top: 5px"
>Styles
<span v-if="avatarDialog.ref.styles.primary" :class="['x-grey', 'x-tag-border-left']">{{
avatarDialog.ref.styles.primary
}}</span>
<span v-if="avatarDialog.ref.styles.secondary" :class="['x-grey', 'x-tag-border-left']">{{
avatarDialog.ref.styles.secondary
}}</span>
</Badge>
<Badge
v-if="avatarDialog.isQuestFallback"
variant="outline"
style="margin-right: 5px; margin-top: 5px">
{{ t('dialog.avatar.tags.fallback') }}
</Badge>
<Badge
v-if="avatarDialog.hasImposter"
variant="outline"
style="margin-right: 5px; margin-top: 5px"
>{{ t('dialog.avatar.tags.impostor') }}
<span v-if="avatarDialog.imposterVersion" :class="['x-grey', 'x-tag-border-left']"
>v{{ avatarDialog.imposterVersion }}</span
>
</Badge>
<Badge
v-if="avatarDialog.ref.unityPackageUrl"
variant="outline"
style="margin-right: 5px; margin-top: 5px">
{{ t('dialog.avatar.tags.future_proofing') }}
</Badge>
<div>
<div class="flex">
<img
:src="avatarDialog.ref.thumbnailImageUrl"
class="cursor-pointer"
@click="showFullscreenImageDialog(avatarDialog.ref.imageUrl)"
style="flex: none; width: 160px; height: 120px; border-radius: 12px"
loading="lazy" />
<div style="flex: 1; display: flex; align-items: center; margin-left: 15px">
<div style="flex: 1">
<div>
<template v-for="tag in avatarDialog.ref.tags" :key="tag">
<span
class="font-bold"
style="margin-right: 5px; cursor: pointer"
v-text="avatarDialog.ref.name"
@click="copyToClipboard(avatarDialog.ref.name)"></span>
</div>
<div style="margin-top: 5px">
<span
class="cursor-pointer x-grey"
style="font-family: monospace"
@click="showUserDialog(avatarDialog.ref.authorId)"
v-text="avatarDialog.ref.authorName"></span>
</div>
<div>
<Badge
v-if="avatarDialog.ref.releaseStatus === 'public'"
variant="outline"
style="margin-right: 5px; margin-top: 5px">
{{ t('dialog.avatar.tags.public') }}
</Badge>
<Badge v-else variant="outline" style="margin-right: 5px; margin-top: 5px">
{{ t('dialog.avatar.tags.private') }}
</Badge>
<TooltipWrapper v-if="avatarDialog.isPC" side="top" content="PC">
<Badge
v-if="tag.startsWith('content_')"
class="x-tag-platform-pc"
variant="outline"
style="margin-right: 5px; margin-top: 5px">
<span v-if="tag === 'content_horror'">{{
t('dialog.avatar.tags.content_horror')
}}</span>
<span v-else-if="tag === 'content_gore'">{{
t('dialog.avatar.tags.content_gore')
}}</span>
<span v-else-if="tag === 'content_violence'">{{
t('dialog.avatar.tags.content_violence')
}}</span>
<span v-else-if="tag === 'content_adult'">{{
t('dialog.avatar.tags.content_adult')
}}</span>
<span v-else-if="tag === 'content_sex'">{{
t('dialog.avatar.tags.content_sex')
}}</span>
<span v-else>{{ tag.replace('content_', '') }}</span>
style="margin-right: 5px; margin-top: 5px"
><Monitor class="h-4 w-4 x-tag-platform-pc" />
<span
v-if="avatarDialog.platformInfo.pc"
:class="['x-grey', 'x-tag-platform-pc', 'x-tag-border-left']"
>{{ avatarDialog.platformInfo.pc.performanceRating }}</span
>
<span
v-if="avatarDialog.bundleSizes['standalonewindows']"
:class="['x-grey', 'x-tag-platform-pc', 'x-tag-border-left']"
>{{ avatarDialog.bundleSizes['standalonewindows'].fileSize }}</span
>
</Badge>
</TooltipWrapper>
<TooltipWrapper v-if="avatarDialog.isQuest" side="top" content="Android">
<Badge
v-if="tag.startsWith('author_tag_')"
class="x-tag-platform-quest"
variant="outline"
style="margin-right: 5px; margin-top: 5px">
<span>
{{ tag.replace('author_tag_', '') }}
</span>
style="margin-right: 5px; margin-top: 5px"
><Smartphone class="h-4 w-4 x-tag-platform-quest" />
<span
v-if="avatarDialog.platformInfo.android"
:class="['x-grey', 'x-tag-platform-quest', 'x-tag-border-left']"
>{{ avatarDialog.platformInfo.android.performanceRating }}</span
>
<span
v-if="avatarDialog.bundleSizes['android']"
:class="['x-grey', 'x-tag-platform-quest', 'x-tag-border-left']"
>{{ avatarDialog.bundleSizes['android'].fileSize }}</span
>
</Badge>
</template>
</TooltipWrapper>
<TooltipWrapper v-if="avatarDialog.isIos" side="top" content="iOS">
<Badge
class="text-[#8e8e93] border-[#8e8e93]"
variant="outline"
style="margin-right: 5px; margin-top: 5px"
><Apple class="h-4 w-4 text-[#8e8e93]" />
<span
v-if="avatarDialog.platformInfo.ios"
:class="['x-grey', 'x-tag-border-left', 'text-[#8e8e93]', 'border-[#8e8e93]']"
>{{ avatarDialog.platformInfo.ios.performanceRating }}</span
>
<span
v-if="avatarDialog.bundleSizes['ios']"
:class="['x-grey', 'x-tag-border-left', 'text-[#8e8e93]', 'border-[#8e8e93]']"
>{{ avatarDialog.bundleSizes['ios'].fileSize }}</span
>
</Badge>
</TooltipWrapper>
<Badge
v-if="avatarDialog.inCache"
variant="outline"
class="cursor-pointer"
style="margin-right: 5px; margin-top: 5px"
@click="openFolderGeneric(avatarDialog.cachePath)">
<span v-text="avatarDialog.cacheSize"></span>
&nbsp;{{ t('dialog.avatar.tags.cache') }}
</Badge>
<Badge
v-if="avatarDialog.ref.styles?.primary || avatarDialog.ref.styles?.secondary"
variant="outline"
style="margin-right: 5px; margin-top: 5px"
>Styles
<span v-if="avatarDialog.ref.styles.primary" :class="['x-grey', 'x-tag-border-left']">{{
avatarDialog.ref.styles.primary
}}</span>
<span
v-if="avatarDialog.ref.styles.secondary"
:class="['x-grey', 'x-tag-border-left']"
>{{ avatarDialog.ref.styles.secondary }}</span
>
</Badge>
<Badge
v-if="avatarDialog.isQuestFallback"
variant="outline"
style="margin-right: 5px; margin-top: 5px">
{{ t('dialog.avatar.tags.fallback') }}
</Badge>
<Badge
v-if="avatarDialog.hasImposter"
variant="outline"
style="margin-right: 5px; margin-top: 5px"
>{{ t('dialog.avatar.tags.impostor') }}
<span v-if="avatarDialog.imposterVersion" :class="['x-grey', 'x-tag-border-left']"
>v{{ avatarDialog.imposterVersion }}</span
>
</Badge>
<Badge
v-if="avatarDialog.ref.unityPackageUrl"
variant="outline"
style="margin-right: 5px; margin-top: 5px">
{{ t('dialog.avatar.tags.future_proofing') }}
</Badge>
<div>
<template v-for="tag in avatarDialog.ref.tags" :key="tag">
<Badge
v-if="tag.startsWith('content_')"
variant="outline"
style="margin-right: 5px; margin-top: 5px">
<span v-if="tag === 'content_horror'">{{
t('dialog.avatar.tags.content_horror')
}}</span>
<span v-else-if="tag === 'content_gore'">{{
t('dialog.avatar.tags.content_gore')
}}</span>
<span v-else-if="tag === 'content_violence'">{{
t('dialog.avatar.tags.content_violence')
}}</span>
<span v-else-if="tag === 'content_adult'">{{
t('dialog.avatar.tags.content_adult')
}}</span>
<span v-else-if="tag === 'content_sex'">{{
t('dialog.avatar.tags.content_sex')
}}</span>
<span v-else>{{ tag.replace('content_', '') }}</span>
</Badge>
<Badge
v-if="tag.startsWith('author_tag_')"
variant="outline"
style="margin-right: 5px; margin-top: 5px">
<span>
{{ tag.replace('author_tag_', '') }}
</span>
</Badge>
</template>
</div>
</div>
<div style="margin-top: 5px">
<span
v-show="avatarDialog.ref.name !== avatarDialog.ref.description"
style="font-size: 12px"
v-text="avatarDialog.ref.description"></span>
</div>
</div>
<div style="margin-top: 5px">
<span
v-show="avatarDialog.ref.name !== avatarDialog.ref.description"
style="font-size: 12px"
v-text="avatarDialog.ref.description"></span>
</div>
</div>
<div class="flex items-center">
<TooltipWrapper
v-if="avatarDialog.inCache"
side="top"
:content="t('dialog.avatar.actions.delete_cache_tooltip')">
<Button
class="rounded-full mr-2"
size="icon-lg"
variant="outline"
:disabled="isGameRunning && avatarDialog.cacheLocked"
@click="deleteVRChatCache(avatarDialog.ref)"
><Trash2
/></Button>
</TooltipWrapper>
<div class="flex items-center">
<TooltipWrapper
v-if="avatarDialog.inCache"
side="top"
:content="t('dialog.avatar.actions.delete_cache_tooltip')">
<Button
class="rounded-full mr-2"
size="icon-lg"
variant="outline"
:disabled="isGameRunning && avatarDialog.cacheLocked"
@click="deleteVRChatCache(avatarDialog.ref)"
><Trash2
/></Button>
</TooltipWrapper>
<TooltipWrapper
v-if="avatarDialog.isFavorite"
side="top"
:ignore-non-keyboard-focus="true"
:content="t('dialog.avatar.actions.favorite_tooltip')">
<Button class="rounded-full" size="icon-lg" @click="avatarDialogCommand('Add Favorite')"
><Star
/></Button>
</TooltipWrapper>
<TooltipWrapper
v-else
side="top"
:ignore-non-keyboard-focus="true"
:content="t('dialog.avatar.actions.favorite_tooltip')">
<Button
class="rounded-full"
size="icon-lg"
variant="outline"
@click="avatarDialogCommand('Add Favorite')"
><Star
/></Button>
</TooltipWrapper>
<TooltipWrapper
v-if="avatarDialog.isFavorite"
side="top"
:ignore-non-keyboard-focus="true"
:content="t('dialog.avatar.actions.favorite_tooltip')">
<Button class="rounded-full" size="icon-lg" @click="avatarDialogCommand('Add Favorite')"
><Star
/></Button>
</TooltipWrapper>
<TooltipWrapper
v-else
side="top"
:ignore-non-keyboard-focus="true"
:content="t('dialog.avatar.actions.favorite_tooltip')">
<Button
class="rounded-full"
size="icon-lg"
variant="outline"
@click="avatarDialogCommand('Add Favorite')"
><Star
/></Button>
</TooltipWrapper>
<TooltipWrapper side="top" :content="t('dialog.avatar.actions.select')">
<Button
class="rounded-full ml-2"
size="icon-lg"
variant="outline"
:disabled="currentUser.currentAvatar === avatarDialog.id"
@click="selectAvatarWithoutConfirmation(avatarDialog.id)">
<CheckCircle
/></Button>
</TooltipWrapper>
<DropdownMenu>
<DropdownMenuTrigger as-child>
<TooltipWrapper side="top" :content="t('dialog.avatar.actions.select')">
<Button
class="rounded-full ml-2"
:variant="avatarDialog.isBlocked ? 'destructive' : 'outline'"
size="icon-lg">
<Ellipsis />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem @click="avatarDialogCommand('RefreshCw')">
<RefreshCw class="size-4" />
{{ t('dialog.avatar.actions.refresh') }}
</DropdownMenuItem>
<DropdownMenuItem @click="avatarDialogCommand('Share2')">
<Share2 class="size-4" />
{{ t('dialog.avatar.actions.share') }}
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
v-if="avatarDialog.isBlocked"
variant="destructive"
@click="avatarDialogCommand('Unblock Avatar')">
<CheckCircle class="size-4" />
{{ t('dialog.avatar.actions.unblock') }}
</DropdownMenuItem>
<DropdownMenuItem v-else @click="avatarDialogCommand('Block Avatar')">
<XCircle class="size-4" />
{{ t('dialog.avatar.actions.block') }}
</DropdownMenuItem>
<DropdownMenuItem
v-if="/quest/.test(avatarDialog.ref.tags)"
@click="avatarDialogCommand('Select Fallback Avatar')">
<Check class="size-4" />
{{ t('dialog.avatar.actions.select_fallback') }}
</DropdownMenuItem>
<template v-if="avatarDialog.ref.authorId === currentUser.id">
<DropdownMenuSeparator />
<DropdownMenuItem
v-if="avatarDialog.ref.releaseStatus === 'public'"
@click="avatarDialogCommand('Make Private')">
<User class="size-4" />
{{ t('dialog.avatar.actions.make_private') }}
</DropdownMenuItem>
<DropdownMenuItem v-else @click="avatarDialogCommand('Make Public')">
<User class="size-4" />
{{ t('dialog.avatar.actions.make_public') }}
</DropdownMenuItem>
<DropdownMenuItem @click="avatarDialogCommand('Rename')">
<Pencil class="size-4" />
{{ t('dialog.avatar.actions.rename') }}
</DropdownMenuItem>
<DropdownMenuItem @click="avatarDialogCommand('Change Description')">
<Pencil class="size-4" />
{{ t('dialog.avatar.actions.change_description') }}
</DropdownMenuItem>
<DropdownMenuItem @click="avatarDialogCommand('Change Content Tags')">
<Pencil class="size-4" />
{{ t('dialog.avatar.actions.change_content_tags') }}
</DropdownMenuItem>
<DropdownMenuItem @click="avatarDialogCommand('Change Styles and Author Tags')">
<Pencil class="size-4" />
{{ t('dialog.avatar.actions.change_styles_author_tags') }}
</DropdownMenuItem>
<DropdownMenuItem @click="avatarDialogCommand('Change Image')">
<Image class="size-4" />
{{ t('dialog.avatar.actions.change_image') }}
</DropdownMenuItem>
<DropdownMenuItem
v-if="avatarDialog.ref.unityPackageUrl"
@click="avatarDialogCommand('Download Unity Package')">
<Download class="size-4" />
{{ t('dialog.avatar.actions.download_package') }}
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
v-if="avatarDialog.hasImposter"
variant="destructive"
@click="avatarDialogCommand('Regenerate Imposter')">
size="icon-lg"
variant="outline"
:disabled="currentUser.currentAvatar === avatarDialog.id"
@click="selectAvatarWithoutConfirmation(avatarDialog.id)">
<CheckCircle
/></Button>
</TooltipWrapper>
<DropdownMenu>
<DropdownMenuTrigger as-child>
<Button
class="rounded-full ml-2"
:variant="avatarDialog.isBlocked ? 'destructive' : 'outline'"
size="icon-lg">
<Ellipsis />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem @click="avatarDialogCommand('RefreshCw')">
<RefreshCw class="size-4" />
{{ t('dialog.avatar.actions.regenerate_impostor') }}
{{ t('dialog.avatar.actions.refresh') }}
</DropdownMenuItem>
<DropdownMenuItem @click="avatarDialogCommand('Share2')">
<Share2 class="size-4" />
{{ t('dialog.avatar.actions.share') }}
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
v-if="avatarDialog.isBlocked"
variant="destructive"
@click="avatarDialogCommand('Unblock Avatar')">
<CheckCircle class="size-4" />
{{ t('dialog.avatar.actions.unblock') }}
</DropdownMenuItem>
<DropdownMenuItem v-else @click="avatarDialogCommand('Block Avatar')">
<XCircle class="size-4" />
{{ t('dialog.avatar.actions.block') }}
</DropdownMenuItem>
<DropdownMenuItem
v-if="avatarDialog.hasImposter"
variant="destructive"
@click="avatarDialogCommand('Trash2 Imposter')">
<Trash2 class="size-4" />
{{ t('dialog.avatar.actions.delete_impostor') }}
v-if="/quest/.test(avatarDialog.ref.tags)"
@click="avatarDialogCommand('Select Fallback Avatar')">
<Check class="size-4" />
{{ t('dialog.avatar.actions.select_fallback') }}
</DropdownMenuItem>
<DropdownMenuItem v-else @click="avatarDialogCommand('Create Imposter')">
<User class="size-4" />
{{ t('dialog.avatar.actions.create_impostor') }}
</DropdownMenuItem>
<DropdownMenuItem variant="destructive" @click="avatarDialogCommand('Trash2')">
<Trash2 class="size-4" />
{{ t('dialog.avatar.actions.delete') }}
</DropdownMenuItem>
</template>
</DropdownMenuContent>
</DropdownMenu>
<template v-if="avatarDialog.ref.authorId === currentUser.id">
<DropdownMenuSeparator />
<DropdownMenuItem
v-if="avatarDialog.ref.releaseStatus === 'public'"
@click="avatarDialogCommand('Make Private')">
<User class="size-4" />
{{ t('dialog.avatar.actions.make_private') }}
</DropdownMenuItem>
<DropdownMenuItem v-else @click="avatarDialogCommand('Make Public')">
<User class="size-4" />
{{ t('dialog.avatar.actions.make_public') }}
</DropdownMenuItem>
<DropdownMenuItem @click="avatarDialogCommand('Rename')">
<Pencil class="size-4" />
{{ t('dialog.avatar.actions.rename') }}
</DropdownMenuItem>
<DropdownMenuItem @click="avatarDialogCommand('Change Description')">
<Pencil class="size-4" />
{{ t('dialog.avatar.actions.change_description') }}
</DropdownMenuItem>
<DropdownMenuItem @click="avatarDialogCommand('Change Content Tags')">
<Pencil class="size-4" />
{{ t('dialog.avatar.actions.change_content_tags') }}
</DropdownMenuItem>
<DropdownMenuItem @click="avatarDialogCommand('Change Styles and Author Tags')">
<Pencil class="size-4" />
{{ t('dialog.avatar.actions.change_styles_author_tags') }}
</DropdownMenuItem>
<DropdownMenuItem @click="avatarDialogCommand('Change Image')">
<Image class="size-4" />
{{ t('dialog.avatar.actions.change_image') }}
</DropdownMenuItem>
<DropdownMenuItem
v-if="avatarDialog.ref.unityPackageUrl"
@click="avatarDialogCommand('Download Unity Package')">
<Download class="size-4" />
{{ t('dialog.avatar.actions.download_package') }}
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
v-if="avatarDialog.hasImposter"
variant="destructive"
@click="avatarDialogCommand('Regenerate Imposter')">
<RefreshCw class="size-4" />
{{ t('dialog.avatar.actions.regenerate_impostor') }}
</DropdownMenuItem>
<DropdownMenuItem
v-if="avatarDialog.hasImposter"
variant="destructive"
@click="avatarDialogCommand('Trash2 Imposter')">
<Trash2 class="size-4" />
{{ t('dialog.avatar.actions.delete_impostor') }}
</DropdownMenuItem>
<DropdownMenuItem v-else @click="avatarDialogCommand('Create Imposter')">
<User class="size-4" />
{{ t('dialog.avatar.actions.create_impostor') }}
</DropdownMenuItem>
<DropdownMenuItem variant="destructive" @click="avatarDialogCommand('Trash2')">
<Trash2 class="size-4" />
{{ t('dialog.avatar.actions.delete') }}
</DropdownMenuItem>
</template>
</DropdownMenuContent>
</DropdownMenu>
</div>
</div>
</div>