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

wip

parent 284b2192
No related branches found
No related tags found
No related merge requests found
<mk-home-timeline>
<mk-init-following v-if="noFollowing" />
<mk-timeline ref="timeline" init={ init } more={ more } empty={ '%i18n:mobile.tags.mk-home-timeline.empty-timeline%' }/>
<style lang="stylus" scoped>
:scope
display block
> mk-init-following
margin-bottom 8px
</style>
<script lang="typescript">
this.mixin('i');
this.mixin('api');
this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.noFollowing = this.I.following_count == 0;
this.init = new Promise((res, rej) => {
this.api('posts/timeline').then(posts => {
res(posts);
this.$emit('loaded');
});
});
this.fetch = () => {
this.api('posts/timeline').then(posts => {
this.$refs.timeline.setPosts(posts);
});
};
this.on('mount', () => {
this.connection.on('post', this.onStreamPost);
this.connection.on('follow', this.onStreamFollow);
this.connection.on('unfollow', this.onStreamUnfollow);
});
this.on('unmount', () => {
this.connection.off('post', this.onStreamPost);
this.connection.off('follow', this.onStreamFollow);
this.connection.off('unfollow', this.onStreamUnfollow);
this.stream.dispose(this.connectionId);
});
this.more = () => {
return this.api('posts/timeline', {
until_id: this.$refs.timeline.tail().id
});
};
this.onStreamPost = post => {
this.update({
isEmpty: false
});
this.$refs.timeline.addPost(post);
};
this.onStreamFollow = () => {
this.fetch();
};
this.onStreamUnfollow = () => {
this.fetch();
};
</script>
</mk-home-timeline>
<mk-timeline>
<div class="init" v-if="init">
%fa:spinner .pulse%%i18n:common.loading%
</div>
<div class="empty" v-if="!init && posts.length == 0">
%fa:R comments%{ opts.empty || '%i18n:mobile.tags.mk-timeline.empty%' }
</div>
<template each={ post, i in posts }>
<mk-timeline-post post={ post }/>
<p class="date" v-if="i != posts.length - 1 && post._date != posts[i + 1]._date">
<span>%fa:angle-up%{ post._datetext }</span>
<span>%fa:angle-down%{ posts[i + 1]._datetext }</span>
</p>
</template>
<footer v-if="!init">
<button v-if="canFetchMore" @click="more" disabled={ fetching }>
<span v-if="!fetching">%i18n:mobile.tags.mk-timeline.load-more%</span>
<span v-if="fetching">%i18n:common.loading%<mk-ellipsis/></span>
</button>
</footer>
<style lang="stylus" scoped>
:scope
display block
background #fff
border-radius 8px
box-shadow 0 0 0 1px rgba(0, 0, 0, 0.2)
> .init
padding 64px 0
text-align center
color #999
> [data-fa]
margin-right 4px
> .empty
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
> .date
display block
margin 0
line-height 32px
text-align center
font-size 0.9em
color #aaa
background #fdfdfd
border-bottom solid 1px #eaeaea
span
margin 0 16px
[data-fa]
margin-right 8px
> footer
text-align center
border-top solid 1px #eaeaea
border-bottom-left-radius 4px
border-bottom-right-radius 4px
> button
margin 0
padding 16px
width 100%
color $theme-color
border-radius 0 0 8px 8px
&:disabled
opacity 0.7
</style>
<script lang="typescript">
this.posts = [];
this.init = true;
this.fetching = false;
this.canFetchMore = true;
this.on('mount', () => {
this.opts.init.then(posts => {
this.init = false;
this.setPosts(posts);
});
});
this.on('update', () => {
this.posts.forEach(post => {
const date = new Date(post.created_at).getDate();
const month = new Date(post.created_at).getMonth() + 1;
post._date = date;
post._datetext = `${month}月 ${date}日`;
});
});
this.more = () => {
if (this.init || this.fetching || this.posts.length == 0) return;
this.update({
fetching: true
});
this.opts.more().then(posts => {
this.fetching = false;
this.prependPosts(posts);
});
};
this.setPosts = posts => {
this.update({
posts: posts
});
};
this.prependPosts = posts => {
posts.forEach(post => {
this.posts.push(post);
this.update();
});
}
this.addPost = post => {
this.posts.unshift(post);
this.update();
};
this.tail = () => {
return this.posts[this.posts.length - 1];
};
</script>
</mk-timeline>
<mk-timeline-post :class="{ repost: isRepost }">
<div class="reply-to" v-if="p.reply">
......
<template>
<div class="mk-posts">
<slot name="head"></slot>
<template v-for="(post, i) in _posts">
<mk-posts-post :post="post" :key="post.id"/>
<p class="date" :key="post._datetext" v-if="i != posts.length - 1 && post._date != _posts[i + 1]._date">
<span>%fa:angle-up%{{ post._datetext }}</span>
<span>%fa:angle-down%{{ _posts[i + 1]._datetext }}</span>
</p>
</template>
<slot name="tail"></slot>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
props: {
posts: {
type: Array,
default: () => []
}
},
computed: {
_posts(): any[] {
return (this.posts as any).map(post => {
const date = new Date(post.created_at).getDate();
const month = new Date(post.created_at).getMonth() + 1;
post._date = date;
post._datetext = `${month}${date}日`;
return post;
});
}
}
});
</script>
<style lang="stylus" scoped>
.mk-posts
background #fff
border-radius 8px
box-shadow 0 0 0 1px rgba(0, 0, 0, 0.2)
> .init
padding 64px 0
text-align center
color #999
> [data-fa]
margin-right 4px
> .empty
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
> .date
display block
margin 0
line-height 32px
text-align center
font-size 0.9em
color #aaa
background #fdfdfd
border-bottom solid 1px #eaeaea
span
margin 0 16px
[data-fa]
margin-right 8px
> footer
text-align center
border-top solid 1px #eaeaea
border-bottom-left-radius 4px
border-bottom-right-radius 4px
> button
margin 0
padding 16px
width 100%
color $theme-color
border-radius 0 0 8px 8px
&:disabled
opacity 0.7
</style>
<template>
<div class="mk-timeline">
<mk-posts ref="timeline" :posts="posts">
<mk-friends-maker v-if="alone" slot="head"/>
<div class="init" v-if="fetching">
%fa:spinner .pulse%%i18n:common.loading%
</div>
<div class="empty" v-if="!fetching && posts.length == 0">
%fa:R comments%
%i18n:mobile.tags.mk-home-timeline.empty-timeline%
</div>
<button v-if="canFetchMore" @click="more" :disabled="fetching" slot="tail">
<span v-if="!fetching">%i18n:mobile.tags.mk-timeline.load-more%</span>
<span v-if="fetching">%i18n:common.loading%<mk-ellipsis/></span>
</button>
</mk-posts>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
props: {
date: {
type: Date,
required: false
}
},
data() {
return {
fetching: true,
moreFetching: false,
posts: [],
connection: null,
connectionId: null
};
},
computed: {
alone(): boolean {
return this.$root.$data.os.i.following_count == 0;
}
},
mounted() {
this.connection = this.$root.$data.os.stream.getConnection();
this.connectionId = this.$root.$data.os.stream.use();
this.connection.on('post', this.onPost);
this.connection.on('follow', this.onChangeFollowing);
this.connection.on('unfollow', this.onChangeFollowing);
this.fetch();
},
beforeDestroy() {
this.connection.off('post', this.onPost);
this.connection.off('follow', this.onChangeFollowing);
this.connection.off('unfollow', this.onChangeFollowing);
this.$root.$data.os.stream.dispose(this.connectionId);
},
methods: {
fetch(cb?) {
this.fetching = true;
this.$root.$data.os.api('posts/timeline', {
until_date: this.date ? (this.date as any).getTime() : undefined
}).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('posts/timeline', {
until_id: this.posts[this.posts.length - 1].id
}).then(posts => {
this.moreFetching = false;
this.posts.unshift(posts);
});
},
onPost(post) {
this.posts.unshift(post);
},
onChangeFollowing() {
this.fetch();
}
}
});
</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