Add list timeline rendering functionality

the list name is missing; this is because the API request to get it is different
to the API request for receiving the list timeline, and is not yet implemented.
This commit is contained in:
Sol Fisher Romanoff 2022-06-15 17:12:05 +03:00
parent c1a8dc34da
commit d5d464a289
Signed by: nbsp
GPG key ID: 9D3F2B64F2341B62
9 changed files with 62 additions and 11 deletions

View file

@ -20,6 +20,7 @@ import ShoutPanel from 'components/shout_panel/shout_panel.vue'
import WhoToFollow from 'components/who_to_follow/who_to_follow.vue' import WhoToFollow from 'components/who_to_follow/who_to_follow.vue'
import About from 'components/about/about.vue' import About from 'components/about/about.vue'
import RemoteUserResolver from 'components/remote_user_resolver/remote_user_resolver.vue' import RemoteUserResolver from 'components/remote_user_resolver/remote_user_resolver.vue'
import ListTimeline from 'components/list_timeline/list_timeline.vue'
export default (store) => { export default (store) => {
const validateAuthenticatedRoute = (to, from, next) => { const validateAuthenticatedRoute = (to, from, next) => {
@ -69,7 +70,8 @@ export default (store) => {
{ name: 'search', path: '/search', component: Search, props: (route) => ({ query: route.query.query }) }, { name: 'search', path: '/search', component: Search, props: (route) => ({ query: route.query.query }) },
{ name: 'who-to-follow', path: '/who-to-follow', component: WhoToFollow, beforeEnter: validateAuthenticatedRoute }, { name: 'who-to-follow', path: '/who-to-follow', component: WhoToFollow, beforeEnter: validateAuthenticatedRoute },
{ name: 'about', path: '/about', component: About }, { name: 'about', path: '/about', component: About },
{ name: 'user-profile', path: '/:_(users)?/:name', component: UserProfile } { name: 'user-profile', path: '/:_(users)?/:name', component: UserProfile },
{ name: 'list-timeline', path: '/lists/:id', component: ListTimeline }
] ]
if (store.state.instance.pleromaChatMessagesAvailable) { if (store.state.instance.pleromaChatMessagesAvailable) {

View file

@ -0,0 +1,23 @@
import Timeline from '../timeline/timeline.vue'
const ListTimeline = {
data () {
return {
listId: null
}
},
components: {
Timeline
},
computed: {
timeline () { return this.$store.state.statuses.timelines.list }
},
created () {
this.listId = this.$route.params.id
this.$store.dispatch('startFetchingTimeline', { timeline: 'list', listId: this.listId })
},
unmounted () {
this.$store.dispatch('stopFetchingTimeline', 'list')
}
}
export default ListTimeline

View file

@ -0,0 +1,10 @@
<template>
<Timeline
title="list.name"
:timeline="timeline"
:list-id="listId"
timeline-name="list"
/>
</template>
<script src="./list_timeline.js"></script>

View file

@ -18,6 +18,7 @@ const Timeline = {
'timelineName', 'timelineName',
'title', 'title',
'userId', 'userId',
'listId',
'tag', 'tag',
'embedded', 'embedded',
'count', 'count',
@ -101,6 +102,7 @@ const Timeline = {
timeline: this.timelineName, timeline: this.timelineName,
showImmediately, showImmediately,
userId: this.userId, userId: this.userId,
listId: this.listId,
tag: this.tag tag: this.tag
}) })
}, },
@ -156,6 +158,7 @@ const Timeline = {
older: true, older: true,
showImmediately: true, showImmediately: true,
userId: this.userId, userId: this.userId,
listId: this.listId,
tag: this.tag tag: this.tag
}).then(({ statuses }) => { }).then(({ statuses }) => {
if (statuses && statuses.length === 0) { if (statuses && statuses.length === 0) {

View file

@ -191,12 +191,13 @@ const api = {
startFetchingTimeline (store, { startFetchingTimeline (store, {
timeline = 'friends', timeline = 'friends',
tag = false, tag = false,
userId = false userId = false,
listId = false
}) { }) {
if (store.state.fetchers[timeline]) return if (store.state.fetchers[timeline]) return
const fetcher = store.state.backendInteractor.startFetchingTimeline({ const fetcher = store.state.backendInteractor.startFetchingTimeline({
timeline, store, userId, tag timeline, store, userId, listId, tag
}) })
store.commit('addFetcher', { fetcherName: timeline, fetcher }) store.commit('addFetcher', { fetcherName: timeline, fetcher })
}, },

View file

@ -62,7 +62,8 @@ export const defaultState = () => ({
friends: emptyTl(), friends: emptyTl(),
tag: emptyTl(), tag: emptyTl(),
dms: emptyTl(), dms: emptyTl(),
bookmarks: emptyTl() bookmarks: emptyTl(),
list: emptyTl()
} }
}) })

View file

@ -50,6 +50,7 @@ const MASTODON_STATUS_CONTEXT_URL = id => `/api/v1/statuses/${id}/context`
const MASTODON_USER_URL = '/api/v1/accounts' const MASTODON_USER_URL = '/api/v1/accounts'
const MASTODON_USER_RELATIONSHIPS_URL = '/api/v1/accounts/relationships' const MASTODON_USER_RELATIONSHIPS_URL = '/api/v1/accounts/relationships'
const MASTODON_USER_TIMELINE_URL = id => `/api/v1/accounts/${id}/statuses` const MASTODON_USER_TIMELINE_URL = id => `/api/v1/accounts/${id}/statuses`
const MASTODON_LIST_TIMELINE_URL = id => `/api/v1/timelines/list/${id}`
const MASTODON_TAG_TIMELINE_URL = tag => `/api/v1/timelines/tag/${tag}` const MASTODON_TAG_TIMELINE_URL = tag => `/api/v1/timelines/tag/${tag}`
const MASTODON_BOOKMARK_TIMELINE_URL = '/api/v1/bookmarks' const MASTODON_BOOKMARK_TIMELINE_URL = '/api/v1/bookmarks'
const MASTODON_USER_BLOCKS_URL = '/api/v1/blocks/' const MASTODON_USER_BLOCKS_URL = '/api/v1/blocks/'
@ -503,6 +504,7 @@ const fetchTimeline = ({
since = false, since = false,
until = false, until = false,
userId = false, userId = false,
listId = false,
tag = false, tag = false,
withMuted = false, withMuted = false,
replyVisibility = 'all' replyVisibility = 'all'
@ -515,6 +517,7 @@ const fetchTimeline = ({
'publicAndExternal': MASTODON_PUBLIC_TIMELINE, 'publicAndExternal': MASTODON_PUBLIC_TIMELINE,
user: MASTODON_USER_TIMELINE_URL, user: MASTODON_USER_TIMELINE_URL,
media: MASTODON_USER_TIMELINE_URL, media: MASTODON_USER_TIMELINE_URL,
list: MASTODON_LIST_TIMELINE_URL,
favorites: MASTODON_USER_FAVORITES_TIMELINE_URL, favorites: MASTODON_USER_FAVORITES_TIMELINE_URL,
tag: MASTODON_TAG_TIMELINE_URL, tag: MASTODON_TAG_TIMELINE_URL,
bookmarks: MASTODON_BOOKMARK_TIMELINE_URL bookmarks: MASTODON_BOOKMARK_TIMELINE_URL
@ -528,6 +531,10 @@ const fetchTimeline = ({
url = url(userId) url = url(userId)
} }
if (timeline === 'list') {
url = url(listId)
}
if (since) { if (since) {
params.push(['since_id', since]) params.push(['since_id', since])
} }

View file

@ -4,8 +4,8 @@ import notificationsFetcher from '../notifications_fetcher/notifications_fetcher
import followRequestFetcher from '../../services/follow_request_fetcher/follow_request_fetcher.service' import followRequestFetcher from '../../services/follow_request_fetcher/follow_request_fetcher.service'
const backendInteractorService = credentials => ({ const backendInteractorService = credentials => ({
startFetchingTimeline ({ timeline, store, userId = false, tag }) { startFetchingTimeline ({ timeline, store, userId = false, listId = false, tag }) {
return timelineFetcher.startFetching({ timeline, store, credentials, userId, tag }) return timelineFetcher.startFetching({ timeline, store, credentials, userId, listId, tag })
}, },
fetchTimeline (args) { fetchTimeline (args) {

View file

@ -3,12 +3,13 @@ import { camelCase } from 'lodash'
import apiService from '../api/api.service.js' import apiService from '../api/api.service.js'
import { promiseInterval } from '../promise_interval/promise_interval.js' import { promiseInterval } from '../promise_interval/promise_interval.js'
const update = ({ store, statuses, timeline, showImmediately, userId, pagination }) => { const update = ({ store, statuses, timeline, showImmediately, userId, listId, pagination }) => {
const ccTimeline = camelCase(timeline) const ccTimeline = camelCase(timeline)
store.dispatch('addNewStatuses', { store.dispatch('addNewStatuses', {
timeline: ccTimeline, timeline: ccTimeline,
userId, userId,
listId,
statuses, statuses,
showImmediately, showImmediately,
pagination pagination
@ -22,6 +23,7 @@ const fetchAndUpdate = ({
older = false, older = false,
showImmediately = false, showImmediately = false,
userId = false, userId = false,
listId = false,
tag = false, tag = false,
until, until,
since since
@ -44,6 +46,7 @@ const fetchAndUpdate = ({
} }
args['userId'] = userId args['userId'] = userId
args['listId'] = listId
args['tag'] = tag args['tag'] = tag
args['withMuted'] = !hideMutedPosts args['withMuted'] = !hideMutedPosts
if (loggedIn && ['friends', 'public', 'publicAndExternal'].includes(timeline)) { if (loggedIn && ['friends', 'public', 'publicAndExternal'].includes(timeline)) {
@ -62,7 +65,7 @@ const fetchAndUpdate = ({
if (!older && statuses.length >= 20 && !timelineData.loading && numStatusesBeforeFetch > 0) { if (!older && statuses.length >= 20 && !timelineData.loading && numStatusesBeforeFetch > 0) {
store.dispatch('queueFlush', { timeline: timeline, id: timelineData.maxId }) store.dispatch('queueFlush', { timeline: timeline, id: timelineData.maxId })
} }
update({ store, statuses, timeline, showImmediately, userId, pagination }) update({ store, statuses, timeline, showImmediately, userId, listId, pagination })
return { statuses, pagination } return { statuses, pagination }
}) })
.catch((error) => { .catch((error) => {
@ -75,14 +78,15 @@ const fetchAndUpdate = ({
}) })
} }
const startFetching = ({ timeline = 'friends', credentials, store, userId = false, tag = false }) => { const startFetching = ({ timeline = 'friends', credentials, store, userId = false, listId = false, tag = false }) => {
const rootState = store.rootState || store.state const rootState = store.rootState || store.state
const timelineData = rootState.statuses.timelines[camelCase(timeline)] const timelineData = rootState.statuses.timelines[camelCase(timeline)]
const showImmediately = timelineData.visibleStatuses.length === 0 const showImmediately = timelineData.visibleStatuses.length === 0
timelineData.userId = userId timelineData.userId = userId
fetchAndUpdate({ timeline, credentials, store, showImmediately, userId, tag }) timelineData.listId = listId
fetchAndUpdate({ timeline, credentials, store, showImmediately, userId, listId, tag })
const boundFetchAndUpdate = () => const boundFetchAndUpdate = () =>
fetchAndUpdate({ timeline, credentials, store, userId, tag }) fetchAndUpdate({ timeline, credentials, store, userId, listId, tag })
return promiseInterval(boundFetchAndUpdate, 20000) return promiseInterval(boundFetchAndUpdate, 20000)
} }
const timelineFetcher = { const timelineFetcher = {