forked from AkkomaGang/akkoma-fe
Merge branch '549' into 'develop'
Prevent showing pinned statuses twice Closes #549 See merge request pleroma/pleroma-fe!812
This commit is contained in:
commit
8aa3e7d52e
6 changed files with 74 additions and 26 deletions
|
@ -1,7 +1,20 @@
|
||||||
import Status from '../status/status.vue'
|
import Status from '../status/status.vue'
|
||||||
import timelineFetcher from '../../services/timeline_fetcher/timeline_fetcher.service.js'
|
import timelineFetcher from '../../services/timeline_fetcher/timeline_fetcher.service.js'
|
||||||
import Conversation from '../conversation/conversation.vue'
|
import Conversation from '../conversation/conversation.vue'
|
||||||
import { throttle } from 'lodash'
|
import { throttle, keyBy } from 'lodash'
|
||||||
|
|
||||||
|
export const getExcludedStatusIdsByPinning = (statuses, pinnedStatusIds) => {
|
||||||
|
const ids = []
|
||||||
|
if (pinnedStatusIds && pinnedStatusIds.length > 0) {
|
||||||
|
for (let status of statuses) {
|
||||||
|
if (!pinnedStatusIds.includes(status.id)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ids.push(status.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ids
|
||||||
|
}
|
||||||
|
|
||||||
const Timeline = {
|
const Timeline = {
|
||||||
props: [
|
props: [
|
||||||
|
@ -11,7 +24,8 @@ const Timeline = {
|
||||||
'userId',
|
'userId',
|
||||||
'tag',
|
'tag',
|
||||||
'embedded',
|
'embedded',
|
||||||
'count'
|
'count',
|
||||||
|
'pinnedStatusIds'
|
||||||
],
|
],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
@ -39,6 +53,12 @@ const Timeline = {
|
||||||
body: ['timeline-body'].concat(!this.embedded ? ['panel-body'] : []),
|
body: ['timeline-body'].concat(!this.embedded ? ['panel-body'] : []),
|
||||||
footer: ['timeline-footer'].concat(!this.embedded ? ['panel-footer'] : [])
|
footer: ['timeline-footer'].concat(!this.embedded ? ['panel-footer'] : [])
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
// id map of statuses which need to be hidden in the main list due to pinning logic
|
||||||
|
excludedStatusIdsObject () {
|
||||||
|
const ids = getExcludedStatusIdsByPinning(this.timeline.visibleStatuses, this.pinnedStatusIds)
|
||||||
|
// Convert id array to object
|
||||||
|
return keyBy(ids, id => id)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
|
@ -28,13 +28,25 @@
|
||||||
</div>
|
</div>
|
||||||
<div :class="classes.body">
|
<div :class="classes.body">
|
||||||
<div class="timeline">
|
<div class="timeline">
|
||||||
|
<template v-for="statusId in pinnedStatusIds">
|
||||||
<conversation
|
<conversation
|
||||||
v-for="status in timeline.visibleStatuses"
|
v-if="timeline.statusesObject[statusId]"
|
||||||
|
:key="statusId + '-pinned'"
|
||||||
|
class="status-fadein"
|
||||||
|
:statusoid="timeline.statusesObject[statusId]"
|
||||||
|
:collapsable="true"
|
||||||
|
:show-pinned="true"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-for="status in timeline.visibleStatuses">
|
||||||
|
<conversation
|
||||||
|
v-if="!excludedStatusIdsObject[status.id]"
|
||||||
:key="status.id"
|
:key="status.id"
|
||||||
class="status-fadein"
|
class="status-fadein"
|
||||||
:statusoid="status"
|
:statusoid="status"
|
||||||
:collapsable="true"
|
:collapsable="true"
|
||||||
/>
|
/>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div :class="classes.footer">
|
<div :class="classes.footer">
|
||||||
|
|
|
@ -15,25 +15,14 @@
|
||||||
:render-only-focused="true"
|
:render-only-focused="true"
|
||||||
>
|
>
|
||||||
<div :label="$t('user_card.statuses')">
|
<div :label="$t('user_card.statuses')">
|
||||||
<div class="timeline">
|
|
||||||
<template v-for="statusId in user.pinnedStatuseIds">
|
|
||||||
<Conversation
|
|
||||||
v-if="timeline.statusesObject[statusId]"
|
|
||||||
:key="statusId"
|
|
||||||
class="status-fadein"
|
|
||||||
:statusoid="timeline.statusesObject[statusId]"
|
|
||||||
:collapsable="true"
|
|
||||||
:show-pinned="true"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
<Timeline
|
<Timeline
|
||||||
:count="user.statuses_count"
|
:count="user.statuses_count"
|
||||||
:embedded="true"
|
:embedded="true"
|
||||||
:title="$t('user_profile.timeline_title')"
|
:title="$t('user_profile.timeline_title')"
|
||||||
:timeline="timeline"
|
:timeline="timeline"
|
||||||
:timeline-name="'user'"
|
timeline-name="user"
|
||||||
:user-id="userId"
|
:user-id="userId"
|
||||||
|
:pinned-status-ids="user.pinnedStatusIds"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -167,11 +167,11 @@ export const mutations = {
|
||||||
},
|
},
|
||||||
setPinned (state, status) {
|
setPinned (state, status) {
|
||||||
const user = state.usersObject[status.user.id]
|
const user = state.usersObject[status.user.id]
|
||||||
const index = user.pinnedStatuseIds.indexOf(status.id)
|
const index = user.pinnedStatusIds.indexOf(status.id)
|
||||||
if (status.pinned && index === -1) {
|
if (status.pinned && index === -1) {
|
||||||
user.pinnedStatuseIds.push(status.id)
|
user.pinnedStatusIds.push(status.id)
|
||||||
} else if (!status.pinned && index !== -1) {
|
} else if (!status.pinned && index !== -1) {
|
||||||
user.pinnedStatuseIds.splice(index, 1)
|
user.pinnedStatusIds.splice(index, 1)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setUserForStatus (state, status) {
|
setUserForStatus (state, status) {
|
||||||
|
|
|
@ -152,7 +152,7 @@ export const parseUser = (data) => {
|
||||||
output.statuses_count = data.statuses_count
|
output.statuses_count = data.statuses_count
|
||||||
output.friendIds = []
|
output.friendIds = []
|
||||||
output.followerIds = []
|
output.followerIds = []
|
||||||
output.pinnedStatuseIds = []
|
output.pinnedStatusIds = []
|
||||||
|
|
||||||
if (data.pleroma) {
|
if (data.pleroma) {
|
||||||
output.follow_request_count = data.pleroma.follow_request_count
|
output.follow_request_count = data.pleroma.follow_request_count
|
||||||
|
|
27
test/unit/specs/components/timeline.spec.js
Normal file
27
test/unit/specs/components/timeline.spec.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { getExcludedStatusIdsByPinning } from 'src/components/timeline/timeline.js'
|
||||||
|
|
||||||
|
describe('Timeline', () => {
|
||||||
|
describe('getExcludedStatusIdsByPinning', () => {
|
||||||
|
const mockStatuses = (ids) => ids.map(id => ({ id }))
|
||||||
|
|
||||||
|
it('should return only members of both pinnedStatusIds and ids of the given statuses', () => {
|
||||||
|
const statusIds = [1, 2, 3, 4]
|
||||||
|
const statuses = mockStatuses(statusIds)
|
||||||
|
const pinnedStatusIds = [1, 3, 5]
|
||||||
|
const result = getExcludedStatusIdsByPinning(statuses, pinnedStatusIds)
|
||||||
|
result.forEach(item => {
|
||||||
|
expect(item).to.be.oneOf(statusIds)
|
||||||
|
expect(item).to.be.oneOf(pinnedStatusIds)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should return ids of pinned statuses not posted before any unpinned status', () => {
|
||||||
|
const pinnedStatusIdSet1 = ['PINNED1', 'PINNED2']
|
||||||
|
const pinnedStatusIdSet2 = ['PINNED3', 'PINNED4']
|
||||||
|
const pinnedStatusIds = [...pinnedStatusIdSet1, ...pinnedStatusIdSet2]
|
||||||
|
const statusIds = [...pinnedStatusIdSet1, 'UNPINNED1', ...pinnedStatusIdSet2]
|
||||||
|
const statuses = mockStatuses(statusIds)
|
||||||
|
expect(getExcludedStatusIdsByPinning(statuses, pinnedStatusIds)).to.eql(pinnedStatusIdSet1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in a new issue