Merge branch 'issue-433-status-reply-form' into 'develop'
Issue 433 status reply form Closes #433 See merge request pleroma/pleroma-fe!674
This commit is contained in:
commit
7e8c2acc98
9 changed files with 102 additions and 73 deletions
|
@ -1,5 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<conversation :collapsable="false" :statusoid="statusoid"></conversation>
|
<conversation
|
||||||
|
:collapsable="false"
|
||||||
|
isPage="true"
|
||||||
|
:statusoid="statusoid"
|
||||||
|
></conversation>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./conversation-page.js"></script>
|
<script src="./conversation-page.js"></script>
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import { reduce, filter } from 'lodash'
|
import { reduce, filter, findIndex } from 'lodash'
|
||||||
import { set } from 'vue'
|
import { set } from 'vue'
|
||||||
import Status from '../status/status.vue'
|
import Status from '../status/status.vue'
|
||||||
|
|
||||||
const sortById = (a, b) => {
|
const sortById = (a, b) => {
|
||||||
const seqA = Number(a.id)
|
const idA = a.type === 'retweet' ? a.retweeted_status.id : a.id
|
||||||
const seqB = Number(b.id)
|
const idB = b.type === 'retweet' ? b.retweeted_status.id : b.id
|
||||||
|
const seqA = Number(idA)
|
||||||
|
const seqB = Number(idB)
|
||||||
const isSeqA = !Number.isNaN(seqA)
|
const isSeqA = !Number.isNaN(seqA)
|
||||||
const isSeqB = !Number.isNaN(seqB)
|
const isSeqB = !Number.isNaN(seqB)
|
||||||
if (isSeqA && isSeqB) {
|
if (isSeqA && isSeqB) {
|
||||||
|
@ -14,12 +16,19 @@ const sortById = (a, b) => {
|
||||||
} else if (!isSeqA && isSeqB) {
|
} else if (!isSeqA && isSeqB) {
|
||||||
return 1
|
return 1
|
||||||
} else {
|
} else {
|
||||||
return a.id < b.id ? -1 : 1
|
return idA < idB ? -1 : 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const sortAndFilterConversation = (conversation) => {
|
const sortAndFilterConversation = (conversation, statusoid) => {
|
||||||
conversation = filter(conversation, (status) => status.type !== 'retweet')
|
if (statusoid.type === 'retweet') {
|
||||||
|
conversation = filter(
|
||||||
|
conversation,
|
||||||
|
(status) => (status.type === 'retweet' || status.id !== statusoid.retweeted_status.id)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
conversation = filter(conversation, (status) => status.type !== 'retweet')
|
||||||
|
}
|
||||||
return conversation.filter(_ => _).sort(sortById)
|
return conversation.filter(_ => _).sort(sortById)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,13 +36,20 @@ const conversation = {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
highlight: null,
|
highlight: null,
|
||||||
|
expanded: false,
|
||||||
converationStatusIds: []
|
converationStatusIds: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: [
|
props: [
|
||||||
'statusoid',
|
'statusoid',
|
||||||
'collapsable'
|
'collapsable',
|
||||||
|
'isPage'
|
||||||
],
|
],
|
||||||
|
created () {
|
||||||
|
if (this.isPage) {
|
||||||
|
this.fetchConversation()
|
||||||
|
}
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
status () {
|
status () {
|
||||||
return this.statusoid
|
return this.statusoid
|
||||||
|
@ -59,12 +75,22 @@ const conversation = {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.isExpanded) {
|
||||||
|
return [this.status]
|
||||||
|
}
|
||||||
|
|
||||||
const statusesObject = this.$store.state.statuses.allStatusesObject
|
const statusesObject = this.$store.state.statuses.allStatusesObject
|
||||||
const conversation = this.idsToShow.reduce((acc, id) => {
|
const conversation = this.idsToShow.reduce((acc, id) => {
|
||||||
acc.push(statusesObject[id])
|
acc.push(statusesObject[id])
|
||||||
return acc
|
return acc
|
||||||
}, [])
|
}, [])
|
||||||
return sortAndFilterConversation(conversation)
|
|
||||||
|
const statusIndex = findIndex(conversation, { id: this.statusId })
|
||||||
|
if (statusIndex !== -1) {
|
||||||
|
conversation[statusIndex] = this.status
|
||||||
|
}
|
||||||
|
|
||||||
|
return sortAndFilterConversation(conversation, this.status)
|
||||||
},
|
},
|
||||||
replies () {
|
replies () {
|
||||||
let i = 1
|
let i = 1
|
||||||
|
@ -82,16 +108,21 @@ const conversation = {
|
||||||
i++
|
i++
|
||||||
return result
|
return result
|
||||||
}, {})
|
}, {})
|
||||||
|
},
|
||||||
|
isExpanded () {
|
||||||
|
return this.expanded || this.isPage
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
Status
|
Status
|
||||||
},
|
},
|
||||||
created () {
|
|
||||||
this.fetchConversation()
|
|
||||||
},
|
|
||||||
watch: {
|
watch: {
|
||||||
'$route': 'fetchConversation'
|
'$route': 'fetchConversation',
|
||||||
|
expanded (value) {
|
||||||
|
if (value) {
|
||||||
|
this.fetchConversation()
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fetchConversation () {
|
fetchConversation () {
|
||||||
|
@ -117,10 +148,19 @@ const conversation = {
|
||||||
return this.replies[id] || []
|
return this.replies[id] || []
|
||||||
},
|
},
|
||||||
focused (id) {
|
focused (id) {
|
||||||
return id === this.statusId
|
return (this.isExpanded) && id === this.status.id
|
||||||
},
|
},
|
||||||
setHighlight (id) {
|
setHighlight (id) {
|
||||||
this.highlight = id
|
this.highlight = id
|
||||||
|
},
|
||||||
|
getHighlight () {
|
||||||
|
return this.isExpanded ? this.highlight : null
|
||||||
|
},
|
||||||
|
toggleExpanded () {
|
||||||
|
this.expanded = !this.expanded
|
||||||
|
if (!this.expanded) {
|
||||||
|
this.setHighlight(null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,42 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="timeline panel panel-default">
|
<div class="timeline panel-default" :class="[isExpanded ? 'panel' : 'panel-disabled']">
|
||||||
<div class="panel-heading conversation-heading">
|
<div v-if="isExpanded" class="panel-heading conversation-heading">
|
||||||
<span class="title"> {{ $t('timeline.conversation') }} </span>
|
<span class="title"> {{ $t('timeline.conversation') }} </span>
|
||||||
<span v-if="collapsable">
|
<span v-if="collapsable">
|
||||||
<a href="#" @click.prevent="$emit('toggleExpanded')">{{ $t('timeline.collapse') }}</a>
|
<a href="#" @click.prevent="toggleExpanded">{{ $t('timeline.collapse') }}</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<status
|
||||||
<div class="timeline">
|
v-for="status in conversation"
|
||||||
<status
|
@goto="setHighlight"
|
||||||
v-for="status in conversation"
|
@toggleExpanded="toggleExpanded"
|
||||||
@goto="setHighlight" :key="status.id"
|
:key="status.id"
|
||||||
:inlineExpanded="collapsable" :statusoid="status"
|
:inlineExpanded="collapsable"
|
||||||
:expandable='false' :focused="focused(status.id)"
|
:statusoid="status"
|
||||||
:inConversation='true'
|
:expandable='!expanded'
|
||||||
:highlight="highlight"
|
:focused="focused(status.id)"
|
||||||
:replies="getReplies(status.id)"
|
:inConversation="isExpanded"
|
||||||
class="status-fadein">
|
:highlight="getHighlight()"
|
||||||
</status>
|
:replies="getReplies(status.id)"
|
||||||
</div>
|
class="status-fadein panel-body"
|
||||||
</div>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./conversation.js"></script>
|
<script src="./conversation.js"></script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
|
.timeline {
|
||||||
|
.panel-disabled {
|
||||||
|
.status-el {
|
||||||
|
border-left: none;
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
border-bottom-style: solid;
|
||||||
|
border-color: var(--border, $fallback--border);
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -310,7 +310,6 @@ const Status = {
|
||||||
this.replying = !this.replying
|
this.replying = !this.replying
|
||||||
},
|
},
|
||||||
gotoOriginal (id) {
|
gotoOriginal (id) {
|
||||||
// only handled by conversation, not status_or_conversation
|
|
||||||
if (this.inConversation) {
|
if (this.inConversation) {
|
||||||
this.$emit('goto', id)
|
this.$emit('goto', id)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div v-if="retweet && !noHeading" :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" :src="statusoid.user.profile_image_url_original"/>
|
<UserAvatar class="media-left" v-if="retweet" :betterShadow="betterShadow" :src="statusoid.user.profile_image_url_original"/>
|
||||||
<div class="media-body faint">
|
<div class="media-body faint">
|
||||||
<span class="user-name">
|
<span class="user-name">
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div :class="[userClass, { highlighted: userStyle, 'is-retweet': retweet }]" :style="[ userStyle ]" class="media status">
|
<div :class="[userClass, { highlighted: userStyle, 'is-retweet': retweet && !inConversation }]" :style="[ userStyle ]" class="media status">
|
||||||
<div v-if="!noHeading" class="media-left">
|
<div v-if="!noHeading" class="media-left">
|
||||||
<router-link :to="userProfileLink" @click.stop.prevent.capture.native="toggleUserExpanded">
|
<router-link :to="userProfileLink" @click.stop.prevent.capture.native="toggleUserExpanded">
|
||||||
<UserAvatar :compact="compact" :betterShadow="betterShadow" :src="status.user.profile_image_url_original"/>
|
<UserAvatar :compact="compact" :betterShadow="betterShadow" :src="status.user.profile_image_url_original"/>
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
import Status from '../status/status.vue'
|
|
||||||
import Conversation from '../conversation/conversation.vue'
|
|
||||||
|
|
||||||
const statusOrConversation = {
|
|
||||||
props: ['statusoid'],
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
expanded: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
Status,
|
|
||||||
Conversation
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
toggleExpanded () {
|
|
||||||
this.expanded = !this.expanded
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default statusOrConversation
|
|
|
@ -1,14 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<conversation v-if="expanded" @toggleExpanded="toggleExpanded" :collapsable="true" :statusoid="statusoid"></conversation>
|
|
||||||
<status v-if="!expanded" @toggleExpanded="toggleExpanded" :expandable="true" :inConversation="false" :focused="false" :statusoid="statusoid"></status>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script src="./status_or_conversation.js"></script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.spacer {
|
|
||||||
height: 1em
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,6 +1,6 @@
|
||||||
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 StatusOrConversation from '../status_or_conversation/status_or_conversation.vue'
|
import Conversation from '../conversation/conversation.vue'
|
||||||
import { throttle } from 'lodash'
|
import { throttle } from 'lodash'
|
||||||
|
|
||||||
const Timeline = {
|
const Timeline = {
|
||||||
|
@ -43,7 +43,7 @@ const Timeline = {
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
Status,
|
Status,
|
||||||
StatusOrConversation
|
Conversation
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
const store = this.$store
|
const store = this.$store
|
||||||
|
|
|
@ -16,7 +16,13 @@
|
||||||
</div>
|
</div>
|
||||||
<div :class="classes.body">
|
<div :class="classes.body">
|
||||||
<div class="timeline">
|
<div class="timeline">
|
||||||
<status-or-conversation v-for="status in timeline.visibleStatuses" :key="status.id" v-bind:statusoid="status" class="status-fadein"></status-or-conversation>
|
<conversation
|
||||||
|
v-for="status in timeline.visibleStatuses"
|
||||||
|
class="status-fadein"
|
||||||
|
:key="status.id"
|
||||||
|
:statusoid="status"
|
||||||
|
:collapsable="true"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div :class="classes.footer">
|
<div :class="classes.footer">
|
||||||
|
|
Loading…
Reference in a new issue