Skip to content
Snippets Groups Projects
Commit c70e56dd authored by syuilo's avatar syuilo
Browse files

wip

parent df136a7f
No related branches found
No related tags found
No related merge requests found
<mk-user-page>
<mk-ui ref="ui">
<mk-user ref="user" user={ parent.user } page={ parent.opts.page }/>
</mk-ui>
<style lang="stylus" scoped>
:scope
display block
</style>
<script lang="typescript">
import Progress from '../../../common/scripts/loading';
this.user = this.opts.user;
this.on('mount', () => {
Progress.start();
this.$refs.ui.refs.user.on('user-fetched', user => {
Progress.set(0.5);
document.title = user.name + ' | Misskey';
});
this.$refs.ui.refs.user.on('loaded', () => {
Progress.done();
});
});
</script>
</mk-user-page>
This diff is collapsed.
<template>
<div class="mk-user-followers-you-know">
<p class="title">%fa:users%%i18n:desktop.tags.mk-user.followers-you-know.title%</p>
<p class="initializing" v-if="initializing">%fa:spinner .pulse .fw%%i18n:desktop.tags.mk-user.followers-you-know.loading%<mk-ellipsis/></p>
<div v-if="!initializing && users.length > 0">
<template each={ user in users }>
<a href={ '/' + user.username }><img src={ user.avatar_url + '?thumbnail&size=64' } alt={ user.name }/></a>
</template>
</div>
<p class="empty" v-if="!initializing && users.length == 0">%i18n:desktop.tags.mk-user.followers-you-know.no-users%</p>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
props: ['user'],
data() {
return {
users: [],
fetching: true
};
},
mounted() {
this.$root.$data.os.api('users/followers', {
user_id: this.user.id,
iknow: true,
limit: 16
}).then(x => {
this.fetching = false;
this.users = x.users;
});
}
});
</script>
<style lang="stylus" scoped>
.mk-user-followers-you-know
background #fff
border solid 1px rgba(0, 0, 0, 0.075)
border-radius 6px
> .title
z-index 1
margin 0
padding 0 16px
line-height 42px
font-size 0.9em
font-weight bold
color #888
box-shadow 0 1px rgba(0, 0, 0, 0.07)
> i
margin-right 4px
> div
padding 8px
> a
display inline-block
margin 4px
> img
width 48px
height 48px
vertical-align bottom
border-radius 100%
> .initializing
> .empty
margin 0
padding 16px
text-align center
color #aaa
> i
margin-right 4px
</style>
<template>
<div class="mk-user-friends">
<p class="title">%fa:users%%i18n:desktop.tags.mk-user.frequently-replied-users.title%</p>
<p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:desktop.tags.mk-user.frequently-replied-users.loading%<mk-ellipsis/></p>
<div class="user" v-if="!fetching && users.length != 0" each={ _user in users }>
<a class="avatar-anchor" href={ '/' + _user.username }>
<img class="avatar" src={ _user.avatar_url + '?thumbnail&size=42' } alt="" data-user-preview={ _user.id }/>
</a>
<div class="body">
<a class="name" href={ '/' + _user.username } data-user-preview={ _user.id }>{ _user.name }</a>
<p class="username">@{ _user.username }</p>
</div>
<mk-follow-button user={ _user }/>
</div>
<p class="empty" v-if="!fetching && users.length == 0">%i18n:desktop.tags.mk-user.frequently-replied-users.no-users%</p>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
props: ['user'],
data() {
return {
users: [],
fetching: true
};
},
mounted() {
this.$root.$data.os.api('users/get_frequently_replied_users', {
user_id: this.user.id,
limit: 4
}).then(docs => {
this.fetching = false;
this.users = docs.map(doc => doc.user);
});
}
});
</script>
<style lang="stylus" scoped>
.mk-user-friends
background #fff
border solid 1px rgba(0, 0, 0, 0.075)
border-radius 6px
> .title
z-index 1
margin 0
padding 0 16px
line-height 42px
font-size 0.9em
font-weight bold
color #888
box-shadow 0 1px rgba(0, 0, 0, 0.07)
> i
margin-right 4px
> .initializing
> .empty
margin 0
padding 16px
text-align center
color #aaa
> i
margin-right 4px
> .user
padding 16px
border-bottom solid 1px #eee
&:last-child
border-bottom none
&:after
content ""
display block
clear both
> .avatar-anchor
display block
float left
margin 0 12px 0 0
> .avatar
display block
width 42px
height 42px
margin 0
border-radius 8px
vertical-align bottom
> .body
float left
width calc(100% - 54px)
> .name
margin 0
font-size 16px
line-height 24px
color #555
> .username
display block
margin 0
font-size 15px
line-height 16px
color #ccc
> mk-follow-button
position absolute
top 16px
right 16px
</style>
<template>
<div class="mk-user-header" :data-is-dark-background="user.banner_url != null">
<div class="banner-container" :style="user.banner_url ? `background-image: url(${user.banner_url}?thumbnail&size=2048)` : ''">
<div class="banner" ref="banner" :style="user.banner_url ? `background-image: url(${user.banner_url}?thumbnail&size=2048)` : ''" @click="onBannerClick"></div>
</div>
<div class="fade"></div>
<div class="container">
<img class="avatar" :src="`${user.avatar_url}?thumbnail&size=150`" alt="avatar"/>
<div class="title">
<p class="name">{{ user.name }}</p>
<p class="username">@{{ user.username }}</p>
<p class="location" v-if="user.profile.location">%fa:map-marker%{{ user.profile.location }}</p>
</div>
<footer>
<a :href="`/${user.username}`" :data-active="$parent.page == 'home'">%fa:home%概要</a>
<a :href="`/${user.username}/media`" :data-active="$parent.page == 'media'">%fa:image%メディア</a>
<a :href="`/${user.username}/graphs`" :data-active="$parent.page == 'graphs'">%fa:chart-bar%グラフ</a>
</footer>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import updateBanner from '../../../scripts/update-banner';
export default Vue.extend({
props: ['user'],
mounted() {
window.addEventListener('load', this.onScroll);
window.addEventListener('scroll', this.onScroll);
window.addEventListener('resize', this.onScroll);
},
beforeDestroy() {
window.removeEventListener('load', this.onScroll);
window.removeEventListener('scroll', this.onScroll);
window.removeEventListener('resize', this.onScroll);
},
methods: {
onScroll() {
const banner = this.$refs.banner as any;
const top = window.scrollY;
const z = 1.25; // 奥行き(小さいほど奥)
const pos = -(top / z);
banner.style.backgroundPosition = `center calc(50% - ${pos}px)`;
const blur = top / 32
if (blur <= 10) banner.style.filter = `blur(${blur}px)`;
},
onBannerClick() {
if (!this.$root.$data.os.isSignedIn || this.$root.$data.os.i.id != this.user.id) return;
updateBanner(this.$root.$data.os.i, i => {
this.user.banner_url = i.banner_url;
});
}
}
});
</script>
<style lang="stylus" scoped>
.mk-user-header
$banner-height = 320px
$footer-height = 58px
overflow hidden
background #f7f7f7
box-shadow 0 1px 1px rgba(0, 0, 0, 0.075)
&[data-is-dark-background]
> .banner-container
> .banner
background-color #383838
> .fade
background linear-gradient(transparent, rgba(0, 0, 0, 0.7))
> .container
> .title
color #fff
> .name
text-shadow 0 0 8px #000
> .banner-container
height $banner-height
overflow hidden
background-size cover
background-position center
> .banner
height 100%
background-color #f5f5f5
background-size cover
background-position center
> .fade
$fade-hight = 78px
position absolute
top ($banner-height - $fade-hight)
left 0
width 100%
height $fade-hight
> .container
max-width 1200px
margin 0 auto
> .avatar
display block
position absolute
bottom 16px
left 16px
z-index 2
width 160px
height 160px
margin 0
border solid 3px #fff
border-radius 8px
box-shadow 1px 1px 3px rgba(0, 0, 0, 0.2)
> .title
position absolute
bottom $footer-height
left 0
width 100%
padding 0 0 8px 195px
color #656565
font-family '游ゴシック', 'YuGothic', 'ヒラギノ角ゴ ProN W3', 'Hiragino Kaku Gothic ProN', 'Meiryo', 'メイリオ', sans-serif
> .name
display block
margin 0
line-height 40px
font-weight bold
font-size 2em
> .username
> .location
display inline-block
margin 0 16px 0 0
line-height 20px
opacity 0.8
> i
margin-right 4px
> footer
z-index 1
height $footer-height
padding-left 195px
> a
display inline-block
margin 0
padding 0 16px
height $footer-height
line-height $footer-height
color #555
&[data-active]
border-bottom solid 4px $theme-color
> i
margin-right 6px
> button
display block
position absolute
top 0
right 0
margin 8px
padding 0
width $footer-height - 16px
line-height $footer-height - 16px - 2px
font-size 1.2em
color #777
border solid 1px #eee
border-radius 4px
&:hover
color #555
border solid 1px #ddd
</style>
<template>
<div class="mk-user-home">
<div>
<div ref="left">
<mk-user-profile :user="user"/>
<mk-user-photos :user="user"/>
<mk-user-followers-you-know v-if="$root.$data.os.isSignedIn && $root.$data.os.i.id != user.id" :user="user"/>
<p>%i18n:desktop.tags.mk-user.last-used-at%: <b><mk-time :time="user.last_used_at"/></b></p>
</div>
</div>
<main>
<mk-post-detail v-if="user.pinned_post" :post="user.pinned_post" compact/>
<mk-user-timeline ref="tl" :user="user"/>
</main>
<div>
<div ref="right">
<mk-calendar-widget @warp="warp" :start="new Date(user.created_at)"/>
<mk-activity-widget :user="user"/>
<mk-user-friends :user="user"/>
<div class="nav"><mk-nav-links/></div>
</div>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
props: ['user'],
methods: {
warp(date) {
(this.$refs.tl as any).warp(date);
}
}
});
</script>
<style lang="stylus" scoped>
.mk-user-home
display flex
justify-content center
margin 0 auto
max-width 1200px
> main
> div > div
> *:not(:last-child)
margin-bottom 16px
> main
padding 16px
width calc(100% - 275px * 2)
> mk-user-timeline
border solid 1px rgba(0, 0, 0, 0.075)
border-radius 6px
> div
width 275px
margin 0
&:first-child > div
padding 16px 0 16px 16px
> p
display block
margin 0
padding 0 12px
text-align center
font-size 0.8em
color #aaa
&:last-child > div
padding 16px 16px 16px 0
> .nav
padding 16px
font-size 12px
color #aaa
background #fff
border solid 1px rgba(0, 0, 0, 0.075)
border-radius 6px
a
color #999
i
color #ccc
</style>
<template>
<div class="mk-user-photos">
<p class="title">%fa:camera%%i18n:desktop.tags.mk-user.photos.title%</p>
<p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:desktop.tags.mk-user.photos.loading%<mk-ellipsis/></p>
<div class="stream" v-if="!fetching && images.length > 0">
<div v-for="image in images" :key="image.id"
class="img"
:style="`background-image: url(${image.url}?thumbnail&size=256)`"
></div>
</div>
<p class="empty" v-if="!fetching && images.length == 0">%i18n:desktop.tags.mk-user.photos.no-photos%</p>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
props: ['user'],
data() {
return {
images: [],
fetching: true
};
},
mounted() {
this.$root.$data.os.api('users/posts', {
user_id: this.user.id,
with_media: true,
limit: 9
}).then(posts => {
this.fetching = false;
posts.forEach(post => {
post.media.forEach(media => {
if (this.images.length < 9) this.images.push(media);
});
});
});
}
});
</script>
<style lang="stylus" scoped>
.mk-user-photos
background #fff
border solid 1px rgba(0, 0, 0, 0.075)
border-radius 6px
> .title
z-index 1
margin 0
padding 0 16px
line-height 42px
font-size 0.9em
font-weight bold
color #888
box-shadow 0 1px rgba(0, 0, 0, 0.07)
> i
margin-right 4px
> .stream
display -webkit-flex
display -moz-flex
display -ms-flex
display flex
justify-content center
flex-wrap wrap
padding 8px
> .img
flex 1 1 33%
width 33%
height 80px
background-position center center
background-size cover
background-clip content-box
border solid 2px transparent
> .initializing
> .empty
margin 0
padding 16px
text-align center
color #aaa
> i
margin-right 4px
</style>
<template>
<div class="mk-user-profile">
<div class="friend-form" v-if="$root.$data.os.isSignedIn && $root.$data.os.i.id != user.id">
<mk-follow-button :user="user" size="big"/>
<p class="followed" v-if="user.is_followed">%i18n:desktop.tags.mk-user.follows-you%</p>
<p v-if="user.is_muted">%i18n:desktop.tags.mk-user.muted% <a @click="unmute">%i18n:desktop.tags.mk-user.unmute%</a></p>
<p v-if="!user.is_muted"><a @click="mute">%i18n:desktop.tags.mk-user.mute%</a></p>
</div>
<div class="description" v-if="user.description">{{ user.description }}</div>
<div class="birthday" v-if="user.profile.birthday">
<p>%fa:birthday-cake%{{ user.profile.birthday.replace('-', '').replace('-', '') + '' }} ({{ age }}歳)</p>
</div>
<div class="twitter" v-if="user.twitter">
<p>%fa:B twitter%<a :href="`https://twitter.com/${user.twitter.screen_name}`" target="_blank">@{{ user.twitter.screen_name }}</a></p>
</div>
<div class="status">
<p class="posts-count">%fa:angle-right%<a>{{ user.posts_count }}</a><b>投稿</b></p>
<p class="following">%fa:angle-right%<a @click="showFollowing">{{ user.following_count }}</a>人を<b>フォロー</b></p>
<p class="followers">%fa:angle-right%<a @click="showFollowers">{{ user.followers_count }}</a>人の<b>フォロワー</b></p>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
const age = require('s-age');
export default Vue.extend({
props: ['user'],
computed: {
age(): number {
return age(this.user.profile.birthday);
}
},
methods: {
showFollowing() {
document.body.appendChild(new MkUserFollowingWindow({
parent: this,
propsData: {
user: this.user
}
}).$mount().$el);
},
showFollowers() {
document.body.appendChild(new MkUserFollowersWindow({
parent: this,
propsData: {
user: this.user
}
}).$mount().$el);
},
mute() {
this.$root.$data.os.api('mute/create', {
user_id: this.user.id
}).then(() => {
this.user.is_muted = true;
}, e => {
alert('error');
});
},
unmute() {
this.$root.$data.os.api('mute/delete', {
user_id: this.user.id
}).then(() => {
this.user.is_muted = false;
}, e => {
alert('error');
});
}
}
});
</script>
<style lang="stylus" scoped>
.mk-user-profile
background #fff
border solid 1px rgba(0, 0, 0, 0.075)
border-radius 6px
> *:first-child
border-top none !important
> .friend-form
padding 16px
border-top solid 1px #eee
> mk-big-follow-button
width 100%
> .followed
margin 12px 0 0 0
padding 0
text-align center
line-height 24px
font-size 0.8em
color #71afc7
background #eefaff
border-radius 4px
> .description
padding 16px
color #555
border-top solid 1px #eee
> .birthday
padding 16px
color #555
border-top solid 1px #eee
> p
margin 0
> i
margin-right 8px
> .twitter
padding 16px
color #555
border-top solid 1px #eee
> p
margin 0
> i
margin-right 8px
> .status
padding 16px
color #555
border-top solid 1px #eee
> p
margin 8px 0
> i
margin-left 8px
margin-right 8px
</style>
<template>
<mk-ui>
<div class="user" v-if="!fetching">
<mk-user-header :user="user"/>
<mk-user-home v-if="page == 'home'" :user="user"/>
<mk-user-graphs v-if="page == 'graphs'" :user="user"/>
</div>
</mk-ui>
</template>
<script lang="ts">
import Vue from 'vue';
import Progress from '../../../common/scripts/loading';
export default Vue.extend({
props: {
username: {
type: String
},
page: {
default: 'home'
}
},
data() {
return {
fetching: true,
user: null
};
},
mounted() {
Progress.start();
this.$root.$data.os.api('users/show', {
username: this.username
}).then(user => {
this.fetching = false;
this.user = user;
Progress.done();
document.title = user.name + ' | Misskey';
});
}
});
</script>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment