diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2021-11-12 02:02:25 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2021-11-12 02:02:25 +0900 |
| commit | 0e4a111f81cceed275d9bec2695f6e401fb654d8 (patch) | |
| tree | 40874799472fa07416f17b50a398ac33b7771905 /src/client/pages/user | |
| parent | update deps (diff) | |
| download | misskey-0e4a111f81cceed275d9bec2695f6e401fb654d8.tar.gz misskey-0e4a111f81cceed275d9bec2695f6e401fb654d8.tar.bz2 misskey-0e4a111f81cceed275d9bec2695f6e401fb654d8.zip | |
refactoring
Resolve #7779
Diffstat (limited to 'src/client/pages/user')
| -rw-r--r-- | src/client/pages/user/clips.vue | 50 | ||||
| -rw-r--r-- | src/client/pages/user/follow-list.vue | 65 | ||||
| -rw-r--r-- | src/client/pages/user/gallery.vue | 56 | ||||
| -rw-r--r-- | src/client/pages/user/index.activity.vue | 34 | ||||
| -rw-r--r-- | src/client/pages/user/index.photos.vue | 107 | ||||
| -rw-r--r-- | src/client/pages/user/index.timeline.vue | 68 | ||||
| -rw-r--r-- | src/client/pages/user/index.vue | 829 | ||||
| -rw-r--r-- | src/client/pages/user/pages.vue | 49 | ||||
| -rw-r--r-- | src/client/pages/user/reactions.vue | 81 |
9 files changed, 0 insertions, 1339 deletions
diff --git a/src/client/pages/user/clips.vue b/src/client/pages/user/clips.vue deleted file mode 100644 index 53ee554383..0000000000 --- a/src/client/pages/user/clips.vue +++ /dev/null @@ -1,50 +0,0 @@ -<template> -<div> - <MkPagination :pagination="pagination" #default="{items}" ref="list"> - <MkA v-for="item in items" :key="item.id" :to="`/clips/${item.id}`" class="item _panel _gap"> - <b>{{ item.name }}</b> - <div v-if="item.description" class="description">{{ item.description }}</div> - </MkA> - </MkPagination> -</div> -</template> - -<script lang="ts"> -import { defineComponent } from 'vue'; -import MkPagination from '@client/components/ui/pagination.vue'; - -export default defineComponent({ - components: { - MkPagination, - }, - - props: { - user: { - type: Object, - required: true - }, - }, - - data() { - return { - pagination: { - endpoint: 'users/clips', - limit: 20, - params: { - userId: this.user.id, - } - }, - }; - }, - - watch: { - user() { - this.$refs.list.reload(); - } - }, -}); -</script> - -<style lang="scss" scoped> - -</style> diff --git a/src/client/pages/user/follow-list.vue b/src/client/pages/user/follow-list.vue deleted file mode 100644 index 1f5ab5993c..0000000000 --- a/src/client/pages/user/follow-list.vue +++ /dev/null @@ -1,65 +0,0 @@ -<template> -<div> - <MkPagination :pagination="pagination" #default="{items}" class="mk-following-or-followers" ref="list"> - <div class="users _isolated"> - <MkUserInfo class="user" v-for="user in items.map(x => type === 'following' ? x.followee : x.follower)" :user="user" :key="user.id"/> - </div> - </MkPagination> -</div> -</template> - -<script lang="ts"> -import { defineComponent } from 'vue'; -import MkUserInfo from '@client/components/user-info.vue'; -import MkPagination from '@client/components/ui/pagination.vue'; - -export default defineComponent({ - components: { - MkPagination, - MkUserInfo, - }, - - props: { - user: { - type: Object, - required: true - }, - type: { - type: String, - required: true - }, - }, - - data() { - return { - pagination: { - endpoint: () => this.type === 'following' ? 'users/following' : 'users/followers', - limit: 20, - params: { - userId: this.user.id, - } - }, - }; - }, - - watch: { - type() { - this.$refs.list.reload(); - }, - - user() { - this.$refs.list.reload(); - } - } -}); -</script> - -<style lang="scss" scoped> -.mk-following-or-followers { - > .users { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); - grid-gap: var(--margin); - } -} -</style> diff --git a/src/client/pages/user/gallery.vue b/src/client/pages/user/gallery.vue deleted file mode 100644 index c21b3e6428..0000000000 --- a/src/client/pages/user/gallery.vue +++ /dev/null @@ -1,56 +0,0 @@ -<template> -<div> - <MkPagination :pagination="pagination" #default="{items}"> - <div class="jrnovfpt"> - <MkGalleryPostPreview v-for="post in items" :post="post" :key="post.id" class="post"/> - </div> - </MkPagination> -</div> -</template> - -<script lang="ts"> -import { defineComponent } from 'vue'; -import MkGalleryPostPreview from '@client/components/gallery-post-preview.vue'; -import MkPagination from '@client/components/ui/pagination.vue'; - -export default defineComponent({ - components: { - MkPagination, - MkGalleryPostPreview, - }, - - props: { - user: { - type: Object, - required: true - }, - }, - - data() { - return { - pagination: { - endpoint: 'users/gallery/posts', - limit: 6, - params: () => ({ - userId: this.user.id - }) - }, - }; - }, - - watch: { - user() { - this.$refs.list.reload(); - } - } -}); -</script> - -<style lang="scss" scoped> -.jrnovfpt { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); - grid-gap: 12px; - margin: var(--margin); -} -</style> diff --git a/src/client/pages/user/index.activity.vue b/src/client/pages/user/index.activity.vue deleted file mode 100644 index be85c252e8..0000000000 --- a/src/client/pages/user/index.activity.vue +++ /dev/null @@ -1,34 +0,0 @@ -<template> -<MkContainer> - <template #header><i class="fas fa-chart-bar" style="margin-right: 0.5em;"></i>{{ $ts.activity }}</template> - - <div style="padding: 8px;"> - <MkChart src="per-user-notes" :args="{ user, withoutAll: true }" span="day" :limit="limit" :stacked="true" :detailed="false" :aspect-ratio="6"/> - </div> -</MkContainer> -</template> - -<script lang="ts"> -import { defineComponent } from 'vue'; -import * as os from '@client/os'; -import MkContainer from '@client/components/ui/container.vue'; -import MkChart from '@client/components/chart.vue'; - -export default defineComponent({ - components: { - MkContainer, - MkChart, - }, - props: { - user: { - type: Object, - required: true - }, - limit: { - type: Number, - required: false, - default: 40 - } - }, -}); -</script> diff --git a/src/client/pages/user/index.photos.vue b/src/client/pages/user/index.photos.vue deleted file mode 100644 index 5029c3feec..0000000000 --- a/src/client/pages/user/index.photos.vue +++ /dev/null @@ -1,107 +0,0 @@ -<template> -<MkContainer :max-height="300" :foldable="true"> - <template #header><i class="fas fa-image" style="margin-right: 0.5em;"></i>{{ $ts.images }}</template> - <div class="ujigsodd"> - <MkLoading v-if="fetching"/> - <div class="stream" v-if="!fetching && images.length > 0"> - <MkA v-for="image in images" - class="img" - :to="notePage(image.note)" - :key="image.id" - > - <ImgWithBlurhash :hash="image.blurhash" :src="thumbnail(image.file)" :alt="image.name" :title="image.name"/> - </MkA> - </div> - <p class="empty" v-if="!fetching && images.length == 0">{{ $ts.nothing }}</p> - </div> -</MkContainer> -</template> - -<script lang="ts"> -import { defineComponent } from 'vue'; -import { getStaticImageUrl } from '@client/scripts/get-static-image-url'; -import notePage from '@client/filters/note'; -import * as os from '@client/os'; -import MkContainer from '@client/components/ui/container.vue'; -import ImgWithBlurhash from '@client/components/img-with-blurhash.vue'; - -export default defineComponent({ - components: { - MkContainer, - ImgWithBlurhash, - }, - props: { - user: { - type: Object, - required: true - }, - }, - data() { - return { - fetching: true, - images: [], - }; - }, - mounted() { - const image = [ - 'image/jpeg', - 'image/png', - 'image/gif', - 'image/apng', - 'image/vnd.mozilla.apng', - ]; - os.api('users/notes', { - userId: this.user.id, - fileType: image, - excludeNsfw: this.$store.state.nsfw !== 'ignore', - limit: 10, - }).then(notes => { - for (const note of notes) { - for (const file of note.files) { - this.images.push({ - note, - file - }); - } - } - this.fetching = false; - }); - }, - methods: { - thumbnail(image: any): string { - return this.$store.state.disableShowingAnimatedImages - ? getStaticImageUrl(image.thumbnailUrl) - : image.thumbnailUrl; - }, - notePage - }, -}); -</script> - -<style lang="scss" scoped> -.ujigsodd { - padding: 8px; - - > .stream { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); - grid-gap: 6px; - - > .img { - height: 128px; - border-radius: 6px; - overflow: clip; - } - } - - > .empty { - margin: 0; - padding: 16px; - text-align: center; - - > i { - margin-right: 4px; - } - } -} -</style> diff --git a/src/client/pages/user/index.timeline.vue b/src/client/pages/user/index.timeline.vue deleted file mode 100644 index c3444f26f6..0000000000 --- a/src/client/pages/user/index.timeline.vue +++ /dev/null @@ -1,68 +0,0 @@ -<template> -<div class="yrzkoczt" v-sticky-container> - <MkTab v-model="with_" class="tab"> - <option :value="null">{{ $ts.notes }}</option> - <option value="replies">{{ $ts.notesAndReplies }}</option> - <option value="files">{{ $ts.withFiles }}</option> - </MkTab> - <XNotes ref="timeline" :no-gap="true" :pagination="pagination" @before="$emit('before')" @after="e => $emit('after', e)"/> -</div> -</template> - -<script lang="ts"> -import { defineComponent } from 'vue'; -import XNotes from '@client/components/notes.vue'; -import MkTab from '@client/components/tab.vue'; -import * as os from '@client/os'; - -export default defineComponent({ - components: { - XNotes, - MkTab, - }, - - props: { - user: { - type: Object, - required: true, - }, - }, - - watch: { - user() { - this.$refs.timeline.reload(); - }, - - with_() { - this.$refs.timeline.reload(); - }, - }, - - data() { - return { - date: null, - with_: null, - pagination: { - endpoint: 'users/notes', - limit: 10, - params: init => ({ - userId: this.user.id, - includeReplies: this.with_ === 'replies', - withFiles: this.with_ === 'files', - untilDate: init ? undefined : (this.date ? this.date.getTime() : undefined), - }) - } - }; - }, -}); -</script> - -<style lang="scss" scoped> -.yrzkoczt { - > .tab { - margin: calc(var(--margin) / 2) 0; - padding: calc(var(--margin) / 2) 0; - background: var(--bg); - } -} -</style> diff --git a/src/client/pages/user/index.vue b/src/client/pages/user/index.vue deleted file mode 100644 index 04585f3fd0..0000000000 --- a/src/client/pages/user/index.vue +++ /dev/null @@ -1,829 +0,0 @@ -<template> -<div> -<transition name="fade" mode="out-in"> - <div class="ftskorzw wide" v-if="user && narrow === false"> - <MkRemoteCaution v-if="user.host != null" :href="user.url"/> - - <div class="banner-container" :style="style"> - <div class="banner" ref="banner" :style="style"></div> - </div> - <div class="contents"> - <div class="side _forceContainerFull_"> - <MkAvatar class="avatar" :user="user" :disable-preview="true" :show-indicator="true"/> - <div class="name"> - <MkUserName :user="user" :nowrap="false" class="name"/> - <MkAcct :user="user" :detail="true" class="acct"/> - </div> - <div class="followed" v-if="$i && $i.id != user.id && user.isFollowed"><span>{{ $ts.followsYou }}</span></div> - <div class="status"> - <MkA :to="userPage(user)" :class="{ active: page === 'index' }"> - <b>{{ number(user.notesCount) }}</b> - <span>{{ $ts.notes }}</span> - </MkA> - <MkA :to="userPage(user, 'following')" :class="{ active: page === 'following' }"> - <b>{{ number(user.followingCount) }}</b> - <span>{{ $ts.following }}</span> - </MkA> - <MkA :to="userPage(user, 'followers')" :class="{ active: page === 'followers' }"> - <b>{{ number(user.followersCount) }}</b> - <span>{{ $ts.followers }}</span> - </MkA> - </div> - <div class="description"> - <Mfm v-if="user.description" :text="user.description" :is-note="false" :author="user" :i="$i" :custom-emojis="user.emojis"/> - <p v-else class="empty">{{ $ts.noAccountDescription }}</p> - </div> - <div class="fields system"> - <dl class="field" v-if="user.location"> - <dt class="name"><i class="fas fa-map-marker fa-fw"></i> {{ $ts.location }}</dt> - <dd class="value">{{ user.location }}</dd> - </dl> - <dl class="field" v-if="user.birthday"> - <dt class="name"><i class="fas fa-birthday-cake fa-fw"></i> {{ $ts.birthday }}</dt> - <dd class="value">{{ user.birthday.replace('-', '/').replace('-', '/') }} ({{ $t('yearsOld', { age }) }})</dd> - </dl> - <dl class="field"> - <dt class="name"><i class="fas fa-calendar-alt fa-fw"></i> {{ $ts.registeredDate }}</dt> - <dd class="value">{{ new Date(user.createdAt).toLocaleString() }} (<MkTime :time="user.createdAt"/>)</dd> - </dl> - </div> - <div class="fields" v-if="user.fields.length > 0"> - <dl class="field" v-for="(field, i) in user.fields" :key="i"> - <dt class="name"> - <Mfm :text="field.name" :plain="true" :custom-emojis="user.emojis" :colored="false"/> - </dt> - <dd class="value"> - <Mfm :text="field.value" :author="user" :i="$i" :custom-emojis="user.emojis" :colored="false"/> - </dd> - </dl> - </div> - <XActivity :user="user" :key="user.id" class="_gap"/> - <XPhotos :user="user" :key="user.id" class="_gap"/> - </div> - <div class="main"> - <div class="actions"> - <button @click="menu" class="menu _button"><i class="fas fa-ellipsis-h"></i></button> - <MkFollowButton v-if="!$i || $i.id != user.id" :user="user" :inline="true" :transparent="false" :full="true" large class="koudoku"/> - </div> - <template v-if="page === 'index'"> - <div v-if="user.pinnedNotes.length > 0" class="_gap"> - <XNote v-for="note in user.pinnedNotes" class="note _gap" :note="note" @update:note="pinnedNoteUpdated(note, $event)" :key="note.id" :pinned="true"/> - </div> - <div class="_gap"> - <XUserTimeline :user="user"/> - </div> - </template> - <XFollowList v-else-if="page === 'following'" type="following" :user="user" class="_gap"/> - <XFollowList v-else-if="page === 'followers'" type="followers" :user="user" class="_gap"/> - <XClips v-else-if="page === 'clips'" :user="user" class="_gap"/> - <XPages v-else-if="page === 'pages'" :user="user" class="_gap"/> - </div> - </div> - </div> - <MkSpacer v-else-if="user && narrow === true" :content-max="800"> - <div class="ftskorzw narrow" v-size="{ max: [500] }"> - <!-- TODO --> - <!-- <div class="punished" v-if="user.isSuspended"><i class="fas fa-exclamation-triangle" style="margin-right: 8px;"></i> {{ $ts.userSuspended }}</div> --> - <!-- <div class="punished" v-if="user.isSilenced"><i class="fas fa-exclamation-triangle" style="margin-right: 8px;"></i> {{ $ts.userSilenced }}</div> --> - - <div class="profile"> - <MkRemoteCaution v-if="user.host != null" :href="user.url" class="warn"/> - - <div class="_block main" :key="user.id"> - <div class="banner-container" :style="style"> - <div class="banner" ref="banner" :style="style"></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="$ts.isAdmin" style="color: var(--badge);"><i class="fas fa-bookmark"></i></span> - <span v-if="!user.isAdmin && user.isModerator" :title="$ts.isModerator" style="color: var(--badge);"><i class="far fa-bookmark"></i></span> - <span v-if="user.isLocked" :title="$ts.isLocked"><i class="fas fa-lock"></i></span> - <span v-if="user.isBot" :title="$ts.isBot"><i class="fas fa-robot"></i></span> - </div> - </div> - <span class="followed" v-if="$i && $i.id != user.id && user.isFollowed">{{ $ts.followsYou }}</span> - <div class="actions" v-if="$i"> - <button @click="menu" class="menu _button"><i class="fas fa-ellipsis-h"></i></button> - <MkFollowButton v-if="$i.id != user.id" :user="user" :inline="true" :transparent="false" :full="true" class="koudoku"/> - </div> - </div> - <MkAvatar class="avatar" :user="user" :disable-preview="true" :show-indicator="true"/> - <div class="title"> - <MkUserName :user="user" :nowrap="false" class="name"/> - <div class="bottom"> - <span class="username"><MkAcct :user="user" :detail="true" /></span> - <span v-if="user.isAdmin" :title="$ts.isAdmin" style="color: var(--badge);"><i class="fas fa-bookmark"></i></span> - <span v-if="!user.isAdmin && user.isModerator" :title="$ts.isModerator" style="color: var(--badge);"><i class="far fa-bookmark"></i></span> - <span v-if="user.isLocked" :title="$ts.isLocked"><i class="fas fa-lock"></i></span> - <span v-if="user.isBot" :title="$ts.isBot"><i class="fas fa-robot"></i></span> - </div> - </div> - <div class="description"> - <Mfm v-if="user.description" :text="user.description" :is-note="false" :author="user" :i="$i" :custom-emojis="user.emojis"/> - <p v-else class="empty">{{ $ts.noAccountDescription }}</p> - </div> - <div class="fields system"> - <dl class="field" v-if="user.location"> - <dt class="name"><i class="fas fa-map-marker fa-fw"></i> {{ $ts.location }}</dt> - <dd class="value">{{ user.location }}</dd> - </dl> - <dl class="field" v-if="user.birthday"> - <dt class="name"><i class="fas fa-birthday-cake fa-fw"></i> {{ $ts.birthday }}</dt> - <dd class="value">{{ user.birthday.replace('-', '/').replace('-', '/') }} ({{ $t('yearsOld', { age }) }})</dd> - </dl> - <dl class="field"> - <dt class="name"><i class="fas fa-calendar-alt fa-fw"></i> {{ $ts.registeredDate }}</dt> - <dd class="value">{{ new Date(user.createdAt).toLocaleString() }} (<MkTime :time="user.createdAt"/>)</dd> - </dl> - </div> - <div class="fields" v-if="user.fields.length > 0"> - <dl class="field" v-for="(field, i) in user.fields" :key="i"> - <dt class="name"> - <Mfm :text="field.name" :plain="true" :custom-emojis="user.emojis" :colored="false"/> - </dt> - <dd class="value"> - <Mfm :text="field.value" :author="user" :i="$i" :custom-emojis="user.emojis" :colored="false"/> - </dd> - </dl> - </div> - <div class="status"> - <MkA :to="userPage(user)" :class="{ active: page === 'index' }" v-click-anime> - <b>{{ number(user.notesCount) }}</b> - <span>{{ $ts.notes }}</span> - </MkA> - <MkA :to="userPage(user, 'following')" :class="{ active: page === 'following' }" v-click-anime> - <b>{{ number(user.followingCount) }}</b> - <span>{{ $ts.following }}</span> - </MkA> - <MkA :to="userPage(user, 'followers')" :class="{ active: page === 'followers' }" v-click-anime> - <b>{{ number(user.followersCount) }}</b> - <span>{{ $ts.followers }}</span> - </MkA> - </div> - </div> - </div> - - <div class="contents"> - <template v-if="page === 'index'"> - <div> - <div v-if="user.pinnedNotes.length > 0" class="_gap"> - <XNote v-for="note in user.pinnedNotes" class="note _block" :note="note" @update:note="pinnedNoteUpdated(note, $event)" :key="note.id" :pinned="true"/> - </div> - <MkInfo v-else-if="$i && $i.id === user.id">{{ $ts.userPagePinTip }}</MkInfo> - <XPhotos :user="user" :key="user.id"/> - <XActivity :user="user" :key="user.id" style="margin-top: var(--margin);"/> - </div> - <div> - <XUserTimeline :user="user"/> - </div> - </template> - <XFollowList v-else-if="page === 'following'" type="following" :user="user" class="_content _gap"/> - <XFollowList v-else-if="page === 'followers'" type="followers" :user="user" class="_content _gap"/> - <XReactions v-else-if="page === 'reactions'" :user="user" class="_gap"/> - <XClips v-else-if="page === 'clips'" :user="user" class="_gap"/> - <XPages v-else-if="page === 'pages'" :user="user" class="_gap"/> - <XGallery v-else-if="page === 'gallery'" :user="user" class="_gap"/> - </div> - </div> - </MkSpacer> - <MkError v-else-if="error" @retry="fetch()"/> - <MkLoading v-else/> -</transition> -</div> -</template> - -<script lang="ts"> -import { defineComponent, defineAsyncComponent, computed } from 'vue'; -import * as age from 's-age'; -import XUserTimeline from './index.timeline.vue'; -import XNote from '@client/components/note.vue'; -import MkFollowButton from '@client/components/follow-button.vue'; -import MkContainer from '@client/components/ui/container.vue'; -import MkFolder from '@client/components/ui/folder.vue'; -import MkRemoteCaution from '@client/components/remote-caution.vue'; -import MkTab from '@client/components/tab.vue'; -import MkInfo from '@client/components/ui/info.vue'; -import Progress from '@client/scripts/loading'; -import { parseAcct } from '@/misc/acct'; -import { getScrollPosition } from '@client/scripts/scroll'; -import { getUserMenu } from '@client/scripts/get-user-menu'; -import number from '@client/filters/number'; -import { userPage, acct as getAcct } from '@client/filters/user'; -import * as os from '@client/os'; -import * as symbols from '@client/symbols'; - -export default defineComponent({ - components: { - XUserTimeline, - XNote, - MkFollowButton, - MkContainer, - MkRemoteCaution, - MkFolder, - MkTab, - MkInfo, - XFollowList: defineAsyncComponent(() => import('./follow-list.vue')), - XReactions: defineAsyncComponent(() => import('./reactions.vue')), - XClips: defineAsyncComponent(() => import('./clips.vue')), - XPages: defineAsyncComponent(() => import('./pages.vue')), - XGallery: defineAsyncComponent(() => import('./gallery.vue')), - XPhotos: defineAsyncComponent(() => import('./index.photos.vue')), - XActivity: defineAsyncComponent(() => import('./index.activity.vue')), - }, - - props: { - acct: { - type: String, - required: true - }, - page: { - type: String, - required: false, - default: 'index' - } - }, - - data() { - return { - [symbols.PAGE_INFO]: computed(() => this.user ? { - icon: 'fas fa-user', - title: this.user.name ? `${this.user.name} (@${this.user.username})` : `@${this.user.username}`, - subtitle: `@${getAcct(this.user)}`, - userName: this.user, - avatar: this.user, - path: `/@${this.user.username}`, - share: { - title: this.user.name, - }, - bg: 'var(--bg)', - tabs: [{ - active: this.page === 'index', - title: this.$ts.overview, - icon: 'fas fa-home', - onClick: () => { this.$router.push('/@' + getAcct(this.user)); }, - }, ...(this.$i && (this.$i.id === this.user.id)) || this.user.publicReactions ? [{ - active: this.page === 'reactions', - title: this.$ts.reaction, - icon: 'fas fa-laugh', - onClick: () => { this.$router.push('/@' + getAcct(this.user) + '/reactions'); }, - }] : [], { - active: this.page === 'clips', - title: this.$ts.clips, - icon: 'fas fa-paperclip', - onClick: () => { this.$router.push('/@' + getAcct(this.user) + '/clips'); }, - }, { - active: this.page === 'pages', - title: this.$ts.pages, - icon: 'fas fa-file-alt', - onClick: () => { this.$router.push('/@' + getAcct(this.user) + '/pages'); }, - }, { - active: this.page === 'gallery', - title: this.$ts.gallery, - icon: 'fas fa-icons', - onClick: () => { this.$router.push('/@' + getAcct(this.user) + '/gallery'); }, - }], - } : null), - user: null, - error: null, - parallaxAnimationId: null, - narrow: null, - }; - }, - - computed: { - style(): any { - if (this.user.bannerUrl == null) return {}; - return { - backgroundImage: `url(${ this.user.bannerUrl })` - }; - }, - - age(): number { - return age(this.user.birthday); - } - }, - - watch: { - acct: 'fetch' - }, - - created() { - this.fetch(); - }, - - mounted() { - window.requestAnimationFrame(this.parallaxLoop); - this.narrow = true//this.$el.clientWidth < 1000; - }, - - beforeUnmount() { - window.cancelAnimationFrame(this.parallaxAnimationId); - }, - - methods: { - getAcct, - - fetch() { - if (this.acct == null) return; - this.user = null; - Progress.start(); - os.api('users/show', parseAcct(this.acct)).then(user => { - this.user = user; - }).catch(e => { - this.error = e; - }).finally(() => { - Progress.done(); - }); - }, - - menu(ev) { - os.popupMenu(getUserMenu(this.user), ev.currentTarget || ev.target); - }, - - parallaxLoop() { - this.parallaxAnimationId = window.requestAnimationFrame(this.parallaxLoop); - this.parallax(); - }, - - parallax() { - const banner = this.$refs.banner as any; - if (banner == null) return; - - const top = getScrollPosition(this.$el); - - if (top < 0) return; - - const z = 1.75; // 奥行き(小さいほど奥) - const pos = -(top / z); - banner.style.backgroundPosition = `center calc(50% - ${pos}px)`; - }, - - pinnedNoteUpdated(oldValue, newValue) { - const i = this.user.pinnedNotes.findIndex(n => n === oldValue); - this.user.pinnedNotes[i] = newValue; - }, - - number, - - userPage - } -}); -</script> - -<style lang="scss" scoped> -.fade-enter-active, -.fade-leave-active { - transition: opacity 0.125s ease; -} -.fade-enter-from, -.fade-leave-to { - opacity: 0; -} - -.ftskorzw.wide { - - > .banner-container { - position: relative; - height: 300px; - overflow: hidden; - background-size: cover; - background-position: center; - - > .banner { - height: 100%; - background-color: #4c5e6d; - background-size: cover; - background-position: center; - box-shadow: 0 0 128px rgba(0, 0, 0, 0.5) inset; - will-change: background-position; - } - } - - > .contents { - display: flex; - padding: 16px; - - > .side { - width: 360px; - - > .avatar { - display: block; - width: 180px; - height: 180px; - margin: -130px auto 0 auto; - } - - > .name { - padding: 16px 0px 20px 0; - text-align: center; - - > .name { - display: block; - font-size: 1.75em; - font-weight: bold; - } - } - - > .followed { - text-align: center; - - > span { - display: inline-block; - font-size: 80%; - padding: 8px 12px; - margin-bottom: 20px; - border: solid 0.5px var(--divider); - border-radius: 999px; - } - } - - > .status { - display: flex; - padding: 20px 16px; - border-top: solid 0.5px var(--divider); - font-size: 90%; - - > a { - flex: 1; - text-align: center; - - &.active { - color: var(--accent); - } - - &:hover { - text-decoration: none; - } - - > b { - display: block; - line-height: 16px; - } - - > span { - font-size: 75%; - } - } - } - - > .description { - padding: 20px 16px; - border-top: solid 0.5px var(--divider); - font-size: 90%; - } - - > .fields { - padding: 20px 16px; - border-top: solid 0.5px var(--divider); - font-size: 90%; - - > .field { - display: flex; - padding: 0; - margin: 0; - align-items: center; - - &:not(:last-child) { - margin-bottom: 8px; - } - - > .name { - width: 30%; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - font-weight: bold; - } - - > .value { - width: 70%; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - margin: 0; - } - } - } - } - - > .main { - flex: 1; - margin-left: var(--margin); - min-width: 0; - - > .nav { - display: flex; - align-items: center; - margin-top: var(--margin); - //font-size: 120%; - font-weight: bold; - - > .link { - display: inline-block; - padding: 15px 24px 12px 24px; - text-align: center; - border-bottom: solid 3px transparent; - - &:hover { - text-decoration: none; - } - - &.active { - color: var(--accent); - border-bottom-color: var(--accent); - } - - &:not(.active):hover { - color: var(--fgHighlighted); - } - - > .icon { - margin-right: 6px; - } - } - - > .actions { - display: flex; - align-items: center; - margin-left: auto; - - > .menu { - padding: 12px 16px; - } - } - } - } - } -} - -.ftskorzw.narrow { - box-sizing: border-box; - overflow: clip; - background: var(--bg); - - > .punished { - font-size: 0.8em; - padding: 16px; - } - - > .profile { - - > .main { - position: relative; - overflow: hidden; - - > .banner-container { - position: relative; - height: 250px; - overflow: hidden; - background-size: cover; - background-position: center; - - > .banner { - height: 100%; - background-color: #4c5e6d; - background-size: cover; - background-position: center; - box-shadow: 0 0 128px rgba(0, 0, 0, 0.5) inset; - will-change: background-position; - } - - > .fade { - position: absolute; - bottom: 0; - left: 0; - width: 100%; - height: 78px; - background: linear-gradient(transparent, rgba(#000, 0.7)); - } - - > .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; - } - - > .actions { - position: absolute; - top: 12px; - right: 12px; - -webkit-backdrop-filter: var(--blur, blur(8px)); - backdrop-filter: var(--blur, blur(8px)); - background: rgba(0, 0, 0, 0.2); - padding: 8px; - border-radius: 24px; - - > .menu { - vertical-align: bottom; - height: 31px; - width: 31px; - color: #fff; - text-shadow: 0 0 8px #000; - font-size: 16px; - } - - > .koudoku { - margin-left: 4px; - vertical-align: bottom; - } - } - - > .title { - position: absolute; - bottom: 0; - left: 0; - width: 100%; - padding: 0 0 8px 154px; - box-sizing: border-box; - color: #fff; - - > .name { - display: block; - margin: 0; - line-height: 32px; - font-weight: bold; - font-size: 1.8em; - text-shadow: 0 0 8px #000; - } - - > .bottom { - > * { - display: inline-block; - margin-right: 16px; - line-height: 20px; - opacity: 0.8; - - &.username { - font-weight: bold; - } - } - } - } - } - - > .title { - display: none; - text-align: center; - padding: 50px 8px 16px 8px; - font-weight: bold; - border-bottom: solid 0.5px var(--divider); - - > .bottom { - > * { - display: inline-block; - margin-right: 8px; - opacity: 0.8; - } - } - } - - > .avatar { - display: block; - position: absolute; - top: 170px; - left: 16px; - z-index: 2; - width: 120px; - height: 120px; - box-shadow: 1px 1px 3px rgba(#000, 0.2); - } - - > .description { - padding: 24px 24px 24px 154px; - font-size: 0.95em; - - > .empty { - margin: 0; - opacity: 0.5; - } - } - - > .fields { - padding: 24px; - font-size: 0.9em; - border-top: solid 0.5px var(--divider); - - > .field { - display: flex; - padding: 0; - margin: 0; - align-items: center; - - &:not(:last-child) { - margin-bottom: 8px; - } - - > .name { - width: 30%; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - font-weight: bold; - text-align: center; - } - - > .value { - width: 70%; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - margin: 0; - } - } - - &.system > .field > .name { - } - } - - > .status { - display: flex; - padding: 24px; - border-top: solid 0.5px var(--divider); - - > a { - flex: 1; - text-align: center; - - &.active { - color: var(--accent); - } - - &:hover { - text-decoration: none; - } - - > b { - display: block; - line-height: 16px; - } - - > span { - font-size: 70%; - } - } - } - } - } - - > .contents { - > .content { - margin-bottom: var(--margin); - } - } - - &.max-width_500px { - > .profile > .main { - > .banner-container { - height: 140px; - - > .fade { - display: none; - } - - > .title { - display: none; - } - } - - > .title { - display: block; - } - - > .avatar { - top: 90px; - left: 0; - right: 0; - width: 92px; - height: 92px; - margin: auto; - } - - > .description { - padding: 16px; - text-align: center; - } - - > .fields { - padding: 16px; - } - - > .status { - padding: 16px; - } - } - - > .contents { - > .nav { - font-size: 80%; - } - } - } -} -</style> diff --git a/src/client/pages/user/pages.vue b/src/client/pages/user/pages.vue deleted file mode 100644 index ece418cf62..0000000000 --- a/src/client/pages/user/pages.vue +++ /dev/null @@ -1,49 +0,0 @@ -<template> -<div> - <MkPagination :pagination="pagination" #default="{items}" ref="list"> - <MkPagePreview v-for="page in items" :page="page" :key="page.id" class="_gap"/> - </MkPagination> -</div> -</template> - -<script lang="ts"> -import { defineComponent } from 'vue'; -import MkPagePreview from '@client/components/page-preview.vue'; -import MkPagination from '@client/components/ui/pagination.vue'; - -export default defineComponent({ - components: { - MkPagination, - MkPagePreview, - }, - - props: { - user: { - type: Object, - required: true - }, - }, - - data() { - return { - pagination: { - endpoint: 'users/pages', - limit: 20, - params: { - userId: this.user.id, - } - }, - }; - }, - - watch: { - user() { - this.$refs.list.reload(); - } - } -}); -</script> - -<style lang="scss" scoped> - -</style> diff --git a/src/client/pages/user/reactions.vue b/src/client/pages/user/reactions.vue deleted file mode 100644 index 5ac7e01027..0000000000 --- a/src/client/pages/user/reactions.vue +++ /dev/null @@ -1,81 +0,0 @@ -<template> -<div> - <MkPagination :pagination="pagination" #default="{items}" ref="list"> - <div v-for="item in items" :key="item.id" :to="`/clips/${item.id}`" class="item _panel _gap afdcfbfb"> - <div class="header"> - <MkAvatar class="avatar" :user="user"/> - <MkReactionIcon class="reaction" :reaction="item.type" :custom-emojis="item.note.emojis" :no-style="true"/> - <MkTime :time="item.createdAt" class="createdAt"/> - </div> - <MkNote :note="item.note" @update:note="updated(note, $event)" :key="item.id"/> - </div> - </MkPagination> -</div> -</template> - -<script lang="ts"> -import { defineComponent } from 'vue'; -import MkPagination from '@client/components/ui/pagination.vue'; -import MkNote from '@client/components/note.vue'; -import MkReactionIcon from '@client/components/reaction-icon.vue'; - -export default defineComponent({ - components: { - MkPagination, - MkNote, - MkReactionIcon, - }, - - props: { - user: { - type: Object, - required: true - }, - }, - - data() { - return { - pagination: { - endpoint: 'users/reactions', - limit: 20, - params: { - userId: this.user.id, - } - }, - }; - }, - - watch: { - user() { - this.$refs.list.reload(); - } - }, -}); -</script> - -<style lang="scss" scoped> -.afdcfbfb { - > .header { - display: flex; - align-items: center; - padding: 8px 16px; - margin-bottom: 8px; - border-bottom: solid 2px var(--divider); - - > .avatar { - width: 24px; - height: 24px; - margin-right: 8px; - } - - > .reaction { - width: 32px; - height: 32px; - } - - > .createdAt { - margin-left: auto; - } - } -} -</style> |