Compare commits
1 commit
develop
...
header-ref
Author | SHA1 | Date | |
---|---|---|---|
|
9590042383 |
15 changed files with 218 additions and 250 deletions
|
@ -1,10 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="fdidabkb" :class="{ slim: titleOnly || narrow }" :style="`--height:${height};`" :key="key">
|
<div class="fdidabkb" :class="{ slim: titleOnly || narrow }" :style="{ background: bg }">
|
||||||
<transition :name="$store.state.animation ? 'header' : ''" mode="out-in" appear>
|
|
||||||
<div class="buttons left" v-if="backButton">
|
|
||||||
<button class="_button button back" @click.stop="$emit('back')" @touchstart="preventDrag" v-tooltip="$ts.goBack"><i class="fas fa-chevron-left"></i></button>
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
<template v-if="info">
|
<template v-if="info">
|
||||||
<div class="titleContainer" @click="showTabsPopup">
|
<div class="titleContainer" @click="showTabsPopup">
|
||||||
<i v-if="info.icon" class="icon" :class="info.icon"></i>
|
<i v-if="info.icon" class="icon" :class="info.icon"></i>
|
||||||
|
@ -43,20 +38,14 @@
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { popupMenu } from '@client/os';
|
import { popupMenu } from '@client/os';
|
||||||
import { url } from '@client/config';
|
import { url } from '@client/config';
|
||||||
|
import * as symbols from '@client/symbols';
|
||||||
|
import * as tinycolor from 'tinycolor2';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
info: {
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
menu: {
|
menu: {
|
||||||
required: false
|
required: false
|
||||||
},
|
},
|
||||||
backButton: {
|
|
||||||
type: Boolean,
|
|
||||||
required: false,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
closeButton: {
|
closeButton: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
|
@ -71,9 +60,10 @@ export default defineComponent({
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
info: null,
|
||||||
|
bg: null,
|
||||||
narrow: false,
|
narrow: false,
|
||||||
height: 0,
|
height: 0,
|
||||||
key: 0,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -92,17 +82,16 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
created() {
|
||||||
info() {
|
this.info = this.$parent[symbols.PAGE_INFO];
|
||||||
this.key++;
|
const bg = tinycolor(this.info.bg.startsWith('var(') ? getComputedStyle(document.documentElement).getPropertyValue(this.info.bg.slice(4, -1)) : this.info.bg);
|
||||||
},
|
bg.setAlpha(0.85);
|
||||||
|
this.bg = bg.toRgbString();
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.height = this.$el.parentElement.offsetHeight + 'px';
|
|
||||||
this.narrow = this.titleOnly || this.$el.parentElement.offsetWidth < 500;
|
this.narrow = this.titleOnly || this.$el.parentElement.offsetWidth < 500;
|
||||||
new ResizeObserver((entries, observer) => {
|
new ResizeObserver((entries, observer) => {
|
||||||
this.height = this.$el.parentElement.offsetHeight + 'px';
|
|
||||||
this.narrow = this.titleOnly || this.$el.parentElement.offsetWidth < 500;
|
this.narrow = this.titleOnly || this.$el.parentElement.offsetWidth < 500;
|
||||||
}).observe(this.$el);
|
}).observe(this.$el);
|
||||||
},
|
},
|
||||||
|
@ -161,7 +150,13 @@ export default defineComponent({
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.fdidabkb {
|
.fdidabkb {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1000;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
-webkit-backdrop-filter: var(--blur, blur(16px));
|
||||||
|
backdrop-filter: var(--blur, blur(16px));
|
||||||
|
--height: 60px;
|
||||||
|
|
||||||
&.slim {
|
&.slim {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -220,6 +215,7 @@ export default defineComponent({
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
margin-left: 16px;
|
||||||
|
|
||||||
> .avatar {
|
> .avatar {
|
||||||
$size: 32px;
|
$size: 32px;
|
|
@ -13,6 +13,7 @@ import i18n from './global/i18n';
|
||||||
import loading from './global/loading.vue';
|
import loading from './global/loading.vue';
|
||||||
import error from './global/error.vue';
|
import error from './global/error.vue';
|
||||||
import ad from './global/ad.vue';
|
import ad from './global/ad.vue';
|
||||||
|
import header from './global/header.vue';
|
||||||
|
|
||||||
export default function(app: App) {
|
export default function(app: App) {
|
||||||
app.component('I18n', i18n);
|
app.component('I18n', i18n);
|
||||||
|
@ -28,4 +29,5 @@ export default function(app: App) {
|
||||||
app.component('MkLoading', loading);
|
app.component('MkLoading', loading);
|
||||||
app.component('MkError', error);
|
app.component('MkError', error);
|
||||||
app.component('MkAd', ad);
|
app.component('MkAd', ad);
|
||||||
|
app.component('MkHeader', header);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import MkModal from '@client/components/ui/modal.vue';
|
import MkModal from '@client/components/ui/modal.vue';
|
||||||
import XHeader from '@client/ui/_common_/header.vue';
|
|
||||||
import { popout } from '@client/scripts/popout';
|
import { popout } from '@client/scripts/popout';
|
||||||
import copyToClipboard from '@client/scripts/copy-to-clipboard';
|
import copyToClipboard from '@client/scripts/copy-to-clipboard';
|
||||||
import { resolve } from '@client/router';
|
import { resolve } from '@client/router';
|
||||||
|
@ -29,7 +28,6 @@ import * as os from '@client/os';
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MkModal,
|
MkModal,
|
||||||
XHeader,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
inject: {
|
inject: {
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import XWindow from '@client/components/ui/window.vue';
|
import XWindow from '@client/components/ui/window.vue';
|
||||||
import XHeader from '@client/ui/_common_/header.vue';
|
|
||||||
import { popout } from '@client/scripts/popout';
|
import { popout } from '@client/scripts/popout';
|
||||||
import copyToClipboard from '@client/scripts/copy-to-clipboard';
|
import copyToClipboard from '@client/scripts/copy-to-clipboard';
|
||||||
import { resolve } from '@client/router';
|
import { resolve } from '@client/router';
|
||||||
|
@ -29,7 +28,6 @@ import * as symbols from '@client/symbols';
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
XWindow,
|
XWindow,
|
||||||
XHeader,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
inject: {
|
inject: {
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="clupoqwt" v-size="{ min: [800] }">
|
<div>
|
||||||
<XNotifications class="notifications" @before="before" @after="after" page/>
|
<MkHeader></MkHeader>
|
||||||
|
<div class="clupoqwt" v-size="{ min: [800] }">
|
||||||
|
<XNotifications class="notifications" @before="before" @after="after"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -47,13 +50,13 @@ export default defineComponent({
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.clupoqwt {
|
.clupoqwt {
|
||||||
&.min-width_800px {
|
padding: 16px;
|
||||||
background: var(--bg);
|
|
||||||
padding: 32px 0;
|
|
||||||
|
|
||||||
|
&.min-width_800px {
|
||||||
> .notifications {
|
> .notifications {
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
border-radius: var(--radius);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
|
<h1 v-if="INFO" style="font-size: 1.3em; margin: 32px 0 0 32px;"><span style="opacity: 0.6;">設定</span> / {{ INFO.title }}</h1>
|
||||||
<component :is="component" :key="page" @info="onInfo" v-bind="pageProps"/>
|
<component :is="component" :key="page" @info="onInfo" v-bind="pageProps"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -170,6 +171,7 @@ export default defineComponent({
|
||||||
const emailNotConfigured = computed(() => instance.enableEmail && ($i.email == null || !$i.emailVerified));
|
const emailNotConfigured = computed(() => instance.enableEmail && ($i.email == null || !$i.emailVerified));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
INFO,
|
||||||
[symbols.PAGE_INFO]: INFO,
|
[symbols.PAGE_INFO]: INFO,
|
||||||
page,
|
page,
|
||||||
narrow,
|
narrow,
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="cmuxhskf" v-hotkey.global="keymap" v-size="{ min: [800] }">
|
<div>
|
||||||
<XTutorial v-if="$store.reactiveState.tutorial.value != -1" class="tutorial _block"/>
|
<MkHeader></MkHeader>
|
||||||
<XPostForm v-if="$store.reactiveState.showFixedPostForm.value" class="post-form _block" fixed/>
|
<div class="cmuxhskf" v-hotkey.global="keymap" v-size="{ min: [800] }">
|
||||||
|
<XTutorial v-if="$store.reactiveState.tutorial.value != -1" class="tutorial _block"/>
|
||||||
|
<XPostForm v-if="$store.reactiveState.showFixedPostForm.value" class="post-form _block" fixed/>
|
||||||
|
|
||||||
<div class="new" v-if="queue > 0"><button class="_buttonPrimary" @click="top()">{{ $ts.newNoteRecived }}</button></div>
|
<div class="new" v-if="queue > 0"><button class="_buttonPrimary" @click="top()">{{ $ts.newNoteRecived }}</button></div>
|
||||||
<div class="tl _block">
|
<div class="tl _block">
|
||||||
<XTimeline ref="tl" class="tl"
|
<XTimeline ref="tl" class="tl"
|
||||||
:key="src"
|
:key="src"
|
||||||
:src="src"
|
:src="src"
|
||||||
:sound="true"
|
:sound="true"
|
||||||
@before="before()"
|
@before="before()"
|
||||||
@after="after()"
|
@after="after()"
|
||||||
@queue="queueUpdated"
|
@queue="queueUpdated"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,98 +1,118 @@
|
||||||
<template>
|
<template>
|
||||||
<transition name="fade" mode="out-in">
|
<div>
|
||||||
<div class="ftskorzw wide" v-if="user && narrow === false">
|
<MkHeader></MkHeader>
|
||||||
<MkRemoteCaution v-if="user.host != null" :href="user.url"/>
|
|
||||||
|
|
||||||
<div class="banner-container" :style="style">
|
<transition name="fade" mode="out-in">
|
||||||
<div class="banner" ref="banner" :style="style"></div>
|
<div class="ftskorzw wide" v-if="user && narrow === false">
|
||||||
</div>
|
<MkRemoteCaution v-if="user.host != null" :href="user.url"/>
|
||||||
<div class="contents">
|
|
||||||
<div class="side _forceContainerFull_">
|
<div class="banner-container" :style="style">
|
||||||
<MkAvatar class="avatar" :user="user" :disable-preview="true" :show-indicator="true"/>
|
<div class="banner" ref="banner" :style="style"></div>
|
||||||
<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>
|
||||||
<div class="main">
|
<div class="contents">
|
||||||
<div class="actions">
|
<div class="side _forceContainerFull_">
|
||||||
<button @click="menu" class="menu _button"><i class="fas fa-ellipsis-h"></i></button>
|
<MkAvatar class="avatar" :user="user" :disable-preview="true" :show-indicator="true"/>
|
||||||
<MkFollowButton v-if="!$i || $i.id != user.id" :user="user" :inline="true" :transparent="false" :full="true" large class="koudoku"/>
|
<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>
|
||||||
<template v-if="page === 'index'">
|
<div class="main">
|
||||||
<div v-if="user.pinnedNotes.length > 0" class="_gap">
|
<div class="actions">
|
||||||
<XNote v-for="note in user.pinnedNotes" class="note _gap" :note="note" @update:note="pinnedNoteUpdated(note, $event)" :key="note.id" :pinned="true"/>
|
<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>
|
</div>
|
||||||
<div class="_gap">
|
<template v-if="page === 'index'">
|
||||||
<XUserTimeline :user="user"/>
|
<div v-if="user.pinnedNotes.length > 0" class="_gap">
|
||||||
</div>
|
<XNote v-for="note in user.pinnedNotes" class="note _gap" :note="note" @update:note="pinnedNoteUpdated(note, $event)" :key="note.id" :pinned="true"/>
|
||||||
</template>
|
</div>
|
||||||
<XFollowList v-else-if="page === 'following'" type="following" :user="user" class="_gap"/>
|
<div class="_gap">
|
||||||
<XFollowList v-else-if="page === 'followers'" type="followers" :user="user" class="_gap"/>
|
<XUserTimeline :user="user"/>
|
||||||
<XClips v-else-if="page === 'clips'" :user="user" class="_gap"/>
|
</div>
|
||||||
<XPages v-else-if="page === 'pages'" :user="user" class="_gap"/>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="ftskorzw narrow _root" v-else-if="user && narrow === true" v-size="{ max: [500] }">
|
||||||
<div class="ftskorzw narrow _root" v-else-if="user && narrow === true" v-size="{ max: [500] }">
|
<!-- TODO -->
|
||||||
<!-- 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.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="punished" v-if="user.isSilenced"><i class="fas fa-exclamation-triangle" style="margin-right: 8px;"></i> {{ $ts.userSilenced }}</div> -->
|
|
||||||
|
|
||||||
<div class="profile">
|
<div class="profile">
|
||||||
<MkRemoteCaution v-if="user.host != null" :href="user.url" class="warn"/>
|
<MkRemoteCaution v-if="user.host != null" :href="user.url" class="warn"/>
|
||||||
|
|
||||||
<div class="_block main" :key="user.id">
|
<div class="_block main" :key="user.id">
|
||||||
<div class="banner-container" :style="style">
|
<div class="banner-container" :style="style">
|
||||||
<div class="banner" ref="banner" :style="style"></div>
|
<div class="banner" ref="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="$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">
|
<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="$ts.isAdmin" style="color: var(--badge);"><i class="fas fa-bookmark"></i></span>
|
<span v-if="user.isAdmin" :title="$ts.isAdmin" style="color: var(--badge);"><i class="fas fa-bookmark"></i></span>
|
||||||
|
@ -101,92 +121,76 @@
|
||||||
<span v-if="user.isBot" :title="$ts.isBot"><i class="fas fa-robot"></i></span>
|
<span v-if="user.isBot" :title="$ts.isBot"><i class="fas fa-robot"></i></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="followed" v-if="$i && $i.id != user.id && user.isFollowed">{{ $ts.followsYou }}</span>
|
<div class="description">
|
||||||
<div class="actions" v-if="$i">
|
<Mfm v-if="user.description" :text="user.description" :is-note="false" :author="user" :i="$i" :custom-emojis="user.emojis"/>
|
||||||
<button @click="menu" class="menu _button"><i class="fas fa-ellipsis-h"></i></button>
|
<p v-else class="empty">{{ $ts.noAccountDescription }}</p>
|
||||||
<MkFollowButton v-if="$i.id != user.id" :user="user" :inline="true" :transparent="false" :full="true" class="koudoku"/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="fields system">
|
||||||
<MkAvatar class="avatar" :user="user" :disable-preview="true" :show-indicator="true"/>
|
<dl class="field" v-if="user.location">
|
||||||
<div class="title">
|
<dt class="name"><i class="fas fa-map-marker fa-fw"></i> {{ $ts.location }}</dt>
|
||||||
<MkUserName :user="user" :nowrap="false" class="name"/>
|
<dd class="value">{{ user.location }}</dd>
|
||||||
<div class="bottom">
|
</dl>
|
||||||
<span class="username"><MkAcct :user="user" :detail="true" /></span>
|
<dl class="field" v-if="user.birthday">
|
||||||
<span v-if="user.isAdmin" :title="$ts.isAdmin" style="color: var(--badge);"><i class="fas fa-bookmark"></i></span>
|
<dt class="name"><i class="fas fa-birthday-cake fa-fw"></i> {{ $ts.birthday }}</dt>
|
||||||
<span v-if="!user.isAdmin && user.isModerator" :title="$ts.isModerator" style="color: var(--badge);"><i class="far fa-bookmark"></i></span>
|
<dd class="value">{{ user.birthday.replace('-', '/').replace('-', '/') }} ({{ $t('yearsOld', { age }) }})</dd>
|
||||||
<span v-if="user.isLocked" :title="$ts.isLocked"><i class="fas fa-lock"></i></span>
|
</dl>
|
||||||
<span v-if="user.isBot" :title="$ts.isBot"><i class="fas fa-robot"></i></span>
|
<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="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>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="contents">
|
<div class="contents">
|
||||||
<template v-if="page === 'index'">
|
<template v-if="page === 'index'">
|
||||||
<div>
|
<div>
|
||||||
<div v-if="user.pinnedNotes.length > 0" class="_gap">
|
<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"/>
|
<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"/>
|
||||||
</div>
|
</div>
|
||||||
<MkInfo v-else-if="$i && $i.id === user.id">{{ $ts.userPagePinTip }}</MkInfo>
|
<div>
|
||||||
<XPhotos :user="user" :key="user.id"/>
|
<XUserTimeline :user="user"/>
|
||||||
<XActivity :user="user" :key="user.id"/>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
<div>
|
<XFollowList v-else-if="page === 'following'" type="following" :user="user" class="_content _gap"/>
|
||||||
<XUserTimeline :user="user"/>
|
<XFollowList v-else-if="page === 'followers'" type="followers" :user="user" class="_content _gap"/>
|
||||||
</div>
|
<XClips v-else-if="page === 'clips'" :user="user" class="_gap"/>
|
||||||
</template>
|
<XPages v-else-if="page === 'pages'" :user="user" class="_gap"/>
|
||||||
<XFollowList v-else-if="page === 'following'" type="following" :user="user" class="_content _gap"/>
|
<XGallery v-else-if="page === 'gallery'" :user="user" class="_gap"/>
|
||||||
<XFollowList v-else-if="page === 'followers'" type="followers" :user="user" class="_content _gap"/>
|
</div>
|
||||||
<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>
|
||||||
</div>
|
<MkError v-else-if="error" @retry="fetch()"/>
|
||||||
<MkError v-else-if="error" @retry="fetch()"/>
|
<MkLoading v-else/>
|
||||||
<MkLoading v-else/>
|
</transition>
|
||||||
</transition>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|
|
@ -101,7 +101,7 @@ import XSidebar from '@client/ui/_common_/sidebar.vue';
|
||||||
import XWidgets from './widgets.vue';
|
import XWidgets from './widgets.vue';
|
||||||
import XCommon from '../_common_/common.vue';
|
import XCommon from '../_common_/common.vue';
|
||||||
import XSide from './side.vue';
|
import XSide from './side.vue';
|
||||||
import XHeader from '../_common_/header.vue';
|
import XHeader from '../../components/global/header.vue';
|
||||||
import XHeaderClock from './header-clock.vue';
|
import XHeaderClock from './header-clock.vue';
|
||||||
import * as os from '@client/os';
|
import * as os from '@client/os';
|
||||||
import { router } from '@client/router';
|
import { router } from '@client/router';
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import XHeader from '../_common_/header.vue';
|
import XHeader from '../../components/global/header.vue';
|
||||||
import * as os from '@client/os';
|
import * as os from '@client/os';
|
||||||
import copyToClipboard from '@client/scripts/copy-to-clipboard';
|
import copyToClipboard from '@client/scripts/copy-to-clipboard';
|
||||||
import { resolve } from '@client/router';
|
import { resolve } from '@client/router';
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import XColumn from './column.vue';
|
import XColumn from './column.vue';
|
||||||
import XNotes from '@client/components/notes.vue';
|
import XNotes from '@client/components/notes.vue';
|
||||||
import XHeader from '@client/ui/_common_/header.vue';
|
|
||||||
import { deckStore } from '@client/ui/deck/deck-store';
|
import { deckStore } from '@client/ui/deck/deck-store';
|
||||||
import * as os from '@client/os';
|
import * as os from '@client/os';
|
||||||
import * as symbols from '@client/symbols';
|
import * as symbols from '@client/symbols';
|
||||||
|
@ -26,7 +25,6 @@ import * as symbols from '@client/symbols';
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
XColumn,
|
XColumn,
|
||||||
XHeader,
|
|
||||||
XNotes
|
XNotes
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import XHeader from './_common_/header.vue';
|
import XHeader from '../components/global/header.vue';
|
||||||
import * as os from '@client/os';
|
import * as os from '@client/os';
|
||||||
import copyToClipboard from '@client/scripts/copy-to-clipboard';
|
import copyToClipboard from '@client/scripts/copy-to-clipboard';
|
||||||
import { resolve } from '@client/router';
|
import { resolve } from '@client/router';
|
||||||
|
|
|
@ -13,9 +13,6 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<main class="main" @contextmenu.stop="onContextmenu" :style="{ background: pageInfo?.bg }">
|
<main class="main" @contextmenu.stop="onContextmenu" :style="{ background: pageInfo?.bg }">
|
||||||
<header class="header" @click="onHeaderClick">
|
|
||||||
<XHeader :info="pageInfo" :back-button="true" @back="back()"/>
|
|
||||||
</header>
|
|
||||||
<div class="content" :class="{ _flat_: !fullView }">
|
<div class="content" :class="{ _flat_: !fullView }">
|
||||||
<router-view v-slot="{ Component }">
|
<router-view v-slot="{ Component }">
|
||||||
<transition :name="$store.state.animation ? 'page' : ''" mode="out-in" @enter="onTransition">
|
<transition :name="$store.state.animation ? 'page' : ''" mode="out-in" @enter="onTransition">
|
||||||
|
@ -67,7 +64,7 @@ import { StickySidebar } from '@client/scripts/sticky-sidebar';
|
||||||
import XSidebar from './default.sidebar.vue';
|
import XSidebar from './default.sidebar.vue';
|
||||||
import XDrawerSidebar from '@client/ui/_common_/sidebar.vue';
|
import XDrawerSidebar from '@client/ui/_common_/sidebar.vue';
|
||||||
import XCommon from './_common_/common.vue';
|
import XCommon from './_common_/common.vue';
|
||||||
import XHeader from './_common_/header.vue';
|
import XHeader from '../components/global/header.vue';
|
||||||
import * as os from '@client/os';
|
import * as os from '@client/os';
|
||||||
import { menuDef } from '@client/menu';
|
import { menuDef } from '@client/menu';
|
||||||
import * as symbols from '@client/symbols';
|
import * as symbols from '@client/symbols';
|
||||||
|
|
|
@ -3,9 +3,6 @@
|
||||||
<XSidebar ref="nav" class="sidebar"/>
|
<XSidebar ref="nav" class="sidebar"/>
|
||||||
|
|
||||||
<div class="contents" ref="contents" @contextmenu.stop="onContextmenu" :style="{ background: pageInfo?.bg }">
|
<div class="contents" ref="contents" @contextmenu.stop="onContextmenu" :style="{ background: pageInfo?.bg }">
|
||||||
<header class="header" ref="header" @click="onHeaderClick" :style="{ background: pageInfo?.bg }">
|
|
||||||
<XHeader :info="pageInfo" :back-button="true" @back="back()"/>
|
|
||||||
</header>
|
|
||||||
<main ref="main">
|
<main ref="main">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<router-view v-slot="{ Component }">
|
<router-view v-slot="{ Component }">
|
||||||
|
@ -58,7 +55,6 @@ import { instanceName } from '@client/config';
|
||||||
import { StickySidebar } from '@client/scripts/sticky-sidebar';
|
import { StickySidebar } from '@client/scripts/sticky-sidebar';
|
||||||
import XSidebar from '@client/ui/_common_/sidebar.vue';
|
import XSidebar from '@client/ui/_common_/sidebar.vue';
|
||||||
import XCommon from './_common_/common.vue';
|
import XCommon from './_common_/common.vue';
|
||||||
import XHeader from './_common_/header.vue';
|
|
||||||
import XSide from './default.side.vue';
|
import XSide from './default.side.vue';
|
||||||
import * as os from '@client/os';
|
import * as os from '@client/os';
|
||||||
import { menuDef } from '@client/menu';
|
import { menuDef } from '@client/menu';
|
||||||
|
@ -70,7 +66,6 @@ export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
XCommon,
|
XCommon,
|
||||||
XSidebar,
|
XSidebar,
|
||||||
XHeader,
|
|
||||||
XWidgets: defineAsyncComponent(() => import('./universal.widgets.vue')),
|
XWidgets: defineAsyncComponent(() => import('./universal.widgets.vue')),
|
||||||
XSide, // NOTE: dynamic importするとAsyncComponentWrapperが間に入るせいでref取得できなくて面倒になる
|
XSide, // NOTE: dynamic importするとAsyncComponentWrapperが間に入るせいでref取得できなくて面倒になる
|
||||||
},
|
},
|
||||||
|
@ -153,7 +148,6 @@ export default defineComponent({
|
||||||
this.navHidden = navWidth === 0;
|
this.navHidden = navWidth === 0;
|
||||||
if (this.$refs.contents == null) return;
|
if (this.$refs.contents == null) return;
|
||||||
const width = this.$refs.contents.offsetWidth;
|
const width = this.$refs.contents.offsetWidth;
|
||||||
if (this.$refs.header) this.$refs.header.style.width = `${width}px`;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
showNav() {
|
showNav() {
|
||||||
|
@ -243,7 +237,6 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
|
|
||||||
.mk-app {
|
.mk-app {
|
||||||
$header-height: 58px; // TODO: どこかに集約したい
|
|
||||||
$ui-font-size: 1em; // TODO: どこかに集約したい
|
$ui-font-size: 1em; // TODO: どこかに集約したい
|
||||||
$widgets-hide-threshold: 1090px;
|
$widgets-hide-threshold: 1090px;
|
||||||
|
|
||||||
|
@ -263,37 +256,11 @@ export default defineComponent({
|
||||||
> .contents {
|
> .contents {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
--stickyTop: #{$header-height};
|
|
||||||
padding-top: $header-height;
|
|
||||||
background: var(--panel);
|
background: var(--panel);
|
||||||
|
|
||||||
> .header {
|
|
||||||
position: fixed;
|
|
||||||
z-index: 1000;
|
|
||||||
top: 0;
|
|
||||||
height: $header-height;
|
|
||||||
width: 100%;
|
|
||||||
line-height: $header-height;
|
|
||||||
text-align: center;
|
|
||||||
font-weight: bold;
|
|
||||||
//background-color: var(--panel);
|
|
||||||
-webkit-backdrop-filter: var(--blur, blur(32px));
|
|
||||||
backdrop-filter: var(--blur, blur(32px));
|
|
||||||
background-color: var(--header);
|
|
||||||
border-bottom: solid 0.5px var(--divider);
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
> main {
|
> main {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|
||||||
> .content {
|
|
||||||
> * {
|
|
||||||
// ほんとは単に calc(100vh - #{$header-height}) と書きたいところだが... https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
|
|
||||||
min-height: calc((var(--vh, 1vh) * 100) - #{$header-height});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .spacer {
|
> .spacer {
|
||||||
height: 82px;
|
height: 82px;
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, defineAsyncComponent } from 'vue';
|
import { defineComponent, defineAsyncComponent } from 'vue';
|
||||||
import { host } from '@client/config';
|
import { host } from '@client/config';
|
||||||
import XHeader from './_common_/header.vue';
|
import XHeader from '../components/global/header.vue';
|
||||||
import XCommon from './_common_/common.vue';
|
import XCommon from './_common_/common.vue';
|
||||||
import * as symbols from '@client/symbols';
|
import * as symbols from '@client/symbols';
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue