Skip to content
Snippets Groups Projects
Commit 7c30b94c authored by こぴなたみぽ's avatar こぴなたみぽ
Browse files

wip

parent 697cbc3a
No related branches found
No related tags found
No related merge requests found
<mk-user-timeline>
<header>
<span data-is-active={ mode == 'default' } @click="setMode.bind(this, 'default')">投稿</span><span data-is-active={ mode == 'with-replies' } @click="setMode.bind(this, 'with-replies')">投稿と返信</span>
</header>
<div class="loading" v-if="isLoading">
<mk-ellipsis-icon/>
</div>
<p class="empty" v-if="isEmpty">%fa:R comments%このユーザーはまだ何も投稿していないようです。</p>
<mk-timeline ref="timeline">
<yield to="footer">
<template v-if="!parent.moreLoading">%fa:moon%</template>
<template v-if="parent.moreLoading">%fa:spinner .pulse .fw%</template>
</yield/>
</mk-timeline>
<style lang="stylus" scoped>
:scope
display block
background #fff
> header
padding 8px 16px
border-bottom solid 1px #eee
> span
margin-right 16px
line-height 27px
font-size 18px
color #555
&:not([data-is-active])
color $theme-color
cursor pointer
&:hover
text-decoration underline
> .loading
padding 64px 0
> .empty
display block
margin 0 auto
padding 32px
max-width 400px
text-align center
color #999
> [data-fa]
display block
margin-bottom 16px
font-size 3em
color #ccc
</style>
<script lang="typescript">
import isPromise from '../../common/scripts/is-promise';
this.mixin('api');
this.user = null;
this.userPromise = isPromise(this.opts.user)
? this.opts.user
: Promise.resolve(this.opts.user);
this.isLoading = true;
this.isEmpty = false;
this.moreLoading = false;
this.unreadCount = 0;
this.mode = 'default';
this.on('mount', () => {
document.addEventListener('keydown', this.onDocumentKeydown);
window.addEventListener('scroll', this.onScroll);
this.userPromise.then(user => {
this.update({
user: user
});
this.fetch(() => this.$emit('loaded'));
});
});
this.on('unmount', () => {
document.removeEventListener('keydown', this.onDocumentKeydown);
window.removeEventListener('scroll', this.onScroll);
});
this.onDocumentKeydown = e => {
if (e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA') {
if (e.which == 84) { // [t]
this.$refs.timeline.focus();
}
}
};
this.fetch = cb => {
this.$root.$data.os.api('users/posts', {
user_id: this.user.id,
until_date: this.date ? this.date.getTime() : undefined,
with_replies: this.mode == 'with-replies'
}).then(posts => {
this.update({
isLoading: false,
isEmpty: posts.length == 0
});
this.$refs.timeline.setPosts(posts);
if (cb) cb();
});
};
this.more = () => {
if (this.moreLoading || this.isLoading || this.$refs.timeline.posts.length == 0) return;
this.update({
moreLoading: true
});
this.$root.$data.os.api('users/posts', {
user_id: this.user.id,
with_replies: this.mode == 'with-replies',
until_id: this.$refs.timeline.tail().id
}).then(posts => {
this.update({
moreLoading: false
});
this.$refs.timeline.prependPosts(posts);
});
};
this.onScroll = () => {
const current = window.scrollY + window.innerHeight;
if (current > document.body.offsetHeight - 16/*遊び*/) {
this.more();
}
};
this.setMode = mode => {
this.update({
mode: mode
});
this.fetch();
};
this.warp = date => {
this.update({
date: date
});
this.fetch();
};
</script>
</mk-user-timeline>
<template>
<div class="mk-user-timeline">
<header>
<span :data-is-active="mode == 'default'" @click="mode = 'default'">投稿</span>
<span :data-is-active="mode == 'with-replies'" @click="mode = 'with-replies'">投稿と返信</span>
</header>
<div class="loading" v-if="fetching">
<mk-ellipsis-icon/>
</div>
<p class="empty" v-if="empty">%fa:R comments%このユーザーはまだ何も投稿していないようです。</p>
<mk-posts ref="timeline" :posts="posts">
<div slot="footer">
<template v-if="!moreFetching">%fa:moon%</template>
<template v-if="moreFetching">%fa:spinner .pulse .fw%</template>
</div>
</mk-posts>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
props: ['user'],
data() {
return {
fetching: true,
moreFetching: false,
mode: 'default',
unreadCount: 0,
posts: [],
date: null
};
},
watch: {
mode() {
this.fetch();
}
},
computed: {
empty(): boolean {
return this.posts.length == 0;
}
},
mounted() {
document.addEventListener('keydown', this.onDocumentKeydown);
window.addEventListener('scroll', this.onScroll);
this.fetch(() => this.$emit('loaded'));
},
beforeDestroy() {
document.removeEventListener('keydown', this.onDocumentKeydown);
window.removeEventListener('scroll', this.onScroll);
},
methods: {
onDocumentKeydown(e) {
if (e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA') {
if (e.which == 84) { // [t]
(this.$refs.timeline as any).focus();
}
}
},
fetch(cb?) {
this.$root.$data.os.api('users/posts', {
user_id: this.user.id,
until_date: this.date ? this.date.getTime() : undefined,
with_replies: this.mode == 'with-replies'
}).then(posts => {
this.fetching = false;
this.posts = posts;
if (cb) cb();
});
},
more() {
if (this.moreFetching || this.fetching || this.posts.length == 0) return;
this.moreFetching = true;
this.$root.$data.os.api('users/posts', {
user_id: this.user.id,
with_replies: this.mode == 'with-replies',
until_id: this.posts[this.posts.length - 1].id
}).then(posts => {
this.moreFetching = false;
this.posts = this.posts.concat(posts);
});
},
onScroll() {
const current = window.scrollY + window.innerHeight;
if (current > document.body.offsetHeight - 16/*遊び*/) {
this.more();
}
}
}
});
</script>
<style lang="stylus" scoped>
.mk-user-timeline
background #fff
> header
padding 8px 16px
border-bottom solid 1px #eee
> span
margin-right 16px
line-height 27px
font-size 18px
color #555
&:not([data-is-active])
color $theme-color
cursor pointer
&:hover
text-decoration underline
> .loading
padding 64px 0
> .empty
display block
margin 0 auto
padding 32px
max-width 400px
text-align center
color #999
> [data-fa]
display block
margin-bottom 16px
font-size 3em
color #ccc
</style>
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