diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2022-08-31 00:24:33 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2022-08-31 00:24:33 +0900 |
| commit | 786b150ea75111b5f6102c256d5cfa42cb83d1fb (patch) | |
| tree | d552d0c371829d7ff027890d1036a80bb08517f7 /packages/client/src/components/MkUserPreview.vue | |
| parent | update deps (diff) | |
| download | misskey-786b150ea75111b5f6102c256d5cfa42cb83d1fb.tar.gz misskey-786b150ea75111b5f6102c256d5cfa42cb83d1fb.tar.bz2 misskey-786b150ea75111b5f6102c256d5cfa42cb83d1fb.zip | |
refactor(client): align filename to component name
Diffstat (limited to 'packages/client/src/components/MkUserPreview.vue')
| -rw-r--r-- | packages/client/src/components/MkUserPreview.vue | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/packages/client/src/components/MkUserPreview.vue b/packages/client/src/components/MkUserPreview.vue new file mode 100644 index 0000000000..427e46ef16 --- /dev/null +++ b/packages/client/src/components/MkUserPreview.vue @@ -0,0 +1,204 @@ +<template> +<transition :name="$store.state.animation ? 'popup' : ''" appear @after-leave="$emit('closed')"> + <div v-if="showing" class="fxxzrfni _popup _shadow" :style="{ zIndex, top: top + 'px', left: left + 'px' }" @mouseover="() => { $emit('mouseover'); }" @mouseleave="() => { $emit('mouseleave'); }"> + <div v-if="fetched" class="info"> + <div class="banner" :style="user.bannerUrl ? `background-image: url(${user.bannerUrl})` : ''"> + <span v-if="$i && $i.id != user.id && user.isFollowed" class="followed">{{ $ts.followsYou }}</span> + </div> + <MkAvatar class="avatar" :user="user" :disable-preview="true" :show-indicator="true"/> + <div class="title"> + <MkA class="name" :to="userPage(user)"><MkUserName :user="user" :nowrap="false"/></MkA> + <p class="username"><MkAcct :user="user"/></p> + </div> + <div class="description"> + <Mfm v-if="user.description" :text="user.description" :author="user" :i="$i" :custom-emojis="user.emojis"/> + </div> + <div class="status"> + <div> + <p>{{ $ts.notes }}</p><span>{{ user.notesCount }}</span> + </div> + <div> + <p>{{ $ts.following }}</p><span>{{ user.followingCount }}</span> + </div> + <div> + <p>{{ $ts.followers }}</p><span>{{ user.followersCount }}</span> + </div> + </div> + <MkFollowButton v-if="$i && user.id != $i.id" class="koudoku-button" :user="user" mini/> + </div> + <div v-else> + <MkLoading/> + </div> + </div> +</transition> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import * as Acct from 'misskey-js/built/acct'; +import MkFollowButton from '@/components/MkFollowButton.vue'; +import { userPage } from '@/filters/user'; +import * as os from '@/os'; + +export default defineComponent({ + components: { + MkFollowButton, + }, + + props: { + showing: { + type: Boolean, + required: true, + }, + q: { + type: String, + required: true, + }, + source: { + required: true, + }, + }, + + emits: ['closed', 'mouseover', 'mouseleave'], + + data() { + return { + user: null, + fetched: false, + top: 0, + left: 0, + zIndex: os.claimZIndex('middle'), + }; + }, + + mounted() { + if (typeof this.q === 'object') { + this.user = this.q; + this.fetched = true; + } else { + const query = this.q.startsWith('@') ? + Acct.parse(this.q.substr(1)) : + { userId: this.q }; + + os.api('users/show', query).then(user => { + if (!this.showing) return; + this.user = user; + this.fetched = true; + }); + } + + const rect = this.source.getBoundingClientRect(); + const x = ((rect.left + (this.source.offsetWidth / 2)) - (300 / 2)) + window.pageXOffset; + const y = rect.top + this.source.offsetHeight + window.pageYOffset; + + this.top = y; + this.left = x; + }, + + methods: { + userPage, + }, +}); +</script> + +<style lang="scss" scoped> +.popup-enter-active, .popup-leave-active { + transition: opacity 0.3s, transform 0.3s !important; +} +.popup-enter-from, .popup-leave-to { + opacity: 0; + transform: scale(0.9); +} + +.fxxzrfni { + position: absolute; + width: 300px; + overflow: hidden; + transform-origin: center top; + + > .info { + > .banner { + height: 84px; + background-color: rgba(0, 0, 0, 0.1); + background-size: cover; + background-position: center; + > .followed { + position: absolute; + top: 12px; + left: 12px; + padding: 4px 8px; + color: #fff; + background: rgba(0, 0, 0, 0.7); + font-size: 0.7em; + border-radius: 6px; + } + } + + > .avatar { + display: block; + position: absolute; + top: 62px; + left: 13px; + z-index: 2; + width: 58px; + height: 58px; + border: solid 3px var(--face); + border-radius: 8px; + } + + > .title { + display: block; + padding: 8px 0 8px 82px; + + > .name { + display: inline-block; + margin: 0; + font-weight: bold; + line-height: 16px; + word-break: break-all; + } + + > .username { + display: block; + margin: 0; + line-height: 16px; + font-size: 0.8em; + color: var(--fg); + opacity: 0.7; + } + } + + > .description { + padding: 0 16px; + font-size: 0.8em; + color: var(--fg); + } + + > .status { + padding: 8px 16px; + + > div { + display: inline-block; + width: 33%; + + > p { + margin: 0; + font-size: 0.7em; + color: var(--fg); + } + + > span { + font-size: 1em; + color: var(--accent); + } + } + } + + > .koudoku-button { + position: absolute; + top: 8px; + right: 8px; + } + } +} +</style> |