Make reactions removable

Co-authored-by: syuilo <syuilotan@yahoo.co.jp>

Resolve #367, resolve #2260, close #3503
This commit is contained in:
Aya Morisawa 2018-12-26 23:05:47 +09:00
parent dfc6ef4be6
commit 9b746f3eb5
No known key found for this signature in database
GPG Key ID: 3E64865D70D579F2
3 changed files with 63 additions and 15 deletions

View File

@ -95,6 +95,7 @@ export default prop => ({
Vue.set(this.$_ns_target.reactionCounts, reaction, 0); Vue.set(this.$_ns_target.reactionCounts, reaction, 0);
} }
// Increment the count
this.$_ns_target.reactionCounts[reaction]++; this.$_ns_target.reactionCounts[reaction]++;
if (body.userId == this.$store.state.i.id) { if (body.userId == this.$store.state.i.id) {
@ -103,6 +104,26 @@ export default prop => ({
break; break;
} }
case 'unreacted': {
const reaction = body.reaction;
if (this.$_ns_target.reactionCounts == null) {
return;
}
if (this.$_ns_target.reactionCounts[reaction] == null) {
return;
}
// Decrement the count
if (this.$_ns_target.reactionCounts[reaction] > 0) this.$_ns_target.reactionCounts[reaction]--;
if (body.userId == this.$store.state.i.id) {
Vue.set(this.$_ns_target, 'myReaction', null);
}
break;
}
case 'pollVoted': { case 'pollVoted': {
if (body.userId == this.$store.state.i.id) return; if (body.userId == this.$store.state.i.id) return;
const choice = body.choice; const choice = body.choice;

View File

@ -1,16 +1,16 @@
<template> <template>
<div class="mk-reactions-viewer"> <div class="mk-reactions-viewer">
<template v-if="reactions"> <template v-if="reactions">
<span :class="{ reacted: note.myReaction == 'like' }" @click="react('like')" v-if="reactions.like" v-particle><mk-reaction-icon reaction="like" ref="like"/><span>{{ reactions.like }}</span></span> <span :class="{ reacted: note.myReaction == 'like' }" @click="toggleReaction('like')" v-if="reactions.like" v-particle><mk-reaction-icon reaction="like" ref="like"/><span>{{ reactions.like }}</span></span>
<span :class="{ reacted: note.myReaction == 'love' }" @click="react('love')" v-if="reactions.love" v-particle><mk-reaction-icon reaction="love" ref="love"/><span>{{ reactions.love }}</span></span> <span :class="{ reacted: note.myReaction == 'love' }" @click="toggleReaction('love')" v-if="reactions.love" v-particle><mk-reaction-icon reaction="love" ref="love"/><span>{{ reactions.love }}</span></span>
<span :class="{ reacted: note.myReaction == 'laugh' }" @click="react('laugh')" v-if="reactions.laugh" v-particle><mk-reaction-icon reaction="laugh" ref="laugh"/><span>{{ reactions.laugh }}</span></span> <span :class="{ reacted: note.myReaction == 'laugh' }" @click="toggleReaction('laugh')" v-if="reactions.laugh" v-particle><mk-reaction-icon reaction="laugh" ref="laugh"/><span>{{ reactions.laugh }}</span></span>
<span :class="{ reacted: note.myReaction == 'hmm' }" @click="react('hmm')" v-if="reactions.hmm" v-particle><mk-reaction-icon reaction="hmm" ref="hmm"/><span>{{ reactions.hmm }}</span></span> <span :class="{ reacted: note.myReaction == 'hmm' }" @click="toggleReaction('hmm')" v-if="reactions.hmm" v-particle><mk-reaction-icon reaction="hmm" ref="hmm"/><span>{{ reactions.hmm }}</span></span>
<span :class="{ reacted: note.myReaction == 'surprise' }" @click="react('surprise')" v-if="reactions.surprise" v-particle><mk-reaction-icon reaction="surprise" ref="surprise"/><span>{{ reactions.surprise }}</span></span> <span :class="{ reacted: note.myReaction == 'surprise' }" @click="toggleReaction('surprise')" v-if="reactions.surprise" v-particle><mk-reaction-icon reaction="surprise" ref="surprise"/><span>{{ reactions.surprise }}</span></span>
<span :class="{ reacted: note.myReaction == 'congrats' }" @click="react('congrats')" v-if="reactions.congrats" v-particle><mk-reaction-icon reaction="congrats" ref="congrats"/><span>{{ reactions.congrats }}</span></span> <span :class="{ reacted: note.myReaction == 'congrats' }" @click="toggleReaction('congrats')" v-if="reactions.congrats" v-particle><mk-reaction-icon reaction="congrats" ref="congrats"/><span>{{ reactions.congrats }}</span></span>
<span :class="{ reacted: note.myReaction == 'angry' }" @click="react('angry')" v-if="reactions.angry" v-particle><mk-reaction-icon reaction="angry" ref="angry"/><span>{{ reactions.angry }}</span></span> <span :class="{ reacted: note.myReaction == 'angry' }" @click="toggleReaction('angry')" v-if="reactions.angry" v-particle><mk-reaction-icon reaction="angry" ref="angry"/><span>{{ reactions.angry }}</span></span>
<span :class="{ reacted: note.myReaction == 'confused' }" @click="react('confused')" v-if="reactions.confused" v-particle><mk-reaction-icon reaction="confused" ref="confused"/><span>{{ reactions.confused }}</span></span> <span :class="{ reacted: note.myReaction == 'confused' }" @click="toggleReaction('confused')" v-if="reactions.confused" v-particle><mk-reaction-icon reaction="confused" ref="confused"/><span>{{ reactions.confused }}</span></span>
<span :class="{ reacted: note.myReaction == 'rip' }" @click="react('rip')" v-if="reactions.rip" v-particle><mk-reaction-icon reaction="rip" ref="rip"/><span>{{ reactions.rip }}</span></span> <span :class="{ reacted: note.myReaction == 'rip' }" @click="toggleReaction('rip')" v-if="reactions.rip" v-particle><mk-reaction-icon reaction="rip" ref="rip"/><span>{{ reactions.rip }}</span></span>
<span :class="{ reacted: note.myReaction == 'pudding' }" @click="react('pudding')" v-if="reactions.pudding" v-particle><mk-reaction-icon reaction="pudding" ref="pudding"/><span>{{ reactions.pudding }}</span></span> <span :class="{ reacted: note.myReaction == 'pudding' }" @click="toggleReaction('pudding')" v-if="reactions.pudding" v-particle><mk-reaction-icon reaction="pudding" ref="pudding"/><span>{{ reactions.pudding }}</span></span>
</template> </template>
</div> </div>
</template> </template>
@ -60,11 +60,25 @@ export default Vue.extend({
} }
}, },
methods: { methods: {
react(reaction: string) { toggleReaction(reaction: string) {
const oldReaction = this.note.myReaction;
if (oldReaction) {
this.$root.api('notes/reactions/delete', {
noteId: this.note.id
}).then(() => {
if (oldReaction !== reaction) {
this.$root.api('notes/reactions/create', { this.$root.api('notes/reactions/create', {
noteId: this.note.id, noteId: this.note.id,
reaction: reaction reaction: reaction
}); });
}
});
} else {
this.$root.api('notes/reactions/create', {
noteId: this.note.id,
reaction: reaction
});
}
}, },
anime(reaction: string) { anime(reaction: string) {
if (this.$store.state.device.reduceMotion) return; if (this.$store.state.device.reduceMotion) return;

View File

@ -2,6 +2,8 @@ import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id
import Reaction from '../../../../../models/note-reaction'; import Reaction from '../../../../../models/note-reaction';
import Note from '../../../../../models/note'; import Note from '../../../../../models/note';
import define from '../../../define'; import define from '../../../define';
import { publishNoteStream } from '../../../../../stream';
const ms = require('ms');
export const meta = { export const meta = {
desc: { desc: {
@ -13,6 +15,12 @@ export const meta = {
kind: 'reaction-write', kind: 'reaction-write',
limit: {
duration: ms('1hour'),
max: 5,
minInterval: ms('3sec')
},
params: { params: {
noteId: { noteId: {
validator: $.type(ID), validator: $.type(ID),
@ -60,4 +68,9 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
Note.update({ _id: note._id }, { Note.update({ _id: note._id }, {
$inc: dec $inc: dec
}); });
publishNoteStream(note._id, 'unreacted', {
reaction: exist.reaction,
userId: user._id
});
})); }));