refs #915 Stop loading after fetch home timeline
This commit is contained in:
parent
50948a03c3
commit
582e751fba
|
@ -28,6 +28,8 @@ import Contents from './TimelineSpace/Contents'
|
|||
import Modals from './TimelineSpace/Modals'
|
||||
import Mousetrap from 'mousetrap'
|
||||
import ReceiveDrop from './TimelineSpace/ReceiveDrop'
|
||||
import { AccountLoadError } from '@/errors/load'
|
||||
import { TimelineFetchError } from '@/errors/fetch'
|
||||
|
||||
export default {
|
||||
name: 'timeline-space',
|
||||
|
@ -50,9 +52,7 @@ export default {
|
|||
},
|
||||
async created() {
|
||||
this.$store.dispatch('TimelineSpace/Contents/SideBar/close')
|
||||
this.$store.commit('TimelineSpace/changeLoading', true)
|
||||
await this.initialize().finally(() => {
|
||||
this.$store.commit('TimelineSpace/changeLoading', false)
|
||||
this.$store.commit('GlobalHeader/updateChanging', false)
|
||||
})
|
||||
},
|
||||
|
@ -84,33 +84,21 @@ export default {
|
|||
async initialize() {
|
||||
await this.clear()
|
||||
|
||||
this.$store.dispatch('TimelineSpace/watchShortcutEvents')
|
||||
const account = await this.$store.dispatch('TimelineSpace/localAccount', this.$route.params.id).catch(() => {
|
||||
this.$message({
|
||||
message: this.$t('message.account_load_error'),
|
||||
type: 'error'
|
||||
})
|
||||
})
|
||||
this.$store.dispatch('TimelineSpace/SideMenu/fetchLists', account)
|
||||
this.$store.dispatch('TimelineSpace/SideMenu/fetchFollowRequests', account)
|
||||
await this.$store.dispatch('TimelineSpace/loadUnreadNotification', this.$route.params.id)
|
||||
|
||||
// Load timelines
|
||||
await this.$store.dispatch('TimelineSpace/fetchContentsTimelines', account).catch(_ => {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
})
|
||||
})
|
||||
|
||||
await this.$store.dispatch('TimelineSpace/detectPleroma')
|
||||
// Bind streamings
|
||||
await this.$store.dispatch('TimelineSpace/bindStreamings', account)
|
||||
// Start streamings
|
||||
this.$store.dispatch('TimelineSpace/startStreamings', account)
|
||||
|
||||
this.$store.dispatch('TimelineSpace/fetchEmojis', account)
|
||||
this.$store.dispatch('TimelineSpace/fetchInstance', account)
|
||||
try {
|
||||
this.$store.dispatch('TimelineSpace/initLoad', this.$route.params.id)
|
||||
} catch (err) {
|
||||
if (err instanceof AccountLoadError) {
|
||||
this.$message({
|
||||
message: this.$t('message.account_load_error'),
|
||||
type: 'error'
|
||||
})
|
||||
} else if (err instanceof TimelineFetchError) {
|
||||
this.$message({
|
||||
message: this.$t('message.timeline_fetch_error'),
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
handleDrop(e) {
|
||||
e.preventDefault()
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
<template>
|
||||
<div id="contents">
|
||||
<div id="scrollable" :class="openSideBar ? 'timeline-wrapper-with-side-bar' : 'timeline-wrapper'">
|
||||
<router-view></router-view>
|
||||
<div id="contents">
|
||||
<div
|
||||
id="scrollable"
|
||||
:class="openSideBar ? 'timeline-wrapper-with-side-bar' : 'timeline-wrapper'"
|
||||
v-loading="loading"
|
||||
:element-loading-text="$t('message.loading')"
|
||||
element-loading-spinner="el-icon-loading"
|
||||
element-loading-background="rgba(0, 0, 0, 0.8)"
|
||||
>
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
<side-bar :overlaid="modalOpened"></side-bar>
|
||||
</div>
|
||||
<side-bar
|
||||
:overlaid="modalOpened"
|
||||
></side-bar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -19,12 +24,13 @@ export default {
|
|||
SideBar
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
openSideBar: state => state.TimelineSpace.Contents.SideBar.openSideBar
|
||||
...mapState('TimelineSpace/Contents', {
|
||||
loading: state => state.loading
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals', [
|
||||
'modalOpened'
|
||||
])
|
||||
...mapState('TimelineSpace/Contents/SideBar', {
|
||||
openSideBar: state => state.openSideBar
|
||||
}),
|
||||
...mapGetters('TimelineSpace/Modals', ['modalOpened'])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export class TimelineFetchError extends Error {}
|
|
@ -0,0 +1 @@
|
|||
export class AccountLoadError extends Error {}
|
|
@ -12,21 +12,23 @@ import LocalAccount from '~/src/types/localAccount'
|
|||
import { Notify } from '~/src/types/notify'
|
||||
import { RootState } from '@/store'
|
||||
import { UnreadNotification } from '~/src/types/unreadNotification'
|
||||
import { AccountLoadError } from '@/errors/load'
|
||||
import { TimelineFetchError } from '@/errors/fetch'
|
||||
|
||||
declare var Notification: any
|
||||
|
||||
interface MyEmoji {
|
||||
name: string,
|
||||
name: string
|
||||
image: string
|
||||
}
|
||||
|
||||
export interface TimelineSpaceState {
|
||||
account: LocalAccount,
|
||||
loading: boolean,
|
||||
emojis: Array<MyEmoji>,
|
||||
tootMax: number,
|
||||
unreadNotification: UnreadNotification,
|
||||
useWebsocket: boolean,
|
||||
account: LocalAccount
|
||||
loading: boolean
|
||||
emojis: Array<MyEmoji>
|
||||
tootMax: number
|
||||
unreadNotification: UnreadNotification
|
||||
useWebsocket: boolean
|
||||
pleroma: boolean
|
||||
}
|
||||
|
||||
|
@ -76,7 +78,7 @@ const mutations: MutationTree<TimelineSpaceState> = {
|
|||
state.loading = value
|
||||
},
|
||||
[MUTATION_TYPES.UPDATE_EMOJIS]: (state, emojis: Array<Emoji>) => {
|
||||
state.emojis = emojis.map((e) => {
|
||||
state.emojis = emojis.map(e => {
|
||||
return {
|
||||
name: `:${e.shortcode}:`,
|
||||
image: e.url
|
||||
|
@ -102,10 +104,32 @@ const mutations: MutationTree<TimelineSpaceState> = {
|
|||
}
|
||||
|
||||
const actions: ActionTree<TimelineSpaceState, RootState> = {
|
||||
initLoad: async ({ dispatch, commit }, accountId: number): Promise<Account> => {
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, true)
|
||||
dispatch('watchShortcutEvents')
|
||||
const account = await dispatch('localAccount', accountId).catch(_ => {
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, false)
|
||||
throw new AccountLoadError()
|
||||
})
|
||||
|
||||
dispatch('TimelineSpace/SideMenu/fetchLists', account, { root: true })
|
||||
dispatch('TimelineSpace/SideMenu/fetchFollowRequests', account, { root: true })
|
||||
await dispatch('loadUnreadNotification', accountId)
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, false)
|
||||
await dispatch('fetchContentsTimelines', account).catch(_ => {
|
||||
throw new TimelineFetchError()
|
||||
})
|
||||
await dispatch('detectPleroma')
|
||||
await dispatch('bindStreamings', account)
|
||||
dispatch('startStreamings', account)
|
||||
dispatch('fetchEmojis', account)
|
||||
dispatch('fetchInstance', account)
|
||||
return account
|
||||
},
|
||||
// -------------------------------------------------
|
||||
// Accounts
|
||||
// -------------------------------------------------
|
||||
localAccount: ({ dispatch, commit }, id: string): Promise<LocalAccount> => {
|
||||
localAccount: async ({ dispatch, commit }, id: string): Promise<LocalAccount> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
ipcRenderer.send('get-local-account', id)
|
||||
ipcRenderer.once('error-get-local-account', (_, err: Error) => {
|
||||
|
@ -121,7 +145,7 @@ const actions: ActionTree<TimelineSpaceState, RootState> = {
|
|||
commit(MUTATION_TYPES.UPDATE_ACCOUNT, acct)
|
||||
resolve(acct)
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
} else {
|
||||
|
@ -216,7 +240,11 @@ const actions: ActionTree<TimelineSpaceState, RootState> = {
|
|||
})
|
||||
},
|
||||
fetchContentsTimelines: async ({ dispatch, state }) => {
|
||||
await dispatch('TimelineSpace/Contents/Home/fetchTimeline', {}, { root: true })
|
||||
dispatch('TimelineSpace/Contents/changeLoading', true, { root: true })
|
||||
await dispatch('TimelineSpace/Contents/Home/fetchTimeline', {}, { root: true }).finally(() => {
|
||||
dispatch('TimelineSpace/Contents/changeLoading', false, { root: true })
|
||||
})
|
||||
|
||||
await dispatch('TimelineSpace/Contents/Notifications/fetchNotifications', {}, { root: true })
|
||||
await dispatch('TimelineSpace/Contents/Mentions/fetchMentions', {}, { root: true })
|
||||
if (state.unreadNotification.direct) {
|
||||
|
@ -308,7 +336,8 @@ const actions: ActionTree<TimelineSpaceState, RootState> = {
|
|||
},
|
||||
startUserStreaming: ({ state }): Promise<{}> => {
|
||||
// @ts-ignore
|
||||
return new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars
|
||||
return new Promise((resolve, reject) => {
|
||||
// eslint-disable-line no-unused-vars
|
||||
ipcRenderer.send('start-user-streaming', {
|
||||
account: state.account,
|
||||
useWebsocket: state.useWebsocket
|
||||
|
@ -329,7 +358,8 @@ const actions: ActionTree<TimelineSpaceState, RootState> = {
|
|||
},
|
||||
startLocalStreaming: ({ state }) => {
|
||||
// @ts-ignore
|
||||
return new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars
|
||||
return new Promise((resolve, reject) => {
|
||||
// eslint-disable-line no-unused-vars
|
||||
ipcRenderer.send('start-local-streaming', {
|
||||
account: state.account,
|
||||
useWebsocket: state.useWebsocket
|
||||
|
@ -350,7 +380,8 @@ const actions: ActionTree<TimelineSpaceState, RootState> = {
|
|||
},
|
||||
startPublicStreaming: ({ state }) => {
|
||||
// @ts-ignore
|
||||
return new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars
|
||||
return new Promise((resolve, reject) => {
|
||||
// eslint-disable-line no-unused-vars
|
||||
ipcRenderer.send('start-public-streaming', {
|
||||
account: state.account,
|
||||
useWebsocket: state.useWebsocket
|
||||
|
@ -371,7 +402,8 @@ const actions: ActionTree<TimelineSpaceState, RootState> = {
|
|||
},
|
||||
startDirectMessagesStreaming: ({ state }) => {
|
||||
// @ts-ignore
|
||||
return new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars
|
||||
return new Promise((resolve, reject) => {
|
||||
// eslint-disable-line no-unused-vars
|
||||
ipcRenderer.send('start-directmessages-streaming', {
|
||||
account: state.account,
|
||||
useWebsocket: state.useWebsocket
|
||||
|
@ -413,9 +445,9 @@ const actions: ActionTree<TimelineSpaceState, RootState> = {
|
|||
}
|
||||
|
||||
export interface TimelineSpaceModuleState extends TimelineSpaceState {
|
||||
SideMenu: SideMenuState,
|
||||
HeaderMenu: HeaderMenuState,
|
||||
Modals: ModalsModuleState,
|
||||
SideMenu: SideMenuState
|
||||
HeaderMenu: HeaderMenuState
|
||||
Modals: ModalsModuleState
|
||||
Contents: ContentsModuleState
|
||||
}
|
||||
|
||||
|
@ -434,7 +466,7 @@ const TimelineSpace: Module<TimelineSpaceState, RootState> = {
|
|||
|
||||
export default TimelineSpace
|
||||
|
||||
function createNotification (notification: NotificationType, notifyConfig: Notify) {
|
||||
function createNotification(notification: NotificationType, notifyConfig: Notify) {
|
||||
switch (notification.type) {
|
||||
case 'favourite':
|
||||
if (notifyConfig.favourite) {
|
||||
|
@ -471,7 +503,7 @@ function createNotification (notification: NotificationType, notifyConfig: Notif
|
|||
}
|
||||
}
|
||||
|
||||
function username (account: Account) {
|
||||
function username(account: Account) {
|
||||
if (account.display_name !== '') {
|
||||
return account.display_name
|
||||
} else {
|
||||
|
|
|
@ -10,10 +10,12 @@ import Hashtag, { HashtagModuleState } from './Contents/Hashtag'
|
|||
import DirectMessages, { DirectMessagesState } from './Contents/DirectMessages'
|
||||
import FollowRequests, { FollowRequestsState } from './Contents/FollowRequests'
|
||||
import Mentions, { MentionsState } from './Contents/Mentions'
|
||||
import { Module } from 'vuex'
|
||||
import { Module, MutationTree, ActionTree } from 'vuex'
|
||||
import { RootState } from '@/store'
|
||||
|
||||
export interface ContentsState {}
|
||||
export interface ContentsState {
|
||||
loading: boolean
|
||||
}
|
||||
|
||||
export interface ContentsModuleState extends ContentsState {
|
||||
SideBar: SideBarModuleState
|
||||
|
@ -29,7 +31,25 @@ export interface ContentsModuleState extends ContentsState {
|
|||
FollowRequests: FollowRequestsState
|
||||
}
|
||||
|
||||
const state = (): ContentsState => ({})
|
||||
const state = (): ContentsState => ({
|
||||
loading: false
|
||||
})
|
||||
|
||||
export const MUTATION_TYPES = {
|
||||
CHANGE_LOADING: 'changeLoading'
|
||||
}
|
||||
|
||||
const mutations: MutationTree<ContentsState> = {
|
||||
[MUTATION_TYPES.CHANGE_LOADING]: (state, loading: boolean) => {
|
||||
state.loading = loading
|
||||
}
|
||||
}
|
||||
|
||||
const actions: ActionTree<ContentsState, RootState> = {
|
||||
changeLoading: ({ commit }, loading) => {
|
||||
commit(MUTATION_TYPES.CHANGE_LOADING, loading)
|
||||
}
|
||||
}
|
||||
|
||||
const Contents: Module<ContentsState, RootState> = {
|
||||
namespaced: true,
|
||||
|
@ -47,7 +67,9 @@ const Contents: Module<ContentsState, RootState> = {
|
|||
Lists,
|
||||
Hashtag,
|
||||
FollowRequests
|
||||
}
|
||||
},
|
||||
mutations: mutations,
|
||||
actions: actions
|
||||
}
|
||||
|
||||
export default Contents
|
||||
|
|
|
@ -3,12 +3,12 @@ import { Module, MutationTree, ActionTree } from 'vuex'
|
|||
import { RootState } from '@/store'
|
||||
|
||||
export interface HomeState {
|
||||
lazyLoading: boolean,
|
||||
heading: boolean,
|
||||
showReblogs: boolean,
|
||||
showReplies: boolean,
|
||||
timeline: Array<Status>,
|
||||
unreadTimeline: Array<Status>,
|
||||
lazyLoading: boolean
|
||||
heading: boolean
|
||||
showReblogs: boolean
|
||||
showReplies: boolean
|
||||
timeline: Array<Status>
|
||||
unreadTimeline: Array<Status>
|
||||
filter: string
|
||||
}
|
||||
|
||||
|
@ -55,23 +55,23 @@ const mutations: MutationTree<HomeState> = {
|
|||
[MUTATION_TYPES.UPDATE_TIMELINE]: (state, messages: Array<Status>) => {
|
||||
state.timeline = messages
|
||||
},
|
||||
[MUTATION_TYPES.MERGE_TIMELINE]: (state) => {
|
||||
[MUTATION_TYPES.MERGE_TIMELINE]: state => {
|
||||
state.timeline = state.unreadTimeline.slice(0, 80).concat(state.timeline)
|
||||
state.unreadTimeline = []
|
||||
},
|
||||
[MUTATION_TYPES.INSERT_TIMELINE]: (state, messages: Array<Status>) => {
|
||||
state.timeline = state.timeline.concat(messages)
|
||||
},
|
||||
[MUTATION_TYPES.ARCHIVE_TIMELINE]: (state) => {
|
||||
[MUTATION_TYPES.ARCHIVE_TIMELINE]: state => {
|
||||
state.timeline = state.timeline.slice(0, 40)
|
||||
},
|
||||
[MUTATION_TYPES.CLEAR_TIMELINE]: (state) => {
|
||||
[MUTATION_TYPES.CLEAR_TIMELINE]: state => {
|
||||
state.timeline = []
|
||||
state.unreadTimeline = []
|
||||
},
|
||||
[MUTATION_TYPES.UPDATE_TOOT]: (state, message: Status) => {
|
||||
// Replace target message in homeTimeline and notifications
|
||||
state.timeline = state.timeline.map((toot) => {
|
||||
state.timeline = state.timeline.map(toot => {
|
||||
if (toot.id === message.id) {
|
||||
return message
|
||||
} else if (toot.reblog !== null && toot.reblog.id === message.id) {
|
||||
|
@ -87,7 +87,7 @@ const mutations: MutationTree<HomeState> = {
|
|||
})
|
||||
},
|
||||
[MUTATION_TYPES.DELETE_TOOT]: (state, message: Status) => {
|
||||
state.timeline = state.timeline.filter((toot) => {
|
||||
state.timeline = state.timeline.filter(toot => {
|
||||
if (toot.reblog !== null && toot.reblog.id === message.id) {
|
||||
return false
|
||||
} else {
|
||||
|
@ -108,10 +108,7 @@ const mutations: MutationTree<HomeState> = {
|
|||
|
||||
const actions: ActionTree<HomeState, RootState> = {
|
||||
fetchTimeline: async ({ commit, rootState }) => {
|
||||
const client = new Mastodon(
|
||||
rootState.TimelineSpace.account.accessToken!,
|
||||
rootState.TimelineSpace.account.baseURL + '/api/v1'
|
||||
)
|
||||
const client = new Mastodon(rootState.TimelineSpace.account.accessToken!, rootState.TimelineSpace.account.baseURL + '/api/v1')
|
||||
const res: Response<Array<Status>> = await client.get<Array<Status>>('/timelines/home', { limit: 40 })
|
||||
commit(MUTATION_TYPES.UPDATE_TIMELINE, res.data)
|
||||
return res.data
|
||||
|
@ -121,11 +118,9 @@ const actions: ActionTree<HomeState, RootState> = {
|
|||
return Promise.resolve(null)
|
||||
}
|
||||
commit(MUTATION_TYPES.CHANGE_LAZY_LOADING, true)
|
||||
const client = new Mastodon(
|
||||
rootState.TimelineSpace.account.accessToken!,
|
||||
rootState.TimelineSpace.account.baseURL + '/api/v1'
|
||||
)
|
||||
return client.get<Array<Status>>('/timelines/home', { max_id: lastStatus.id, limit: 40 })
|
||||
const client = new Mastodon(rootState.TimelineSpace.account.accessToken!, rootState.TimelineSpace.account.baseURL + '/api/v1')
|
||||
return client
|
||||
.get<Array<Status>>('/timelines/home', { max_id: lastStatus.id, limit: 40 })
|
||||
.then(res => {
|
||||
commit(MUTATION_TYPES.INSERT_TIMELINE, res.data)
|
||||
return res.data
|
||||
|
|
Loading…
Reference in New Issue