summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaxence Lange <maxence@artificial-owl.com>2023-04-11 16:52:17 -0100
committerGitHub <noreply@github.com>2023-04-11 16:52:17 -0100
commit6d945ff03c6a381c5fcf2380044f7f72b3336481 (patch)
tree0ea9340559c14732ce405e00d455ba284cd5ae97
parentc71ed30f2f3cb55212e106b67447d619aa50b348 (diff)
parentcb47afc124e770b4d599d71bdd03422bb146768c (diff)
Merge pull request #1729 from nextcloud/artonge/fix/again_some_fixes
Fix blocking issues
-rw-r--r--src/components/Composer/Composer.vue2
-rw-r--r--src/components/TimelineEntry.vue99
-rw-r--r--src/components/TimelinePost.vue53
-rw-r--r--src/store/timeline.js225
-rw-r--r--src/views/Timeline.vue7
-rw-r--r--src/views/TimelineSinglePost.vue14
6 files changed, 257 insertions, 143 deletions
diff --git a/src/components/Composer/Composer.vue b/src/components/Composer/Composer.vue
index e7111f11..e0a77ecc 100644
--- a/src/components/Composer/Composer.vue
+++ b/src/components/Composer/Composer.vue
@@ -378,7 +378,7 @@ export default {
this.updateStatusContent()
},
keyup(event) {
- if (event.shiftKey || event.ctrlKey) {
+ if (event.ctrlKey) {
this.createPost(event)
}
},
diff --git a/src/components/TimelineEntry.vue b/src/components/TimelineEntry.vue
index 2c641ebe..80812f1a 100644
--- a/src/components/TimelineEntry.vue
+++ b/src/components/TimelineEntry.vue
@@ -1,10 +1,24 @@
<template>
- <li :class="['timeline-entry', hasHeader ? 'with-header' : '']">
- <div v-if="isNotification" class="notification">
- <Bell :size="22" />
- <span class="notification-action">
+ <component :is="element" class="timeline-entry" :class="{ 'notification': isNotification, 'with-header': hasHeader }">
+ <div v-if="isNotification" class="notification__header">
+ <span class="notification__summary">
+ <img :src="notification.account.avatar">
+ <Heart v-if="notification.type === 'favourite'" :size="16" />
+ <Repeat v-if="notification.type === 'reblog'" :size="16" />
{{ actionSummary }}
</span>
+ <span class="notification__details">
+ <router-link :to="{ name: 'single-post', params: {
+ account: item.account.display_name,
+ id: notification.status.id,
+ type: 'single-post',
+ } }"
+ :data-timestamp="notification.created_at"
+ class="post-timestamp live-relative-timestamp"
+ :title="notificationFormattedDate">
+ {{ notificationRelativeTimestamp }}
+ </router-link>
+ </span>
</div>
<template v-else-if="isBoost">
<div class="container-icon-boost boost">
@@ -24,18 +38,22 @@
:item="item.account" />
<template v-else>
<div class="wrapper">
- <TimelineAvatar class="entry__avatar" :item="entryContent" />
+ <TimelineAvatar v-if="!isNotification" class="entry__avatar" :item="entryContent" />
<TimelinePost class="entry__content"
:item="entryContent"
:type="type" />
</div>
</template>
- </li>
+ </component>
</template>
<script>
import Bell from 'vue-material-design-icons/Bell.vue'
+import Repeat from 'vue-material-design-icons/Repeat.vue'
+import Reply from 'vue-material-design-icons/Reply.vue'
+import Heart from 'vue-material-design-icons/Heart.vue'
import { translate } from '@nextcloud/l10n'
+import moment from '@nextcloud/moment'
import TimelinePost from './TimelinePost.vue'
import TimelineAvatar from './TimelineAvatar.vue'
import UserEntry from './UserEntry.vue'
@@ -48,6 +66,9 @@ export default {
TimelineAvatar,
UserEntry,
Bell,
+ Repeat,
+ Reply,
+ Heart,
},
props: {
/** @type {import('vue').PropType<import('../types/Mastodon.js').Status|import('../types/Mastodon.js').Notification>} */
@@ -59,6 +80,10 @@ export default {
type: String,
required: true,
},
+ element: {
+ type: String,
+ default: 'li',
+ },
},
computed: {
/**
@@ -77,6 +102,14 @@ export default {
isNotification() {
return this.item.type !== undefined
},
+ /** @return {string} */
+ notificationFormattedDate() {
+ return moment(this.notification.created_at).format('LLL')
+ },
+ /** @return {string} */
+ notificationRelativeTimestamp() {
+ return moment(this.notification.created_at).fromNow()
+ },
/** @return {boolean} */
isBoost() {
return this.status.reblog !== null
@@ -137,21 +170,61 @@ export default {
}
.notification {
- display: flex;
- padding-left: 2rem;
- gap: 0.2rem;
- margin-top: 1rem;
+ border-bottom: 1px solid var(--color-border);
+
+ &__header {
+ display: flex;
+ gap: 0.2rem;
+ margin-top: 1rem;
+ }
- &-action {
+ &__summary {
flex-grow: 1;
display: inline-block;
grid-row: 1;
grid-column: 2;
color: var(--color-text-lighter);
+ position: relative;
+ margin-bottom: 8px;
+
+ img {
+ width: 32px;
+ border-radius: 50%;
+ overflow: hidden;
+ margin-right: 3px;
+ vertical-align: middle;
+ margin-top: -1px;
+ margin-right: 8px;
+ }
+
+ .material-design-icon {
+ position: absolute;
+ top: 16px;
+ left: 20px;
+ padding: 2px;
+ background: var(--color-main-background);
+ border-radius: 50%;
+ border: 1px solid var(--color-background-dark);
+ }
+
+ }
+
+ &__details a {
+ color: var(--color-text-lighter);
+
+ &:hover {
+ text-decoration: underline;
+ }
}
- .bell-icon {
- opacity: .5;
+ :deep(.post-header) {
+ .post-visibility {
+ display: none;
+ }
+
+ .post-timestamp {
+ display: none;
+ }
}
}
diff --git a/src/components/TimelinePost.vue b/src/components/TimelinePost.vue
index 5d504788..1b23b79b 100644
--- a/src/components/TimelinePost.vue
+++ b/src/components/TimelinePost.vue
@@ -14,16 +14,16 @@
</span>
</router-link>
</div>
- <VisibilityIcon v-if="visibility"
- :title="visibility.text"
- class="post-visibility"
- :visibility="visibility.id" />
<a :data-timestamp="timestamp"
class="post-timestamp live-relative-timestamp"
:title="formattedDate"
@click="getSinglePostTimeline">
{{ relativeTimestamp }}
</a>
+ <VisibilityIcon v-if="visibility"
+ :title="visibility.text"
+ class="post-visibility"
+ :visibility="visibility.id" />
</div>
<div v-if="item.content" class="post-message">
<MessageContent :item="item" />
@@ -33,7 +33,7 @@
<PostAttachment v-if="hasAttachments" :attachments="item.media_attachments || []" />
<div v-if="$route && $route.params.type !== 'notifications' && !serverData.public" class="post-actions">
<NcButton :title="t('social', 'Reply')"
- type="tertiary-no-background"
+ type="tertiary"
@click="reply">
<template #icon>
<Reply :size="20" />
@@ -46,7 +46,7 @@
</NcButton>
<NcButton v-if="item.visibility === 'public' || item.visibility === 'unlisted'"
:title="t('social', 'Boost')"
- type="tertiary-no-background"
+ type="tertiary"
@click="boost">
<template #icon>
<Repeat :size="20" :fill-color="isBoosted ? 'var(--color-primary)' : 'var(--color-main-text)'" />
@@ -59,7 +59,7 @@
</NcButton>
<NcButton v-if="!isLiked"
:title="t('social', 'Like')"
- type="tertiary-no-background"
+ type="tertiary"
@click="like">
<template #icon>
<HeartOutline :size="20" />
@@ -72,7 +72,7 @@
</NcButton>
<NcButton v-if="isLiked"
:title="t('social', 'Undo Like')"
- type="tertiary-no-background"
+ type="tertiary"
@click="like">
<template #icon>
<Heart :size="20" :fill-color="'var(--color-error)'" />
@@ -208,24 +208,18 @@ export default {
getSinglePostTimeline(e) {
// Display internal or external post
if (!this.isLocal) {
- // TODO - fix
- if (this.type === 'Note') {
- window.open(this.item.id)
- } else if (this.type === 'Announce') {
- window.open(this.item.object)
- } else {
- logger.warn("Don't know what to do with posts of type " + this.type, { post: this.item })
- }
- } else {
- this.$router.push({
- name: 'single-post',
- params: {
- account: this.item.account.display_name,
- id: this.item.id,
- type: 'single-post',
- },
- })
+ logger.warn("Don't know what to do with posts of type " + this.type, { post: this.item })
+ return
}
+
+ this.$router.push({
+ name: 'single-post',
+ params: {
+ account: this.item.account.display_name,
+ id: this.item.id,
+ type: 'single-post',
+ },
+ })
},
userDisplayName(actorInfo) {
return actorInfo.name !== '' ? actorInfo.name : actorInfo.preferredUsername
@@ -236,7 +230,7 @@ export default {
},
boost() {
const params = {
- post: this.item,
+ status: this.item,
parentAnnounce: this.reblog,
}
if (this.isBoosted) {
@@ -250,7 +244,7 @@ export default {
},
like() {
const params = {
- post: this.item,
+ status: this.item,
parentAnnounce: this.reblog,
}
if (this.isLiked) {
@@ -330,6 +324,11 @@ export default {
margin-left: -13px;
height: 44px;
display: flex;
+ margin: 4px;
+
+ .button-vue:hover {
+ background: var(--color-background-dark);
+ }
.post-actions-more {
position: relative;
diff --git a/src/store/timeline.js b/src/store/timeline.js
index 4b67ef99..e972c0a1 100644
--- a/src/store/timeline.js
+++ b/src/store/timeline.js
@@ -33,13 +33,17 @@ import logger from '../services/logger.js'
const state = {
/**
- * @type {Object<string, import('../types/Mastodon.js').Status>} timeline - The posts' collection
+ * @type {Object<string, import('../types/Mastodon.js').Status>} List of locally known statuses
*/
- timeline: {},
+ statuses: {},
/**
- * @type {Object<string, import('../types/Mastodon.js').Status>} timeline - The parents posts' collection
+ * @type {string[]} timeline - The statuses' collection
*/
- parentsTimeline: {},
+ timeline: [],
+ /**
+ * @type {string[]} parentsTimeline - The parents statuses' collection
+ */
+ parentsTimeline: [],
/**
* @type {string} type - Timeline's type: 'home', 'single-post',...
*/
@@ -49,6 +53,7 @@ const state = {
* @property {string} params.account ???
* @property {string} params.id
* @property {string} params.type ???
+ * @property {string?} params.singlePost ???
*/
params: {},
/**
@@ -68,26 +73,61 @@ const state = {
const mutations = {
/**
* @param state
+ * @param {import ('../types/Mastodon.js').Status} status
+ */
+ addToStatuses(state, status) {
+ Vue.set(state.statuses, status.id, status)
+ },
+ /**
+ * @param state
* @param {import ('../types/Mastodon.js').Status[]|import('../types/Mastodon.js').Context} data
*/
addToTimeline(state, data) {
if (Array.isArray(data)) {
- data.forEach((post) => Vue.set(state.timeline, post.id, post))
+ data.forEach(status => Vue.set(state.statuses, status.id, status))
+ data
+ .filter(status => state.timeline.indexOf(status.id) === -1)
+ .forEach(status => state.timeline.push(status.id))
} else {
- data.descendants.forEach((post) => Vue.set(state.timeline, post.id, post))
- data.ancestors.forEach((post) => Vue.set(state.parentsTimeline, post.id, post))
+ data.descendants.forEach(status => Vue.set(state.statuses, status.id, status))
+ data.ancestors.forEach(status => Vue.set(state.statuses, status.id, status))
+
+ data.descendants
+ .filter(status => state.timeline.indexOf(status.id) === -1)
+ .forEach(status => state.timeline.push(status.id))
+ data.ancestors
+ .filter(status => state.parentsTimeline.indexOf(status.id) === -1)
+ .forEach(status => state.parentsTimeline.push(status.id))
}
},
/**
* @param state
- * @param {import('../types/Mastodon.js').Status} post
+ * @param {import ('../types/Mastodon.js').Status[]} data
+ */
+ updateInTimelines(state, data) {
+ data.forEach((status) => {
+ if (state.statuses[status.id] !== undefined) {
+ Vue.set(state.statuses, status.id, status)
+ }
+ })
+ },
+ /**
+ * @param state
+ * @param {import('../types/Mastodon.js').Status} status
*/
- removePost(state, post) {
- Vue.delete(state.timeline, post.id)
+ removeStatusf(state, status) {
+ const timelineIndex = state.timeline.indexOf(status.id)
+ if (timelineIndex !== -1) {
+ state.timeline.splice(timelineIndex, 1)
+ }
+ const parentsTimelineIndex = state.parentsTimeline.indexOf(status.id)
+ if (timelineIndex !== -1) {
+ state.parentsTimeline.splice(parentsTimelineIndex, 1)
+ }
},
resetTimeline(state) {
- state.timeline = {}
- state.parentsTimeline = {}
+ state.timeline = []
+ state.parentsTimeline = []
},
/**
* @param state
@@ -116,53 +156,41 @@ const mutations = {
/**
* @param state
* @param {object} root0
- * @param {import('../types/Mastodon.js').Status} root0.post
+ * @param {import('../types/Mastodon.js').Status} root0.status
*/
- likePost(state, { post }) {
- if (state.timeline[post.id] !== undefined) {
- Vue.set(state.timeline[post.id], 'favourited', true)
- }
- if (post.reblog !== null && state.timeline[post.reblog.id] !== undefined) {
- Vue.set(state.timeline[post.reblog.id], 'favourited', true)
+ likeStatus(state, { status }) {
+ if (state.statuses[status.id] !== undefined) {
+ Vue.set(state.statuses[status.id], 'favourited', true)
}
},
/**
* @param state
* @param {object} root0
- * @param {import('../types/Mastodon.js').Status} root0.post
+ * @param {import('../types/Mastodon.js').Status} root0.status
*/
- unlikePost(state, { post }) {
- if (state.timeline[post.id] !== undefined) {
- Vue.set(state.timeline[post.id], 'favourited', false)
- }
- if (post.reblog !== null && state.timeline[post.reblog.id] !== undefined) {
- Vue.set(state.timeline[post.reblog.id], 'favourited', false)
+ unlikeStatus(state, { status }) {
+ if (state.statuses[status.id] !== undefined) {
+ Vue.set(state.statuses[status.id], 'favourited', false)
}
},
/**
* @param state
* @param {object} root0
- * @param {import('../types/Mastodon.js').Status} root0.post
+ * @param {import('../types/Mastodon.js').Status} root0.status
*/
- boostPost(state, { post }) {
- if (state.timeline[post.id] !== undefined) {
- Vue.set(state.timeline[post.id], 'reblogged', true)
- }
- if (post.reblog !== null && state.timeline[post.reblog.id] !== undefined) {
- Vue.set(state.timeline[post.reblog.id], 'reblogged', true)
+ boostStatus(state, { status }) {
+ if (state.statuses[status.id] !== undefined) {
+ Vue.set(state.statuses[status.id], 'reblogged', true)
}
},
/**
* @param state
* @param {object} root0
- * @param {import('../types/Mastodon.js').Status} root0.post
+ * @param {import('../types/Mastodon.js').Status} root0.status
*/
- unboostPost(state, { post }) {
- if (state.timeline[post.id] !== undefined) {
- Vue.set(state.timeline[post.id], 'reblogged', false)
- }
- if (post.reblog !== null && state.timeline[post.reblog.id] !== undefined) {
- Vue.set(state.timeline[post.reblog.id], 'reblogged', false)
+ unboostStatus(state, { status }) {
+ if (state.statuses[status.id] !== undefined) {
+ Vue.set(state.statuses[status.id], 'reblogged', false)
}
},
}
@@ -173,23 +201,24 @@ const getters = {
return state.composerDisplayStatus
},
getTimeline(state) {
- return Object.values(state.timeline).sort(function(a, b) {
- return new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
- })
+ return state.timeline
+ .map(statusId => state.statuses[statusId])
+ .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())
},
getParentsTimeline(state) {
- return Object.values(state.parentsTimeline).sort(function(a, b) {
- return new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
- })
+ return state.parentsTimeline
+ .map(statusId => state.statuses[statusId])
+ .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())
+ },
+ getSinglePost(state) {
+ return state.statuses[state.params.singlePost]
},
getPostFromTimeline(state) {
- return (postId) => {
- if (state.timeline[postId] !== undefined) {
- return state.timeline[postId]
- } else if (state.parentsTimeline[postId] !== undefined) {
- return state.parentsTimeline[postId]
+ return (/** @type {string} */ statusId) => {
+ if (state.statuses[statusId] !== undefined) {
+ return state.statuses[statusId]
} else {
- logger.warn('Could not find post in timeline', { postId })
+ logger.warn('Could not find status in timeline', { statusId })
}
}
},
@@ -234,108 +263,108 @@ const actions = {
},
/**
* @param context
- * @param {import('../types/Mastodon.js').Status} post
+ * @param {import('../types/Mastodon.js').Status} status
*/
- async post(context, post) {
+ async post(context, status) {
try {
- const { data } = await axios.post(generateUrl('apps/social/api/v1/statuses'), post)
+ const { data } = await axios.post(generateUrl('apps/social/api/v1/statuses'), status)
logger.info('Post created', data.id)
} catch (error) {
- showError('Failed to create a post')
- logger.error('Failed to create a post', { error })
+ showError('Failed to create a status')
+ logger.error('Failed to create a status', { error })
}
},
/**
* @param context
- * @param {import('../types/Mastodon.js').Status} post
+ * @param {import('../types/Mastodon.js').Status} status
*/
- async postDelete(context, post) {
+ async postDelete(context, status) {
try {
- context.commit('removePost', post)
- const response = await axios.delete(generateUrl(`apps/social/api/v1/post?id=${post.uri}`))
+ context.commit('removeStatusf', status)
+ const response = await axios.delete(generateUrl(`apps/social/api/v1/post?id=${status.uri}`))
logger.info('Post deleted with token ' + response.data.result.token)
} catch (error) {
- context.commit('addToTimeline', [post])
- showError('Failed to delete the post')
- logger.error('Failed to delete the post', { error })
+ context.commit('updateInTimelines', [status])
+ showError('Failed to delete the status')
+ logger.error('Failed to delete the status', { error })
}
},
/**
* @param context
* @param {object} root0
- * @param {import('../types/Mastodon.js').Status} root0.post
+ * @param {import('../types/Mastodon.js').Status} root0.status
*/
- async postLike(context, { post }) {
+ async postLike(context, { status }) {
try {
- context.commit('likePost', { post })
- const response = await axios.post(generateUrl(`apps/social/api/v1/statuses/${post.id}/favourite`))
+ context.commit('likeStatus', { status })
+ const response = await axios.post(generateUrl(`apps/social/api/v1/statuses/${status.id}/favourite`))
logger.info('Post liked')
- context.commit('addToTimeline', [response.data])
+ context.commit('updateInTimelines', [response.data])
return response
} catch (error) {
- context.commit('unlikePost', { post })
- showError('Failed to like post')
- logger.error('Failed to like post', { error })
+ context.commit('unlikeStatus', { status })
+ showError('Failed to like status')
+ logger.error('Failed to like status', { error })
}
},
/**
* @param context
* @param {object} root0
- * @param {import('../types/Mastodon.js').Status} root0.post
+ * @param {import('../types/Mastodon.js').Status} root0.status
*/
- async postUnlike(context, { post }) {
+ async postUnlike(context, { status }) {
try {
- // Remove post from list if we are in the 'liked' timeline
+ // Remove status from list if we are in the 'liked' timeline
if (state.type === 'liked') {
- context.commit('removePost', post)
+ context.commit('removeStatusf', status)
}
- context.commit('unlikePost', { post })
- const response = await axios.post(generateUrl(`apps/social/api/v1/statuses/${post.id}/unfavourite`))
+ context.commit('unlikeStatus', { status })
+ const response = await axios.post(generateUrl(`apps/social/api/v1/statuses/${status.id}/unfavourite`))
logger.info('Post unliked')
- context.commit('addToTimeline', [response.data])
+ context.commit('updateInTimelines', [response.data])
return response
} catch (error) {
- // Readd post from list if we are in the 'liked' timeline
+ // Readd status from list if we are in the 'liked' timeline
if (state.type === 'liked') {
- context.commit('addToTimeline', [post])
+ context.commit('addToTimeline', [status])
}
- context.commit('likePost', { post })
- showError('Failed to unlike post')
- logger.error('Failed to unlike post', { error })
+ context.commit('likeStatus', { status })
+ showError('Failed to unlike status')
+ logger.error('Failed to unlike status', { error })
}
},
/**
* @param context
* @param {object} root0
- * @param {import('../types/Mastodon.js').Status} root0.post
+ * @param {import('../types/Mastodon.js').Status} root0.status
*/
- async postBoost(context, { post }) {
+ async postBoost(context, { status }) {
try {
- context.commit('boostPost', { post })
- const response = await axios.post(generateUrl(`apps/social/api/v1/statuses/${post.id}/reblog`))
+ context.commit('boostStatus', { status })
+ const response = await axios.post(generateUrl(`apps/social/api/v1/statuses/${status.id}/reblog`))
logger.info('Post boosted')
- context.commit('addToTimeline', [response.data])
+ context.commit('updateInTimelines', [response.data])
return response
} catch (error) {
- context.commit('unboostPost', { post })
- showError('Failed to create a boost post')
- logger.error('Failed to create a boost post', { error })
+ context.commit('unboostStatus', { status })
+ showError('Failed to create a boost status')
+ logger.error('Failed to create a boost status', { error })
}
},
/**
* @param context
* @param {object} root0
- * @param {import('../types/Mastodon.js').Status} root0.post
+ * @param {import('../types/Mastodon.js').Status} root0.status
*/
- async postUnBoost(context, { post }) {
+ async postUnBoost(context, { status }) {
try {
- context.commit('unboostPost', { post })
- const response = await axios.post(generateUrl(`apps/social/api/v1/statuses/${post.id}/unreblog`))
+ context.commit('unboostStatus', { status })
+ const response = await axios.post(generateUrl(`apps/social/api/v1/statuses/${status.id}/unreblog`))
logger.info('Boost deleted')
- context.commit('addToTimeline', [response.data])
+ context.commit('updateInTimelines', [response.data])
return response
} catch (error) {
- context.commit('boostPost', { post })
+ context.commit('boostStatus', { status })
showError('Failed to delete the boost')
logger.error('Failed to delete the boost', { error })
}
diff --git a/src/views/Timeline.vue b/src/views/Timeline.vue
index 2ee0fe5c..2a8958c0 100644
--- a/src/views/Timeline.vue
+++ b/src/views/Timeline.vue
@@ -25,10 +25,17 @@
</div>
</div>
</transition>
+
<Composer v-if="type !== 'notifications' && type !== 'single-post'" :default-visibility="type === 'direct' ? 'direct' : undefined" />
+
<h2 v-if="type === 'tags'">
#{{ $route.params.tag }}
</h2>
+
+ <h2 v-if="type === 'notifications'">
+ {{ t('social', 'Notifications') }}
+ </h2>
+
<TimelineList :type="type" />
</div>
</template>
diff --git a/src/views/TimelineSinglePost.vue b/src/views/TimelineSinglePost.vue
index af9bcf90..f7e4b45f 100644
--- a/src/views/TimelineSinglePost.vue
+++ b/src/views/TimelineSinglePost.vue
@@ -7,8 +7,9 @@
:reverse-order="true" />
<TimelineEntry ref="mainPost"
class="main-post"
- :item="mainPost"
- type="single-post" />
+ :item="singlePost"
+ type="single-post"
+ element="div" />
<TimelineList v-if="timeline" class="descendants" :type="$route.params.type" />
</div>
</template>
@@ -36,11 +37,14 @@ export default {
],
data() {
return {
- mainPost: {},
uid: this.$route.params.account,
}
},
computed: {
+ /** @return {Status?} */
+ singlePost() {
+ return this.$store.getters.getSinglePost
+ },
/**
* @description Tells whether Composer shall be displayed or not
* @return {boolean}
@@ -79,15 +83,17 @@ export default {
},
},
async beforeMount() {
- this.mainPost = this.$store.getters.getPostFromTimeline(this.$route.params.id) || loadState('social', 'item')
+ const singlePost = this.$store.getters.getPostFromTimeline(this.$route.params.id) || loadState('social', 'item')
// Fetch single post timeline
+ this.$store.commit('addToStatuses', singlePost)
this.$store.dispatch('changeTimelineType', {
type: 'single-post',
params: {
account: this.account,
id: this.$route.params.id,
type: 'single-post',
+ singlePost: this.$route.params.id || loadState('social', 'item').id,
},
})