forked from AkkomaGang/akkoma-fe
Merge branch 'feat/emoji-reactions' into 'develop'
Emoji reactions See merge request pleroma/pleroma-fe!1049
This commit is contained in:
commit
73253b87bf
12 changed files with 407 additions and 2 deletions
|
@ -150,6 +150,7 @@ const conversation = {
|
||||||
if (!id) return
|
if (!id) return
|
||||||
this.highlight = id
|
this.highlight = id
|
||||||
this.$store.dispatch('fetchFavsAndRepeats', id)
|
this.$store.dispatch('fetchFavsAndRepeats', id)
|
||||||
|
this.$store.dispatch('fetchEmojiReactionsBy', id)
|
||||||
},
|
},
|
||||||
getHighlight () {
|
getHighlight () {
|
||||||
return this.isExpanded ? this.highlight : null
|
return this.isExpanded ? this.highlight : null
|
||||||
|
|
32
src/components/emoji_reactions/emoji_reactions.js
Normal file
32
src/components/emoji_reactions/emoji_reactions.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
|
||||||
|
const EmojiReactions = {
|
||||||
|
name: 'EmojiReactions',
|
||||||
|
props: ['status'],
|
||||||
|
computed: {
|
||||||
|
emojiReactions () {
|
||||||
|
return this.status.emoji_reactions
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
reactedWith (emoji) {
|
||||||
|
const user = this.$store.state.users.currentUser
|
||||||
|
const reaction = this.status.emoji_reactions.find(r => r.emoji === emoji)
|
||||||
|
return reaction.accounts && reaction.accounts.find(u => u.id === user.id)
|
||||||
|
},
|
||||||
|
reactWith (emoji) {
|
||||||
|
this.$store.dispatch('reactWithEmoji', { id: this.status.id, emoji })
|
||||||
|
},
|
||||||
|
unreact (emoji) {
|
||||||
|
this.$store.dispatch('unreactWithEmoji', { id: this.status.id, emoji })
|
||||||
|
},
|
||||||
|
emojiOnClick (emoji, event) {
|
||||||
|
if (this.reactedWith(emoji)) {
|
||||||
|
this.unreact(emoji)
|
||||||
|
} else {
|
||||||
|
this.reactWith(emoji)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EmojiReactions
|
51
src/components/emoji_reactions/emoji_reactions.vue
Normal file
51
src/components/emoji_reactions/emoji_reactions.vue
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
<template>
|
||||||
|
<div class="emoji-reactions">
|
||||||
|
<button
|
||||||
|
v-for="(reaction) in emojiReactions"
|
||||||
|
:key="reaction.emoji"
|
||||||
|
class="emoji-reaction btn btn-default"
|
||||||
|
:class="{ 'picked-reaction': reactedWith(reaction.emoji) }"
|
||||||
|
@click="emojiOnClick(reaction.emoji, $event)"
|
||||||
|
>
|
||||||
|
<span>{{ reaction.emoji }}</span>
|
||||||
|
<span>{{ reaction.count }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./emoji_reactions.js" ></script>
|
||||||
|
<style lang="scss">
|
||||||
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
|
.emoji-reactions {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 0.25em;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-reaction {
|
||||||
|
padding: 0 0.5em;
|
||||||
|
margin-right: 0.5em;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
&:first-child {
|
||||||
|
margin-right: 0.25em;
|
||||||
|
}
|
||||||
|
&:last-child {
|
||||||
|
width: 1.5em;
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.picked-reaction {
|
||||||
|
border: 1px solid var(--link, $fallback--link);
|
||||||
|
margin-left: -1px; // offset the border, can't use inset shadows either
|
||||||
|
margin-right: calc(0.5em - 1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
43
src/components/react_button/react_button.js
Normal file
43
src/components/react_button/react_button.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
|
||||||
|
const ReactButton = {
|
||||||
|
props: ['status', 'loggedIn'],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
showTooltip: false,
|
||||||
|
filterWord: '',
|
||||||
|
popperOptions: {
|
||||||
|
modifiers: {
|
||||||
|
preventOverflow: { padding: { top: 50 }, boundariesElement: 'viewport' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
openReactionSelect () {
|
||||||
|
this.showTooltip = true
|
||||||
|
this.filterWord = ''
|
||||||
|
},
|
||||||
|
closeReactionSelect () {
|
||||||
|
this.showTooltip = false
|
||||||
|
},
|
||||||
|
addReaction (event, emoji) {
|
||||||
|
this.$store.dispatch('reactWithEmoji', { id: this.status.id, emoji })
|
||||||
|
this.closeReactionSelect()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
commonEmojis () {
|
||||||
|
return ['❤️', '😠', '👀', '😂', '🔥']
|
||||||
|
},
|
||||||
|
emojis () {
|
||||||
|
if (this.filterWord !== '') {
|
||||||
|
return this.$store.state.instance.emoji.filter(emoji => emoji.displayText.includes(this.filterWord))
|
||||||
|
}
|
||||||
|
return this.$store.state.instance.emoji || []
|
||||||
|
},
|
||||||
|
...mapGetters(['mergedConfig'])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ReactButton
|
109
src/components/react_button/react_button.vue
Normal file
109
src/components/react_button/react_button.vue
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
<template>
|
||||||
|
<v-popover
|
||||||
|
:popper-options="popperOptions"
|
||||||
|
:open="showTooltip"
|
||||||
|
trigger="manual"
|
||||||
|
placement="top"
|
||||||
|
class="react-button-popover"
|
||||||
|
@hide="closeReactionSelect"
|
||||||
|
>
|
||||||
|
<div slot="popover">
|
||||||
|
<div class="reaction-picker-filter">
|
||||||
|
<input
|
||||||
|
v-model="filterWord"
|
||||||
|
:placeholder="$t('emoji.search_emoji')"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="reaction-picker">
|
||||||
|
<span
|
||||||
|
v-for="emoji in commonEmojis"
|
||||||
|
:key="emoji"
|
||||||
|
class="emoji-button"
|
||||||
|
@click="addReaction($event, emoji)"
|
||||||
|
>
|
||||||
|
{{ emoji }}
|
||||||
|
</span>
|
||||||
|
<div class="reaction-picker-divider" />
|
||||||
|
<span
|
||||||
|
v-for="(emoji, key) in emojis"
|
||||||
|
:key="key"
|
||||||
|
class="emoji-button"
|
||||||
|
@click="addReaction($event, emoji.replacement)"
|
||||||
|
>
|
||||||
|
{{ emoji.replacement }}
|
||||||
|
</span>
|
||||||
|
<div class="reaction-bottom-fader" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="loggedIn"
|
||||||
|
@click.prevent="openReactionSelect"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="icon-smile button-icon add-reaction-button"
|
||||||
|
:title="$t('tool_tip.add_reaction')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</v-popover>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script src="./react_button.js" ></script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import '../../_variables.scss';
|
||||||
|
|
||||||
|
.reaction-picker-filter {
|
||||||
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reaction-picker-divider {
|
||||||
|
height: 1px;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0.5em;
|
||||||
|
background-color: var(--border, $fallback--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reaction-picker {
|
||||||
|
width: 10em;
|
||||||
|
height: 9em;
|
||||||
|
font-size: 1.5em;
|
||||||
|
overflow-y: scroll;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 0.5em;
|
||||||
|
text-align: center;
|
||||||
|
align-content: flex-start;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
mask: linear-gradient(to top, white 0, transparent 100%) bottom no-repeat,
|
||||||
|
linear-gradient(to bottom, white 0, transparent 100%) top no-repeat,
|
||||||
|
linear-gradient(to top, white, white);
|
||||||
|
transition: mask-size 150ms;
|
||||||
|
mask-size: 100% 20px, 100% 20px, auto;
|
||||||
|
// Autoprefixed seem to ignore this one, and also syntax is different
|
||||||
|
-webkit-mask-composite: xor;
|
||||||
|
mask-composite: exclude;
|
||||||
|
|
||||||
|
.emoji-button {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
flex-basis: 20%;
|
||||||
|
line-height: 1.5em;
|
||||||
|
align-content: center;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.25);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-reaction-button {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $fallback--text;
|
||||||
|
color: var(--text, $fallback--text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
|
@ -1,5 +1,6 @@
|
||||||
import Attachment from '../attachment/attachment.vue'
|
import Attachment from '../attachment/attachment.vue'
|
||||||
import FavoriteButton from '../favorite_button/favorite_button.vue'
|
import FavoriteButton from '../favorite_button/favorite_button.vue'
|
||||||
|
import ReactButton from '../react_button/react_button.vue'
|
||||||
import RetweetButton from '../retweet_button/retweet_button.vue'
|
import RetweetButton from '../retweet_button/retweet_button.vue'
|
||||||
import Poll from '../poll/poll.vue'
|
import Poll from '../poll/poll.vue'
|
||||||
import ExtraButtons from '../extra_buttons/extra_buttons.vue'
|
import ExtraButtons from '../extra_buttons/extra_buttons.vue'
|
||||||
|
@ -11,6 +12,7 @@ import LinkPreview from '../link-preview/link-preview.vue'
|
||||||
import AvatarList from '../avatar_list/avatar_list.vue'
|
import AvatarList from '../avatar_list/avatar_list.vue'
|
||||||
import Timeago from '../timeago/timeago.vue'
|
import Timeago from '../timeago/timeago.vue'
|
||||||
import StatusPopover from '../status_popover/status_popover.vue'
|
import StatusPopover from '../status_popover/status_popover.vue'
|
||||||
|
import EmojiReactions from '../emoji_reactions/emoji_reactions.vue'
|
||||||
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
|
||||||
import fileType from 'src/services/file_type/file_type.service'
|
import fileType from 'src/services/file_type/file_type.service'
|
||||||
import { processHtml } from 'src/services/tiny_post_html_processor/tiny_post_html_processor.service.js'
|
import { processHtml } from 'src/services/tiny_post_html_processor/tiny_post_html_processor.service.js'
|
||||||
|
@ -319,6 +321,7 @@ const Status = {
|
||||||
components: {
|
components: {
|
||||||
Attachment,
|
Attachment,
|
||||||
FavoriteButton,
|
FavoriteButton,
|
||||||
|
ReactButton,
|
||||||
RetweetButton,
|
RetweetButton,
|
||||||
ExtraButtons,
|
ExtraButtons,
|
||||||
PostStatusForm,
|
PostStatusForm,
|
||||||
|
@ -329,7 +332,8 @@ const Status = {
|
||||||
LinkPreview,
|
LinkPreview,
|
||||||
AvatarList,
|
AvatarList,
|
||||||
Timeago,
|
Timeago,
|
||||||
StatusPopover
|
StatusPopover,
|
||||||
|
EmojiReactions
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
visibilityIcon (visibility) {
|
visibilityIcon (visibility) {
|
||||||
|
|
|
@ -354,6 +354,10 @@
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
|
<EmojiReactions
|
||||||
|
:status="status"
|
||||||
|
/>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="!noHeading && !isPreview"
|
v-if="!noHeading && !isPreview"
|
||||||
class="status-actions media-body"
|
class="status-actions media-body"
|
||||||
|
@ -382,6 +386,10 @@
|
||||||
:logged-in="loggedIn"
|
:logged-in="loggedIn"
|
||||||
:status="status"
|
:status="status"
|
||||||
/>
|
/>
|
||||||
|
<ReactButton
|
||||||
|
:logged-in="loggedIn"
|
||||||
|
:status="status"
|
||||||
|
/>
|
||||||
<extra-buttons
|
<extra-buttons
|
||||||
:status="status"
|
:status="status"
|
||||||
@onError="showError"
|
@onError="showError"
|
||||||
|
|
|
@ -648,6 +648,7 @@
|
||||||
"repeat": "Repeat",
|
"repeat": "Repeat",
|
||||||
"reply": "Reply",
|
"reply": "Reply",
|
||||||
"favorite": "Favorite",
|
"favorite": "Favorite",
|
||||||
|
"add_reaction": "Add Reaction",
|
||||||
"user_settings": "User Settings"
|
"user_settings": "User Settings"
|
||||||
},
|
},
|
||||||
"upload":{
|
"upload":{
|
||||||
|
|
|
@ -1,4 +1,17 @@
|
||||||
import { remove, slice, each, findIndex, find, maxBy, minBy, merge, first, last, isArray, omitBy } from 'lodash'
|
import {
|
||||||
|
remove,
|
||||||
|
slice,
|
||||||
|
each,
|
||||||
|
findIndex,
|
||||||
|
find,
|
||||||
|
maxBy,
|
||||||
|
minBy,
|
||||||
|
merge,
|
||||||
|
first,
|
||||||
|
last,
|
||||||
|
isArray,
|
||||||
|
omitBy
|
||||||
|
} from 'lodash'
|
||||||
import { set } from 'vue'
|
import { set } from 'vue'
|
||||||
import apiService from '../services/api/api.service.js'
|
import apiService from '../services/api/api.service.js'
|
||||||
// import parse from '../services/status_parser/status_parser.js'
|
// import parse from '../services/status_parser/status_parser.js'
|
||||||
|
@ -518,6 +531,50 @@ export const mutations = {
|
||||||
newStatus.fave_num = newStatus.favoritedBy.length
|
newStatus.fave_num = newStatus.favoritedBy.length
|
||||||
newStatus.favorited = !!newStatus.favoritedBy.find(({ id }) => currentUser.id === id)
|
newStatus.favorited = !!newStatus.favoritedBy.find(({ id }) => currentUser.id === id)
|
||||||
},
|
},
|
||||||
|
addEmojiReactionsBy (state, { id, emojiReactions, currentUser }) {
|
||||||
|
const status = state.allStatusesObject[id]
|
||||||
|
set(status, 'emoji_reactions', emojiReactions)
|
||||||
|
},
|
||||||
|
addOwnReaction (state, { id, emoji, currentUser }) {
|
||||||
|
const status = state.allStatusesObject[id]
|
||||||
|
const reactionIndex = findIndex(status.emoji_reactions, { emoji })
|
||||||
|
const reaction = status.emoji_reactions[reactionIndex] || { emoji, count: 0, accounts: [] }
|
||||||
|
|
||||||
|
const newReaction = {
|
||||||
|
...reaction,
|
||||||
|
count: reaction.count + 1,
|
||||||
|
accounts: [
|
||||||
|
...reaction.accounts,
|
||||||
|
currentUser
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update count of existing reaction if it exists, otherwise append at the end
|
||||||
|
if (reactionIndex >= 0) {
|
||||||
|
set(status.emoji_reactions, reactionIndex, newReaction)
|
||||||
|
} else {
|
||||||
|
set(status, 'emoji_reactions', [...status.emoji_reactions, newReaction])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeOwnReaction (state, { id, emoji, currentUser }) {
|
||||||
|
const status = state.allStatusesObject[id]
|
||||||
|
const reactionIndex = findIndex(status.emoji_reactions, { emoji })
|
||||||
|
if (reactionIndex < 0) return
|
||||||
|
|
||||||
|
const reaction = status.emoji_reactions[reactionIndex]
|
||||||
|
|
||||||
|
const newReaction = {
|
||||||
|
...reaction,
|
||||||
|
count: reaction.count - 1,
|
||||||
|
accounts: reaction.accounts.filter(acc => acc.id === currentUser.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newReaction.count > 0) {
|
||||||
|
set(status.emoji_reactions, reactionIndex, newReaction)
|
||||||
|
} else {
|
||||||
|
set(status, 'emoji_reactions', status.emoji_reactions.filter(r => r.emoji !== emoji))
|
||||||
|
}
|
||||||
|
},
|
||||||
updateStatusWithPoll (state, { id, poll }) {
|
updateStatusWithPoll (state, { id, poll }) {
|
||||||
const status = state.allStatusesObject[id]
|
const status = state.allStatusesObject[id]
|
||||||
status.poll = poll
|
status.poll = poll
|
||||||
|
@ -622,6 +679,31 @@ const statuses = {
|
||||||
commit('addRepeats', { id, rebloggedByUsers, currentUser: rootState.users.currentUser })
|
commit('addRepeats', { id, rebloggedByUsers, currentUser: rootState.users.currentUser })
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
reactWithEmoji ({ rootState, dispatch, commit }, { id, emoji }) {
|
||||||
|
const currentUser = rootState.users.currentUser
|
||||||
|
commit('addOwnReaction', { id, emoji, currentUser })
|
||||||
|
rootState.api.backendInteractor.reactWithEmoji({ id, emoji }).then(
|
||||||
|
status => {
|
||||||
|
dispatch('fetchEmojiReactionsBy', id)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
unreactWithEmoji ({ rootState, dispatch, commit }, { id, emoji }) {
|
||||||
|
const currentUser = rootState.users.currentUser
|
||||||
|
commit('removeOwnReaction', { id, emoji, currentUser })
|
||||||
|
rootState.api.backendInteractor.unreactWithEmoji({ id, emoji }).then(
|
||||||
|
status => {
|
||||||
|
dispatch('fetchEmojiReactionsBy', id)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
fetchEmojiReactionsBy ({ rootState, commit }, id) {
|
||||||
|
rootState.api.backendInteractor.fetchEmojiReactions({ id }).then(
|
||||||
|
emojiReactions => {
|
||||||
|
commit('addEmojiReactionsBy', { id, emojiReactions, currentUser: rootState.users.currentUser })
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
fetchFavs ({ rootState, commit }, id) {
|
fetchFavs ({ rootState, commit }, id) {
|
||||||
rootState.api.backendInteractor.fetchFavoritedByUsers({ id })
|
rootState.api.backendInteractor.fetchFavoritedByUsers({ id })
|
||||||
.then(favoritedByUsers => commit('addFavs', { id, favoritedByUsers, currentUser: rootState.users.currentUser }))
|
.then(favoritedByUsers => commit('addFavs', { id, favoritedByUsers, currentUser: rootState.users.currentUser }))
|
||||||
|
|
|
@ -74,6 +74,9 @@ const MASTODON_SEARCH_2 = `/api/v2/search`
|
||||||
const MASTODON_USER_SEARCH_URL = '/api/v1/accounts/search'
|
const MASTODON_USER_SEARCH_URL = '/api/v1/accounts/search'
|
||||||
const MASTODON_DOMAIN_BLOCKS_URL = '/api/v1/domain_blocks'
|
const MASTODON_DOMAIN_BLOCKS_URL = '/api/v1/domain_blocks'
|
||||||
const MASTODON_STREAMING = '/api/v1/streaming'
|
const MASTODON_STREAMING = '/api/v1/streaming'
|
||||||
|
const PLEROMA_EMOJI_REACTIONS_URL = id => `/api/v1/pleroma/statuses/${id}/emoji_reactions_by`
|
||||||
|
const PLEROMA_EMOJI_REACT_URL = id => `/api/v1/pleroma/statuses/${id}/react_with_emoji`
|
||||||
|
const PLEROMA_EMOJI_UNREACT_URL = id => `/api/v1/pleroma/statuses/${id}/unreact_with_emoji`
|
||||||
|
|
||||||
const oldfetch = window.fetch
|
const oldfetch = window.fetch
|
||||||
|
|
||||||
|
@ -881,6 +884,28 @@ const fetchRebloggedByUsers = ({ id }) => {
|
||||||
return promisedRequest({ url: MASTODON_STATUS_REBLOGGEDBY_URL(id) }).then((users) => users.map(parseUser))
|
return promisedRequest({ url: MASTODON_STATUS_REBLOGGEDBY_URL(id) }).then((users) => users.map(parseUser))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fetchEmojiReactions = ({ id }) => {
|
||||||
|
return promisedRequest({ url: PLEROMA_EMOJI_REACTIONS_URL(id) })
|
||||||
|
}
|
||||||
|
|
||||||
|
const reactWithEmoji = ({ id, emoji, credentials }) => {
|
||||||
|
return promisedRequest({
|
||||||
|
url: PLEROMA_EMOJI_REACT_URL(id),
|
||||||
|
method: 'POST',
|
||||||
|
credentials,
|
||||||
|
payload: { emoji }
|
||||||
|
}).then(parseStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
const unreactWithEmoji = ({ id, emoji, credentials }) => {
|
||||||
|
return promisedRequest({
|
||||||
|
url: PLEROMA_EMOJI_UNREACT_URL(id),
|
||||||
|
method: 'POST',
|
||||||
|
credentials,
|
||||||
|
payload: { emoji }
|
||||||
|
}).then(parseStatus)
|
||||||
|
}
|
||||||
|
|
||||||
const reportUser = ({ credentials, userId, statusIds, comment, forward }) => {
|
const reportUser = ({ credentials, userId, statusIds, comment, forward }) => {
|
||||||
return promisedRequest({
|
return promisedRequest({
|
||||||
url: MASTODON_REPORT_USER_URL,
|
url: MASTODON_REPORT_USER_URL,
|
||||||
|
@ -1130,6 +1155,9 @@ const apiService = {
|
||||||
fetchPoll,
|
fetchPoll,
|
||||||
fetchFavoritedByUsers,
|
fetchFavoritedByUsers,
|
||||||
fetchRebloggedByUsers,
|
fetchRebloggedByUsers,
|
||||||
|
fetchEmojiReactions,
|
||||||
|
reactWithEmoji,
|
||||||
|
unreactWithEmoji,
|
||||||
reportUser,
|
reportUser,
|
||||||
updateNotificationSettings,
|
updateNotificationSettings,
|
||||||
search2,
|
search2,
|
||||||
|
|
|
@ -242,6 +242,7 @@ export const parseStatus = (data) => {
|
||||||
output.is_local = pleroma.local
|
output.is_local = pleroma.local
|
||||||
output.in_reply_to_screen_name = data.pleroma.in_reply_to_account_acct
|
output.in_reply_to_screen_name = data.pleroma.in_reply_to_account_acct
|
||||||
output.thread_muted = pleroma.thread_muted
|
output.thread_muted = pleroma.thread_muted
|
||||||
|
output.emoji_reactions = pleroma.emoji_reactions
|
||||||
} else {
|
} else {
|
||||||
output.text = data.content
|
output.text = data.content
|
||||||
output.summary = data.spoiler_text
|
output.summary = data.spoiler_text
|
||||||
|
|
|
@ -241,6 +241,51 @@ describe('Statuses module', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('emojiReactions', () => {
|
||||||
|
it('increments count in existing reaction', () => {
|
||||||
|
const state = defaultState()
|
||||||
|
const status = makeMockStatus({ id: '1' })
|
||||||
|
status.emoji_reactions = [ { emoji: '😂', count: 1, accounts: [] } ]
|
||||||
|
|
||||||
|
mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' })
|
||||||
|
mutations.addOwnReaction(state, { id: '1', emoji: '😂', currentUser: { id: 'me' } })
|
||||||
|
expect(state.allStatusesObject['1'].emoji_reactions[0].count).to.eql(2)
|
||||||
|
expect(state.allStatusesObject['1'].emoji_reactions[0].accounts[0].id).to.eql('me')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('adds a new reaction', () => {
|
||||||
|
const state = defaultState()
|
||||||
|
const status = makeMockStatus({ id: '1' })
|
||||||
|
status.emoji_reactions = []
|
||||||
|
|
||||||
|
mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' })
|
||||||
|
mutations.addOwnReaction(state, { id: '1', emoji: '😂', currentUser: { id: 'me' } })
|
||||||
|
expect(state.allStatusesObject['1'].emoji_reactions[0].count).to.eql(1)
|
||||||
|
expect(state.allStatusesObject['1'].emoji_reactions[0].accounts[0].id).to.eql('me')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('decreases count in existing reaction', () => {
|
||||||
|
const state = defaultState()
|
||||||
|
const status = makeMockStatus({ id: '1' })
|
||||||
|
status.emoji_reactions = [ { emoji: '😂', count: 2, accounts: [{ id: 'me' }] } ]
|
||||||
|
|
||||||
|
mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' })
|
||||||
|
mutations.removeOwnReaction(state, { id: '1', emoji: '😂', currentUser: {} })
|
||||||
|
expect(state.allStatusesObject['1'].emoji_reactions[0].count).to.eql(1)
|
||||||
|
expect(state.allStatusesObject['1'].emoji_reactions[0].accounts).to.eql([])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('removes a reaction', () => {
|
||||||
|
const state = defaultState()
|
||||||
|
const status = makeMockStatus({ id: '1' })
|
||||||
|
status.emoji_reactions = [{ emoji: '😂', count: 1, accounts: [{ id: 'me' }] }]
|
||||||
|
|
||||||
|
mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' })
|
||||||
|
mutations.removeOwnReaction(state, { id: '1', emoji: '😂', currentUser: {} })
|
||||||
|
expect(state.allStatusesObject['1'].emoji_reactions.length).to.eql(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('showNewStatuses', () => {
|
describe('showNewStatuses', () => {
|
||||||
it('resets the minId to the min of the visible statuses when adding new to visible statuses', () => {
|
it('resets the minId to the min of the visible statuses when adding new to visible statuses', () => {
|
||||||
const state = defaultState()
|
const state = defaultState()
|
||||||
|
|
Loading…
Reference in a new issue