diff --git a/src/client/app/common/views/components/note-menu.vue b/src/client/app/common/views/components/note-menu.vue index 25431c8003..ecea08b756 100644 --- a/src/client/app/common/views/components/note-menu.vue +++ b/src/client/app/common/views/components/note-menu.vue @@ -15,68 +15,72 @@ import { faCopy } from '@fortawesome/free-regular-svg-icons'; export default Vue.extend({ i18n: i18n('common/views/components/note-menu.vue'), props: ['note', 'source'], + data() { + return { + isFavorited: false + }; + }, computed: { items(): any[] { - return concat(intersperse([null], [ - [ - [{ - icon: 'at', - text: this.$t('mention'), - action: this.mention - }] - ], - [ - [{ - icon: 'info-circle', - text: this.$t('detail'), - action: this.detail - }], [{ - icon: faCopy, - text: this.$t('copy-content'), - action: this.copyContent - }], [{ - icon: 'link', - text: this.$t('copy-link'), - action: this.copyLink - }], this.note.uri ? [{ - icon: 'external-link-square-alt', - text: this.$t('remote'), - action: () => { - window.open(this.note.uri, '_blank'); - } - }] : [] - ], - [ - this.note.isFavorited ? [{ - icon: 'star', - text: this.$t('unfavorite'), - action: this.unfavorite - }] : [{ - icon: 'star', - text: this.$t('favorite'), - action: this.favorite - }], this.note.userId == this.$store.state.i.id ? [ - (this.$store.state.i.pinnedNoteIds || []).includes(this.note.id) ? { - icon: 'thumbtack', - text: this.$t('unpin'), - action: this.unpin - } : { - icon: 'thumbtack', - text: this.$t('pin'), - action: this.pin - } - ] : [] - ], [ - this.note.userId == this.$store.state.i.id || this.$store.state.i.isAdmin || this.$store.state.i.isModerator ? [{ - icon: ['far', 'trash-alt'], - text: this.$t('delete'), - action: this.del - }] : [] - ] - ].map(concat).filter(x => x.length > 0))); + return [{ + icon: 'at', + text: this.$t('mention'), + action: this.mention + }, null, { + icon: 'info-circle', + text: this.$t('detail'), + action: this.detail + }, { + icon: faCopy, + text: this.$t('copy-content'), + action: this.copyContent + }, { + icon: 'link', + text: this.$t('copy-link'), + action: this.copyLink + }, this.note.uri ? { + icon: 'external-link-square-alt', + text: this.$t('remote'), + action: () => { + window.open(this.note.uri, '_blank'); + } + } : undefined, + null, + this.isFavorited ? { + icon: 'star', + text: this.$t('unfavorite'), + action: this.unfavorite + } : { + icon: 'star', + text: this.$t('favorite'), + action: this.favorite + }, + this.note.userId == this.$store.state.i.id ? (this.$store.state.i.pinnedNoteIds || []).includes(this.note.id) ? { + icon: 'thumbtack', + text: this.$t('unpin'), + action: this.unpin + } : { + icon: 'thumbtack', + text: this.$t('pin'), + action: this.pin + } : undefined, + null, + this.note.userId == this.$store.state.i.id || this.$store.state.i.isAdmin || this.$store.state.i.isModerator ? { + icon: ['far', 'trash-alt'], + text: this.$t('delete'), + action: this.del + } : undefined].filter(x => x !== undefined) } }, + created() { + this.$root.api('notes/state', { + noteId: this.note.id + }).then(state => { + this.isFavorited = state.isFavorited; + }); + }, + methods: { mention() { this.$post({ mention: this.note.user }); diff --git a/src/models/note.ts b/src/models/note.ts index ce886f51c9..352de4f8d6 100644 --- a/src/models/note.ts +++ b/src/models/note.ts @@ -9,7 +9,6 @@ import { pack as packApp } from './app'; import PollVote from './poll-vote'; import Reaction from './note-reaction'; import { packMany as packFileMany, IDriveFile } from './drive-file'; -import Favorite from './favorite'; import Following from './following'; import Emoji from './emoji'; @@ -346,19 +345,6 @@ export const pack = async ( return null; })(); - - // isFavorited - _note.isFavorited = (async () => { - const favorite = await Favorite - .count({ - userId: meId, - noteId: id - }, { - limit: 1 - }); - - return favorite === 1; - })(); } } diff --git a/src/server/api/endpoints/notes/state.ts b/src/server/api/endpoints/notes/state.ts new file mode 100644 index 0000000000..d8adc48c94 --- /dev/null +++ b/src/server/api/endpoints/notes/state.ts @@ -0,0 +1,38 @@ +import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id'; +import define from '../../define'; +import Favorite from '../../../../models/favorite'; + +export const meta = { + stability: 'stable', + + desc: { + 'ja-JP': '指定した投稿の状態を取得します。', + 'en-US': 'Get state of a note.' + }, + + requireCredential: true, + + params: { + noteId: { + validator: $.type(ID), + transform: transform, + desc: { + 'ja-JP': '対象の投稿のID', + 'en-US': 'Target note ID.' + } + } + } +}; + +export default define(meta, (ps, user) => new Promise(async (res, rej) => { + const favorite = await Favorite.count({ + userId: user._id, + noteId: ps.noteId + }, { + limit: 1 + }); + + res({ + isFavorited: favorite !== 0 + }); +}));