pleroma-fe/src/services/timeline_fetcher/timeline_fetcher.service.js

99 lines
3.0 KiB
JavaScript

import { camelCase, includes } from 'lodash'
import apiService from '../api/api.service.js'
import { parseStatus } from '../entity_normalizer/entity_normalizer.service.js'
const update = ({store, statuses, timeline, showImmediately, userId}) => {
const ccTimeline = camelCase(timeline)
store.dispatch('setError', { value: false })
store.dispatch('addNewStatuses', {
timeline: ccTimeline,
userId,
statuses,
showImmediately
})
}
const fetchAndUpdate = ({store, credentials, timeline = 'friends', older = false, showImmediately = false, userId = false, tag = false, until}) => {
const args = { timeline, credentials }
const rootState = store.rootState || store.state
const timelineData = rootState.statuses.timelines[camelCase(timeline)]
if (older) {
args['until'] = until || timelineData.minVisibleId
} else {
args['since'] = timelineData.maxId
}
args['userId'] = userId
args['tag'] = tag
return apiService.fetchTimeline(args)
.then((statuses) => {
if (!older && statuses.length >= 20 && !timelineData.loading && timelineData.statuses.length) {
store.dispatch('queueFlush', { timeline: timeline, id: timelineData.maxId })
}
update({store, statuses, timeline, showImmediately, userId})
}, () => store.dispatch('setError', { value: true }))
}
const streamTimeline = ({timeline, store, userId}) => {
const rootState = store.rootState || store.state
const timelines = {
publicAndExternal: 'public',
public: 'public:local',
friends: 'user'
}
let url = `${rootState.instance.server}/api/v1/streaming?stream=${timelines[timeline]}`.replace('http', 'ws')
if (rootState.oauth.token) {
url = url + `&access_token=${rootState.oauth.token}`
}
const socket = new window.WebSocket(url)
socket.addEventListener('message', (event) => {
if (event.data === '') { return }
const data = JSON.parse(event.data)
if (data.event === 'update') {
const status = JSON.parse(data.payload)
update({store, statuses: [parseStatus(status)], timeline, showImmediately: false, userId})
}
})
return {
stop: () => socket.close()
}
}
const startFetching = ({timeline = 'friends', credentials, store, userId = false, tag = false}) => {
// First fetch is over REST
const rootState = store.rootState || store.state
const timelineData = rootState.statuses.timelines[camelCase(timeline)]
const showImmediately = timelineData.visibleStatuses.length === 0
timelineData.userId = userId
fetchAndUpdate({timeline, credentials, store, showImmediately, userId, tag})
const websocketTimelines = ['publicAndExternal', 'public', 'friends']
if (includes(websocketTimelines, timeline)) {
return streamTimeline({timeline, store, userId})
} else {
const boundFetchAndUpdate = () => fetchAndUpdate({ timeline, credentials, store, userId, tag })
const fetcher = setInterval(boundFetchAndUpdate, 10000)
return {
stop: () => window.clearInterval(fetcher)
}
}
}
const timelineFetcher = {
fetchAndUpdate,
startFetching
}
export default timelineFetcher