#468 - show pinned timeline and add pinned label to the status
This commit is contained in:
parent
e28b19645a
commit
2c89d49a3d
11 changed files with 69 additions and 18 deletions
|
@ -41,7 +41,8 @@ const conversation = {
|
||||||
props: [
|
props: [
|
||||||
'statusoid',
|
'statusoid',
|
||||||
'collapsable',
|
'collapsable',
|
||||||
'isPage'
|
'isPage',
|
||||||
|
'pinned'
|
||||||
],
|
],
|
||||||
created () {
|
created () {
|
||||||
if (this.isPage) {
|
if (this.isPage) {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
:key="status.id"
|
:key="status.id"
|
||||||
:inlineExpanded="collapsable && isExpanded"
|
:inlineExpanded="collapsable && isExpanded"
|
||||||
:statusoid="status"
|
:statusoid="status"
|
||||||
|
:pinned="pinned"
|
||||||
:expandable='!isExpanded'
|
:expandable='!isExpanded'
|
||||||
:focused="focused(status.id)"
|
:focused="focused(status.id)"
|
||||||
:inConversation="isExpanded"
|
:inConversation="isExpanded"
|
||||||
|
|
|
@ -26,7 +26,8 @@ const Status = {
|
||||||
'replies',
|
'replies',
|
||||||
'isPreview',
|
'isPreview',
|
||||||
'noHeading',
|
'noHeading',
|
||||||
'inlineExpanded'
|
'inlineExpanded',
|
||||||
|
'pinned'
|
||||||
],
|
],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -12,6 +12,13 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
<div v-if="pinned" class="status-pin">
|
||||||
|
<i class="fa icon-pin faint"></i>
|
||||||
|
<span class="faint">Pinned</span>
|
||||||
|
<div class="button-icon button-action-icon" v-if="status.pinned && ownStatus" @click.prevent="unpinStatus" title="Unpin">
|
||||||
|
<i class="fa icon-cancel"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div v-if="retweet && !noHeading && !inConversation" :class="[repeaterClass, { highlighted: repeaterStyle }]" :style="[repeaterStyle]" class="media container retweet-info">
|
<div v-if="retweet && !noHeading && !inConversation" :class="[repeaterClass, { highlighted: repeaterStyle }]" :style="[repeaterStyle]" class="media container retweet-info">
|
||||||
<UserAvatar class="media-left" v-if="retweet" :betterShadow="betterShadow" :user="statusoid.user"/>
|
<UserAvatar class="media-left" v-if="retweet" :betterShadow="betterShadow" :user="statusoid.user"/>
|
||||||
<div class="media-body faint">
|
<div class="media-body faint">
|
||||||
|
@ -55,9 +62,6 @@
|
||||||
<div class="button-icon button-action-icon" v-if="!status.pinned && ownStatus" @click.prevent="pinStatus" title="Pin">
|
<div class="button-icon button-action-icon" v-if="!status.pinned && ownStatus" @click.prevent="pinStatus" title="Pin">
|
||||||
<i class="fa icon-pin"></i>
|
<i class="fa icon-pin"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="button-icon button-action-icon" v-if="status.pinned && ownStatus" @click.prevent="unpinStatus" title="Unpin">
|
|
||||||
<i class="fa icon-cancel"></i>
|
|
||||||
</div>
|
|
||||||
<div class="button-icon button-action-icon" v-if="expandable && !isPreview" @click.prevent="toggleExpanded" title="Expand">
|
<div class="button-icon button-action-icon" v-if="expandable && !isPreview" @click.prevent="toggleExpanded" title="Expand">
|
||||||
<i class="button-icon icon-plus-squared"></i>
|
<i class="button-icon icon-plus-squared"></i>
|
||||||
</div>
|
</div>
|
||||||
|
@ -205,6 +209,13 @@ $status-margin: 0.75em;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.status-pin {
|
||||||
|
padding: 0.75em 0.75em 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
.status-preview {
|
.status-preview {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
max-width: 95%;
|
max-width: 95%;
|
||||||
|
|
|
@ -11,7 +11,8 @@ const Timeline = {
|
||||||
'userId',
|
'userId',
|
||||||
'tag',
|
'tag',
|
||||||
'embedded',
|
'embedded',
|
||||||
'count'
|
'count',
|
||||||
|
'noLoadMore'
|
||||||
],
|
],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -21,11 +21,12 @@
|
||||||
class="status-fadein"
|
class="status-fadein"
|
||||||
:key="status.id"
|
:key="status.id"
|
||||||
:statusoid="status"
|
:statusoid="status"
|
||||||
|
:pinned="timelineName === 'pinned'"
|
||||||
:collapsable="true"
|
:collapsable="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div :class="classes.footer">
|
<div :class="classes.footer" v-if="!noLoadMore">
|
||||||
<div v-if="count===0" class="new-status-notification text-center panel-footer faint">
|
<div v-if="count===0" class="new-status-notification text-center panel-footer faint">
|
||||||
{{$t('timeline.no_statuses')}}
|
{{$t('timeline.no_statuses')}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -40,6 +40,9 @@ const UserProfile = {
|
||||||
timeline () {
|
timeline () {
|
||||||
return this.$store.state.statuses.timelines.user
|
return this.$store.state.statuses.timelines.user
|
||||||
},
|
},
|
||||||
|
pinned () {
|
||||||
|
return this.$store.state.statuses.timelines.pinned
|
||||||
|
},
|
||||||
favorites () {
|
favorites () {
|
||||||
return this.$store.state.statuses.timelines.favorites
|
return this.$store.state.statuses.timelines.favorites
|
||||||
},
|
},
|
||||||
|
@ -91,6 +94,7 @@ const UserProfile = {
|
||||||
fetchTimelines () {
|
fetchTimelines () {
|
||||||
const userId = this.userId
|
const userId = this.userId
|
||||||
this.$store.dispatch('startFetchingTimeline', { timeline: 'user', userId })
|
this.$store.dispatch('startFetchingTimeline', { timeline: 'user', userId })
|
||||||
|
this.$store.dispatch('startFetchingTimeline', { timeline: 'pinned', userId })
|
||||||
this.$store.dispatch('startFetchingTimeline', { timeline: 'media', userId })
|
this.$store.dispatch('startFetchingTimeline', { timeline: 'media', userId })
|
||||||
if (this.isUs) {
|
if (this.isUs) {
|
||||||
this.$store.dispatch('startFetchingTimeline', { timeline: 'favorites', userId })
|
this.$store.dispatch('startFetchingTimeline', { timeline: 'favorites', userId })
|
||||||
|
@ -98,6 +102,7 @@ const UserProfile = {
|
||||||
},
|
},
|
||||||
cleanUp () {
|
cleanUp () {
|
||||||
this.$store.dispatch('stopFetching', 'user')
|
this.$store.dispatch('stopFetching', 'user')
|
||||||
|
this.$store.dispatch('stopFetching', 'pinned')
|
||||||
this.$store.dispatch('stopFetching', 'favorites')
|
this.$store.dispatch('stopFetching', 'favorites')
|
||||||
this.$store.dispatch('stopFetching', 'media')
|
this.$store.dispatch('stopFetching', 'media')
|
||||||
this.$store.commit('clearTimeline', { timeline: 'user' })
|
this.$store.commit('clearTimeline', { timeline: 'user' })
|
||||||
|
|
|
@ -3,16 +3,25 @@
|
||||||
<div v-if="user" class="user-profile panel panel-default">
|
<div v-if="user" class="user-profile panel panel-default">
|
||||||
<UserCard :user="user" :switcher="true" :selected="timeline.viewing" rounded="top"/>
|
<UserCard :user="user" :switcher="true" :selected="timeline.viewing" rounded="top"/>
|
||||||
<tab-switcher :renderOnlyFocused="true" ref="tabSwitcher">
|
<tab-switcher :renderOnlyFocused="true" ref="tabSwitcher">
|
||||||
<Timeline
|
<div :label="$t('user_card.statuses')" :disabled="!user.statuses_count">
|
||||||
:label="$t('user_card.statuses')"
|
<Timeline
|
||||||
:disabled="!user.statuses_count"
|
: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="pinned"
|
||||||
:timeline="timeline"
|
:timeline-name="'pinned'"
|
||||||
:timeline-name="'user'"
|
:user-id="userId"
|
||||||
:user-id="userId"
|
:no-load-more="true"
|
||||||
/>
|
/>
|
||||||
|
<Timeline
|
||||||
|
:count="user.statuses_count"
|
||||||
|
:embedded="true"
|
||||||
|
:title="$t('user_profile.timeline_title')"
|
||||||
|
:timeline="timeline"
|
||||||
|
:timeline-name="'user'"
|
||||||
|
:user-id="userId"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div :label="$t('user_card.followees')" v-if="followsTabVisible" :disabled="!user.friends_count">
|
<div :label="$t('user_card.followees')" v-if="followsTabVisible" :disabled="!user.friends_count">
|
||||||
<FriendList :userId="userId">
|
<FriendList :userId="userId">
|
||||||
<template slot="item" slot-scope="{item}">
|
<template slot="item" slot-scope="{item}">
|
||||||
|
|
|
@ -47,7 +47,8 @@ export const defaultState = () => ({
|
||||||
publicAndExternal: emptyTl(),
|
publicAndExternal: emptyTl(),
|
||||||
friends: emptyTl(),
|
friends: emptyTl(),
|
||||||
tag: emptyTl(),
|
tag: emptyTl(),
|
||||||
dms: emptyTl()
|
dms: emptyTl(),
|
||||||
|
pinned: emptyTl()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -506,6 +506,19 @@ const fetchTimeline = ({timeline, credentials, since = false, until = false, use
|
||||||
.then((data) => data.map(isNotifications ? parseNotification : parseStatus))
|
.then((data) => data.map(isNotifications ? parseNotification : parseStatus))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fetchPinnedStatuses = ({ id, credentials }) => {
|
||||||
|
const url = MASTODON_USER_TIMELINE_URL(id) + '?pinned=true'
|
||||||
|
return fetch(url, { headers: authHeaders(credentials) })
|
||||||
|
.then((data) => {
|
||||||
|
if (data.ok) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
throw new Error('Error fetching pinned timeline', data)
|
||||||
|
})
|
||||||
|
.then((data) => data.json())
|
||||||
|
.then((data) => data.map(parseStatus))
|
||||||
|
}
|
||||||
|
|
||||||
const verifyCredentials = (user) => {
|
const verifyCredentials = (user) => {
|
||||||
return fetch(LOGIN_URL, {
|
return fetch(LOGIN_URL, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
@ -726,6 +739,7 @@ const reportUser = ({credentials, userId, statusIds, comment, forward}) => {
|
||||||
const apiService = {
|
const apiService = {
|
||||||
verifyCredentials,
|
verifyCredentials,
|
||||||
fetchTimeline,
|
fetchTimeline,
|
||||||
|
fetchPinnedStatuses,
|
||||||
fetchConversation,
|
fetchConversation,
|
||||||
fetchStatus,
|
fetchStatus,
|
||||||
fetchFriends,
|
fetchFriends,
|
||||||
|
|
|
@ -16,6 +16,12 @@ const update = ({store, statuses, timeline, showImmediately, userId}) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchAndUpdate = ({store, credentials, timeline = 'friends', older = false, showImmediately = false, userId = false, tag = false, until}) => {
|
const fetchAndUpdate = ({store, credentials, timeline = 'friends', older = false, showImmediately = false, userId = false, tag = false, until}) => {
|
||||||
|
if (timeline === 'pinned') {
|
||||||
|
return apiService.fetchPinnedStatuses({ id: userId, credentials })
|
||||||
|
.then(statuses => {
|
||||||
|
update({ store, statuses, timeline, showImmediately, userId })
|
||||||
|
})
|
||||||
|
}
|
||||||
const args = { timeline, credentials }
|
const args = { timeline, credentials }
|
||||||
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)]
|
||||||
|
|
Loading…
Reference in a new issue