refs #282 Add lazyLoading in account profile timeline

This commit is contained in:
AkiraFukushima 2018-05-11 01:10:30 +09:00
parent f0f3c61a87
commit 10b9dbdb09
4 changed files with 70 additions and 5 deletions

View File

@ -5,7 +5,7 @@
<i class="el-icon-loading" v-show="loading"></i>
<i class="el-icon-close" @click="close"></i>
</div>
<div class="scrollable">
<div id="sidebar_scrollable">
<account-profile v-if="component === 1" v-on:change-loading="changeLoading"></account-profile>
<toot-detail v-if="component === 2"></toot-detail>
</div>
@ -72,7 +72,7 @@ export default {
}
}
.scrollable {
#sidebar_scrollable {
overflow: auto;
height: calc(100% - 30px);
}

View File

@ -3,6 +3,8 @@
<template v-for="message in timeline">
<toot :message="message" :key="message.id" v-on:update="updateToot" v-on:delete="deleteToot"></toot>
</template>
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor">
</div>
</div>
</template>
@ -16,12 +18,22 @@ export default {
components: { Toot },
computed: {
...mapState({
timeline: state => state.TimelineSpace.Contents.SideBar.AccountProfile.Timeline.timeline
timeline: state => state.TimelineSpace.Contents.SideBar.AccountProfile.Timeline.timeline,
lazyLoading: state => state.TimelineSpace.Contents.SideBar.AccountProfile.Timeline.lazyLoading,
backgroundColor: state => state.App.theme.background_color
})
},
created () {
this.load()
},
mounted () {
document.getElementById('sidebar_scrollable').addEventListener('scroll', this.onScroll)
},
destroyed () {
if (document.getElementById('sidebar_scrollable') !== undefined && document.getElementById('sidebar_scrollable') !== null) {
document.getElementById('sidebar_scrollable').removeEventListener('scroll', this.onScroll)
}
},
watch: {
account: function (newAccount, oldAccount) {
this.load()
@ -37,6 +49,23 @@ export default {
})
})
},
onScroll (event) {
// for lazyLoading
if (((event.target.clientHeight + event.target.scrollTop) >= document.getElementById('account_profile').clientHeight - 10) && !this.lazyloading) {
this.$store.dispatch(
'TimelineSpace/Contents/SideBar/AccountProfile/Timeline/lazyFetchTimeline',
{
account: this.account,
last: this.timeline[this.timeline.length - 1]
})
.catch(() => {
this.$message({
message: 'Could not fetch account timeline',
type: 'error'
})
})
}
},
updateToot (message) {
this.$store.commit('TimelineSpace/Contents/SideBar/AccountProfile/Timeline/updateToot', message)
},
@ -48,4 +77,11 @@ export default {
</script>
<style lang="scss" scoped>
.loading-card {
height: 60px;
}
.loading-card:empty {
height: 0;
}
</style>

View File

@ -97,9 +97,9 @@ const Home = {
api_url: rootState.TimelineSpace.account.baseURL + '/api/v1'
})
client.get('/timelines/home', { max_id: last.id, limit: 40 }, (err, data, res) => {
commit('changeLazyLoading', false)
if (err) return reject(err)
commit('insertTimeline', data)
commit('changeLazyLoading', false)
})
})
}

View File

@ -3,12 +3,19 @@ import Mastodon from 'mastodon-api'
const Timeline = {
namespaced: true,
state: {
timeline: []
timeline: [],
lazyLoading: false
},
mutations: {
updateTimeline (state, timeline) {
state.timeline = timeline
},
insertTimeline (state, messages) {
state.timeline = state.timeline.concat(messages)
},
changeLazyLoading (state, value) {
state.lazyLoading = value
},
updateToot (state, message) {
// Replace target message in timeline
state.timeline = state.timeline.map((toot) => {
@ -52,6 +59,28 @@ const Timeline = {
resolve(res)
})
})
},
lazyFetchTimeline ({ state, commit, rootState }, info) {
const last = info.last
if (last === undefined || last === null) {
return null
}
return new Promise((resolve, reject) => {
if (state.lazyLoading) {
return resolve()
}
commit('changeLazyLoading', true)
const client = new Mastodon(
{
access_token: rootState.TimelineSpace.account.accessToken,
api_url: rootState.TimelineSpace.account.baseURL + '/api/v1'
})
client.get(`/accounts/${info.account.id}/statuses`, { max_id: last.id, limit: 40 }, (err, data, res) => {
commit('changeLazyLoading', false)
if (err) return reject(err)
commit('insertTimeline', data)
})
})
}
}
}