Update home.vue

This commit is contained in:
syuilo 2025-05-03 14:30:33 +09:00
parent 77d4acfd32
commit c192d0512e
1 changed files with 138 additions and 131 deletions

View File

@ -4,158 +4,160 @@ SPDX-License-Identifier: AGPL-3.0-only
--> -->
<template> <template>
<div class="_spacer" :style="{ '--MI_SPACER-w': narrow ? '800px' : '1100px' }"> <component :is="prefer.s.enablePullToRefresh ? MkPullToRefresh : 'div'" :refresher="() => reload()">
<div ref="rootEl" class="ftskorzw" :class="{ wide: !narrow }" style="container-type: inline-size;"> <div class="_spacer" :style="{ '--MI_SPACER-w': narrow ? '800px' : '1100px' }">
<div class="main _gaps"> <div ref="rootEl" class="ftskorzw" :class="{ wide: !narrow }" style="container-type: inline-size;">
<!-- TODO --> <div class="main _gaps">
<!-- <div class="punished" v-if="user.isSuspended"><i class="ti ti-alert-triangle" style="margin-right: 8px;"></i> {{ i18n.ts.userSuspended }}</div> --> <!-- TODO -->
<!-- <div class="punished" v-if="user.isSilenced"><i class="ti ti-alert-triangle" style="margin-right: 8px;"></i> {{ i18n.ts.userSilenced }}</div> --> <!-- <div class="punished" v-if="user.isSuspended"><i class="ti ti-alert-triangle" style="margin-right: 8px;"></i> {{ i18n.ts.userSuspended }}</div> -->
<!-- <div class="punished" v-if="user.isSilenced"><i class="ti ti-alert-triangle" style="margin-right: 8px;"></i> {{ i18n.ts.userSilenced }}</div> -->
<div class="profile _gaps"> <div class="profile _gaps">
<MkAccountMoved v-if="user.movedTo" :movedTo="user.movedTo"/> <MkAccountMoved v-if="user.movedTo" :movedTo="user.movedTo"/>
<MkRemoteCaution v-if="user.host != null" :href="user.url ?? user.uri!"/> <MkRemoteCaution v-if="user.host != null" :href="user.url ?? user.uri!"/>
<MkInfo v-if="user.host == null && user.username.includes('.')">{{ i18n.ts.isSystemAccount }}</MkInfo> <MkInfo v-if="user.host == null && user.username.includes('.')">{{ i18n.ts.isSystemAccount }}</MkInfo>
<div :key="user.id" class="main _panel"> <div :key="user.id" class="main _panel">
<div class="banner-container" :style="style"> <div class="banner-container" :style="style">
<div ref="bannerEl" class="banner" :style="style"></div> <div ref="bannerEl" class="banner" :style="style"></div>
<div class="fade"></div> <div class="fade"></div>
<div class="title">
<MkUserName class="name" :user="user" :nowrap="true"/>
<div class="bottom">
<span class="username"><MkAcct :user="user" :detail="true"/></span>
<span v-if="user.isAdmin" :title="i18n.ts.isAdmin" style="color: var(--MI_THEME-badge);"><i class="ti ti-shield"></i></span>
<span v-if="user.isLocked" :title="i18n.ts.isLocked"><i class="ti ti-lock"></i></span>
<span v-if="user.isBot" :title="i18n.ts.isBot"><i class="ti ti-robot"></i></span>
<button v-if="$i && !isEditingMemo && !memoDraft" class="_button add-note-button" @click="showMemoTextarea">
<i class="ti ti-edit"/> {{ i18n.ts.addMemo }}
</button>
</div>
</div>
<span v-if="$i && $i.id != user.id && user.isFollowed" class="followed">{{ i18n.ts.followsYou }}</span>
<div class="actions">
<button class="menu _button" @click="menu"><i class="ti ti-dots"></i></button>
<MkFollowButton v-if="$i?.id != user.id" v-model:user="user" :inline="true" :transparent="false" :full="true" class="koudoku"/>
</div>
</div>
<MkAvatar class="avatar" :user="user" indicator/>
<div class="title"> <div class="title">
<MkUserName class="name" :user="user" :nowrap="true"/> <MkUserName :user="user" :nowrap="false" class="name"/>
<div class="bottom"> <div class="bottom">
<span class="username"><MkAcct :user="user" :detail="true"/></span> <span class="username"><MkAcct :user="user" :detail="true"/></span>
<span v-if="user.isAdmin" :title="i18n.ts.isAdmin" style="color: var(--MI_THEME-badge);"><i class="ti ti-shield"></i></span> <span v-if="user.isAdmin" :title="i18n.ts.isAdmin" style="color: var(--MI_THEME-badge);"><i class="ti ti-shield"></i></span>
<span v-if="user.isLocked" :title="i18n.ts.isLocked"><i class="ti ti-lock"></i></span> <span v-if="user.isLocked" :title="i18n.ts.isLocked"><i class="ti ti-lock"></i></span>
<span v-if="user.isBot" :title="i18n.ts.isBot"><i class="ti ti-robot"></i></span> <span v-if="user.isBot" :title="i18n.ts.isBot"><i class="ti ti-robot"></i></span>
<button v-if="$i && !isEditingMemo && !memoDraft" class="_button add-note-button" @click="showMemoTextarea">
<i class="ti ti-edit"/> {{ i18n.ts.addMemo }}
</button>
</div> </div>
</div> </div>
<span v-if="$i && $i.id != user.id && user.isFollowed" class="followed">{{ i18n.ts.followsYou }}</span> <div v-if="user.followedMessage != null" class="followedMessage">
<div class="actions"> <MkFukidashi class="fukidashi" :tail="narrow ? 'none' : 'left'" negativeMargin>
<button class="menu _button" @click="menu"><i class="ti ti-dots"></i></button> <div class="messageHeader">{{ i18n.ts.messageToFollower }}</div>
<MkFollowButton v-if="$i?.id != user.id" v-model:user="user" :inline="true" :transparent="false" :full="true" class="koudoku"/> <div><MkSparkle><Mfm :plain="true" :text="user.followedMessage" :author="user" class="_selectable"/></MkSparkle></div>
</MkFukidashi>
</div> </div>
</div> <div v-if="user.roles.length > 0" class="roles">
<MkAvatar class="avatar" :user="user" indicator/> <span v-for="role in user.roles" :key="role.id" v-tooltip="role.description" class="role" :style="{ '--color': role.color }">
<div class="title"> <MkA v-adaptive-bg :to="`/roles/${role.id}`">
<MkUserName :user="user" :nowrap="false" class="name"/> <img v-if="role.iconUrl" style="height: 1.3em; vertical-align: -22%;" :src="role.iconUrl"/>
<div class="bottom"> {{ role.name }}
<span class="username"><MkAcct :user="user" :detail="true"/></span> </MkA>
<span v-if="user.isAdmin" :title="i18n.ts.isAdmin" style="color: var(--MI_THEME-badge);"><i class="ti ti-shield"></i></span> </span>
<span v-if="user.isLocked" :title="i18n.ts.isLocked"><i class="ti ti-lock"></i></span>
<span v-if="user.isBot" :title="i18n.ts.isBot"><i class="ti ti-robot"></i></span>
</div> </div>
</div> <div v-if="iAmModerator" class="moderationNote">
<div v-if="user.followedMessage != null" class="followedMessage"> <MkTextarea v-if="editModerationNote || (moderationNote != null && moderationNote !== '')" v-model="moderationNote" manualSave>
<MkFukidashi class="fukidashi" :tail="narrow ? 'none' : 'left'" negativeMargin> <template #label>{{ i18n.ts.moderationNote }}</template>
<div class="messageHeader">{{ i18n.ts.messageToFollower }}</div> <template #caption>{{ i18n.ts.moderationNoteDescription }}</template>
<div><MkSparkle><Mfm :plain="true" :text="user.followedMessage" :author="user" class="_selectable"/></MkSparkle></div> </MkTextarea>
</MkFukidashi> <div v-else>
</div> <MkButton small @click="editModerationNote = true">{{ i18n.ts.addModerationNote }}</MkButton>
<div v-if="user.roles.length > 0" class="roles"> </div>
<span v-for="role in user.roles" :key="role.id" v-tooltip="role.description" class="role" :style="{ '--color': role.color }"> </div>
<MkA v-adaptive-bg :to="`/roles/${role.id}`"> <div v-if="isEditingMemo || memoDraft" class="memo" :class="{'no-memo': !memoDraft}">
<img v-if="role.iconUrl" style="height: 1.3em; vertical-align: -22%;" :src="role.iconUrl"/> <div class="heading" v-text="i18n.ts.memo"/>
{{ role.name }} <textarea
ref="memoTextareaEl"
v-model="memoDraft"
rows="1"
@focus="isEditingMemo = true"
@blur="updateMemo"
@input="adjustMemoTextarea"
/>
</div>
<div class="description">
<MkOmit>
<Mfm v-if="user.description" :text="user.description" :isNote="false" :author="user" class="_selectable"/>
<p v-else class="empty">{{ i18n.ts.noAccountDescription }}</p>
</MkOmit>
</div>
<div class="fields system">
<dl v-if="user.location" class="field">
<dt class="name"><i class="ti ti-map-pin ti-fw"></i> {{ i18n.ts.location }}</dt>
<dd class="value">{{ user.location }}</dd>
</dl>
<dl v-if="user.birthday" class="field">
<dt class="name"><i class="ti ti-cake ti-fw"></i> {{ i18n.ts.birthday }}</dt>
<dd class="value">{{ user.birthday.replace('-', '/').replace('-', '/') }} ({{ i18n.tsx.yearsOld({ age }) }})</dd>
</dl>
<dl class="field">
<dt class="name"><i class="ti ti-calendar ti-fw"></i> {{ i18n.ts.registeredDate }}</dt>
<dd class="value">{{ dateString(user.createdAt) }} (<MkTime :time="user.createdAt"/>)</dd>
</dl>
</div>
<div v-if="user.fields.length > 0" class="fields">
<dl v-for="(field, i) in user.fields" :key="i" class="field">
<dt class="name">
<Mfm :text="field.name" :author="user" :plain="true" :colored="false" class="_selectable"/>
</dt>
<dd class="value">
<Mfm :text="field.value" :author="user" :colored="false" class="_selectable"/>
<i v-if="user.verifiedLinks.includes(field.value)" v-tooltip:dialog="i18n.ts.verifiedLink" class="ti ti-circle-check" :class="$style.verifiedLink"></i>
</dd>
</dl>
</div>
<div class="status">
<MkA :to="userPage(user)">
<b>{{ number(user.notesCount) }}</b>
<span>{{ i18n.ts.notes }}</span>
</MkA>
<MkA v-if="isFollowingVisibleForMe(user)" :to="userPage(user, 'following')">
<b>{{ number(user.followingCount) }}</b>
<span>{{ i18n.ts.following }}</span>
</MkA>
<MkA v-if="isFollowersVisibleForMe(user)" :to="userPage(user, 'followers')">
<b>{{ number(user.followersCount) }}</b>
<span>{{ i18n.ts.followers }}</span>
</MkA> </MkA>
</span>
</div>
<div v-if="iAmModerator" class="moderationNote">
<MkTextarea v-if="editModerationNote || (moderationNote != null && moderationNote !== '')" v-model="moderationNote" manualSave>
<template #label>{{ i18n.ts.moderationNote }}</template>
<template #caption>{{ i18n.ts.moderationNoteDescription }}</template>
</MkTextarea>
<div v-else>
<MkButton small @click="editModerationNote = true">{{ i18n.ts.addModerationNote }}</MkButton>
</div> </div>
</div> </div>
<div v-if="isEditingMemo || memoDraft" class="memo" :class="{'no-memo': !memoDraft}">
<div class="heading" v-text="i18n.ts.memo"/>
<textarea
ref="memoTextareaEl"
v-model="memoDraft"
rows="1"
@focus="isEditingMemo = true"
@blur="updateMemo"
@input="adjustMemoTextarea"
/>
</div>
<div class="description">
<MkOmit>
<Mfm v-if="user.description" :text="user.description" :isNote="false" :author="user" class="_selectable"/>
<p v-else class="empty">{{ i18n.ts.noAccountDescription }}</p>
</MkOmit>
</div>
<div class="fields system">
<dl v-if="user.location" class="field">
<dt class="name"><i class="ti ti-map-pin ti-fw"></i> {{ i18n.ts.location }}</dt>
<dd class="value">{{ user.location }}</dd>
</dl>
<dl v-if="user.birthday" class="field">
<dt class="name"><i class="ti ti-cake ti-fw"></i> {{ i18n.ts.birthday }}</dt>
<dd class="value">{{ user.birthday.replace('-', '/').replace('-', '/') }} ({{ i18n.tsx.yearsOld({ age }) }})</dd>
</dl>
<dl class="field">
<dt class="name"><i class="ti ti-calendar ti-fw"></i> {{ i18n.ts.registeredDate }}</dt>
<dd class="value">{{ dateString(user.createdAt) }} (<MkTime :time="user.createdAt"/>)</dd>
</dl>
</div>
<div v-if="user.fields.length > 0" class="fields">
<dl v-for="(field, i) in user.fields" :key="i" class="field">
<dt class="name">
<Mfm :text="field.name" :author="user" :plain="true" :colored="false" class="_selectable"/>
</dt>
<dd class="value">
<Mfm :text="field.value" :author="user" :colored="false" class="_selectable"/>
<i v-if="user.verifiedLinks.includes(field.value)" v-tooltip:dialog="i18n.ts.verifiedLink" class="ti ti-circle-check" :class="$style.verifiedLink"></i>
</dd>
</dl>
</div>
<div class="status">
<MkA :to="userPage(user)">
<b>{{ number(user.notesCount) }}</b>
<span>{{ i18n.ts.notes }}</span>
</MkA>
<MkA v-if="isFollowingVisibleForMe(user)" :to="userPage(user, 'following')">
<b>{{ number(user.followingCount) }}</b>
<span>{{ i18n.ts.following }}</span>
</MkA>
<MkA v-if="isFollowersVisibleForMe(user)" :to="userPage(user, 'followers')">
<b>{{ number(user.followersCount) }}</b>
<span>{{ i18n.ts.followers }}</span>
</MkA>
</div>
</div> </div>
</div>
<div class="contents _gaps"> <div class="contents _gaps">
<div v-if="user.pinnedNotes.length > 0" class="_gaps"> <div v-if="user.pinnedNotes.length > 0" class="_gaps">
<MkNote v-for="note in user.pinnedNotes" :key="note.id" class="note _panel" :note="note" :pinned="true"/> <MkNote v-for="note in user.pinnedNotes" :key="note.id" class="note _panel" :note="note" :pinned="true"/>
</div> </div>
<MkInfo v-else-if="$i && $i.id === user.id">{{ i18n.ts.userPagePinTip }}</MkInfo> <MkInfo v-else-if="$i && $i.id === user.id">{{ i18n.ts.userPagePinTip }}</MkInfo>
<template v-if="narrow"> <template v-if="narrow">
<MkLazy> <MkLazy>
<XFiles :key="user.id" :user="user" @unfold="emit('unfoldFiles')"/> <XFiles :key="user.id" :user="user" @unfold="emit('unfoldFiles')"/>
</MkLazy> </MkLazy>
<MkLazy> <MkLazy>
<XActivity :key="user.id" :user="user"/> <XActivity :key="user.id" :user="user"/>
</MkLazy> </MkLazy>
</template> </template>
<div v-if="!disableNotes"> <div v-if="!disableNotes">
<MkLazy> <MkLazy>
<XTimeline :user="user"/> <XTimeline :user="user"/>
</MkLazy> </MkLazy>
</div>
</div> </div>
</div> </div>
</div> <div v-if="!narrow" class="sub _gaps" style="container-type: inline-size;">
<div v-if="!narrow" class="sub _gaps" style="container-type: inline-size;"> <XFiles :key="user.id" :user="user" @unfold="emit('unfoldFiles')"/>
<XFiles :key="user.id" :user="user" @unfold="emit('unfoldFiles')"/> <XActivity :key="user.id" :user="user"/>
<XActivity :key="user.id" :user="user"/> </div>
</div> </div>
</div> </div>
</div> </component>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -185,6 +187,7 @@ import { useRouter } from '@/router.js';
import { getStaticImageUrl } from '@/utility/media-proxy.js'; import { getStaticImageUrl } from '@/utility/media-proxy.js';
import MkSparkle from '@/components/MkSparkle.vue'; import MkSparkle from '@/components/MkSparkle.vue';
import { prefer } from '@/preferences.js'; import { prefer } from '@/preferences.js';
import MkPullToRefresh from '@/components/MkPullToRefresh.vue';
function calcAge(birthdate: string): number { function calcAge(birthdate: string): number {
const date = new Date(birthdate); const date = new Date(birthdate);
@ -299,6 +302,10 @@ watch([props.user], () => {
memoDraft.value = props.user.memo; memoDraft.value = props.user.memo;
}); });
async function reload() {
// TODO
}
onMounted(() => { onMounted(() => {
window.requestAnimationFrame(parallaxLoop); window.requestAnimationFrame(parallaxLoop);
narrow.value = rootEl.value!.clientWidth < 1000; narrow.value = rootEl.value!.clientWidth < 1000;