fix pinned statuses appearing at the bottom of user timeline (and

possibly fetching new ones there)
This commit is contained in:
Henry Jameson 2022-02-20 00:04:47 +02:00
parent 8ade11783a
commit 2a97bdb39d
2 changed files with 31 additions and 3 deletions

View file

@ -37,7 +37,7 @@
</template> </template>
<template v-for="status in timeline.visibleStatuses"> <template v-for="status in timeline.visibleStatuses">
<conversation <conversation
v-if="!excludedStatusIdsObject[status.id]" v-if="status._meta.fetchedFromPinned <= 0"
:key="status.id" :key="status.id"
class="status-fadein" class="status-fadein"
:status-id="status.id" :status-id="status.id"

View file

@ -84,7 +84,7 @@ const mergeOrAdd = (arr, obj, item) => {
// We already have this, so only merge the new info. // We already have this, so only merge the new info.
// We ignore null values to avoid overwriting existing properties with missing data // We ignore null values to avoid overwriting existing properties with missing data
// we also skip 'user' because that is handled by users module // we also skip 'user' because that is handled by users module
merge(oldItem, omitBy(item, (v, k) => v === null || k === 'user')) merge(oldItem, omitBy(item, (v, k) => v === null || k === 'user' || k === '_meta'))
// Reactivity fix. // Reactivity fix.
oldItem.attachments.splice(oldItem.attachments.length) oldItem.attachments.splice(oldItem.attachments.length)
return { item: oldItem, new: false } return { item: oldItem, new: false }
@ -122,6 +122,22 @@ const sortTimeline = (timeline) => {
// Add status to the global storages (arrays and objects maintaining statuses) except timelines // Add status to the global storages (arrays and objects maintaining statuses) except timelines
const addStatusToGlobalStorage = (state, data) => { const addStatusToGlobalStorage = (state, data) => {
// POST METADATA PROCESSING.
// In this context "metadata" means all the sidechannel information about the post that we have
// i.e. where post was obtained from (which endpoint), what timestamp was etc. anything that isn't
// directly attached into it by server.
//
// @@_meta.fetchedFromPinned: number
// -1 = fetched from elsewhere
// +1 = fetched from pinned posts
// 0 = fetched from elsewhere and from pinned posts
//
// The logic is mainly for user profile page - don't show post in timeline context
// if post was ONLY fetched from pinned posts, show it if it was obtained from
// elsewhere (i.e. user posts fetching)
data._meta = data._meta || {}
data._meta.fetchedFromPinned = data._meta.fetchedFromPinned || -1
const result = mergeOrAdd(state.allStatuses, state.allStatusesObject, data) const result = mergeOrAdd(state.allStatuses, state.allStatusesObject, data)
if (result.new) { if (result.new) {
// Add to conversation // Add to conversation
@ -133,6 +149,18 @@ const addStatusToGlobalStorage = (state, data) => {
} else { } else {
set(conversationsObject, conversationId, [status]) set(conversationsObject, conversationId, [status])
} }
} else {
// If post was fetched from elsewhere AND from pinned (=0 we don't care anymore)
// otherwise we sum the old data and new data and clamp it to [-1; 1]
if (result.item._meta.fetchedFromPinned !== 0) {
result.item._meta.fetchedFromPinned = Math.min(
1,
Math.max(
-1,
result.item._meta.fetchedFromPinned + data._meta.fetchedFromPinned
)
)
}
} }
return result return result
} }
@ -626,7 +654,7 @@ const statuses = {
}, },
fetchPinnedStatuses ({ rootState, dispatch }, userId) { fetchPinnedStatuses ({ rootState, dispatch }, userId) {
rootState.api.backendInteractor.fetchPinnedStatuses({ id: userId }) rootState.api.backendInteractor.fetchPinnedStatuses({ id: userId })
.then(statuses => dispatch('addNewStatuses', { statuses, timeline: 'user', userId, showImmediately: true, noIdUpdate: true })) .then(statuses => dispatch('addNewStatuses', { statuses: statuses.map(status => ({ ...status, _meta: { fetchedFromPinned: 1 } })), timeline: 'user', userId, showImmediately: true, noIdUpdate: true }))
}, },
pinStatus ({ rootState, dispatch }, statusId) { pinStatus ({ rootState, dispatch }, statusId) {
return rootState.api.backendInteractor.pinOwnStatus({ id: statusId }) return rootState.api.backendInteractor.pinOwnStatus({ id: statusId })