Merge pull request #23 from team-shahu/feat/muted-reaction
feat: リアクションした人一覧がブロック・ミュートを考慮するようにする設定
This commit is contained in:
parent
759109e7a1
commit
a313fc6366
@ -2824,3 +2824,6 @@ _contextMenu:
|
||||
app: "Application"
|
||||
appWithShift: "Application with shift key"
|
||||
native: "Native"
|
||||
_reactionChecksMuting:
|
||||
title: "Check mutings when get reactions"
|
||||
caption: "Check mutings when get reactions, but cache does not work and may increase traffic"
|
||||
|
10
locales/index.d.ts
vendored
10
locales/index.d.ts
vendored
@ -10895,6 +10895,16 @@ export interface Locale extends ILocale {
|
||||
*/
|
||||
"native": string;
|
||||
};
|
||||
"_reactionChecksMuting": {
|
||||
/**
|
||||
* リアクションでミュートを考慮する
|
||||
*/
|
||||
"title": string;
|
||||
/**
|
||||
* リアクションがミュートを考慮しますが、キャッシュが効かず通信量が増えることがあります。
|
||||
*/
|
||||
"caption": string;
|
||||
};
|
||||
}
|
||||
declare const locales: {
|
||||
[lang: string]: Locale;
|
||||
|
@ -2899,3 +2899,7 @@ _contextMenu:
|
||||
app: "アプリケーション"
|
||||
appWithShift: "Shiftキーでアプリケーション"
|
||||
native: "ブラウザのUI"
|
||||
|
||||
_reactionChecksMuting:
|
||||
title: "リアクションでミュートを考慮する"
|
||||
caption: "リアクションがミュートを考慮しますが、キャッシュが効かず通信量が増えることがあります。"
|
||||
|
@ -4,13 +4,12 @@
|
||||
*/
|
||||
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Brackets, type FindOptionsWhere } from 'typeorm';
|
||||
import type { NoteReactionsRepository } from '@/models/_.js';
|
||||
import type { MiNoteReaction } from '@/models/NoteReaction.js';
|
||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import { NoteReactionEntityService } from '@/core/entities/NoteReactionEntityService.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { QueryService } from '@/core/QueryService.js';
|
||||
import { CacheService } from '@/core/CacheService.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['notes', 'reactions'],
|
||||
@ -59,6 +58,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
|
||||
private noteReactionEntityService: NoteReactionEntityService,
|
||||
private queryService: QueryService,
|
||||
private cacheService: CacheService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
const query = this.queryService.makePaginationQuery(this.noteReactionsRepository.createQueryBuilder('reaction'), ps.sinceId, ps.untilId)
|
||||
@ -66,6 +66,15 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
.leftJoinAndSelect('reaction.user', 'user')
|
||||
.leftJoinAndSelect('reaction.note', 'note');
|
||||
|
||||
if (me != null) {
|
||||
const [userIdsWhoMeMuting, userIdsWhoBlockingMe] = await Promise.all([
|
||||
this.cacheService.userMutingsCache.get(me.id),
|
||||
this.cacheService.userBlockedCache.get(me.id),
|
||||
]);
|
||||
|
||||
query.andWhere('reaction.userId NOT IN (:...userIds)', { userIds: Array.from(userIdsWhoMeMuting ?? []).concat(Array.from(userIdsWhoBlockingMe ?? [])) });
|
||||
}
|
||||
|
||||
if (ps.type) {
|
||||
// ローカルリアクションはホスト名が . とされているが
|
||||
// DB 上ではそうではないので、必要に応じて変換
|
||||
|
@ -15,6 +15,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<MkAvatar :class="$style.avatar" :user="u"/>
|
||||
<MkUserName :user="u" :nowrap="true"/>
|
||||
</div>
|
||||
<div v-if="count <= 0" :class="$style.user"> {{ i18n.ts.noUsers }} </div>
|
||||
<div v-if="count > 10" :class="$style.more">+{{ count - 10 }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -26,6 +27,7 @@ import { } from 'vue';
|
||||
import MkTooltip from './MkTooltip.vue';
|
||||
import MkReactionIcon from '@/components/MkReactionIcon.vue';
|
||||
import { getEmojiName } from '@/scripts/emojilist.js';
|
||||
import { i18n } from '@/i18n';
|
||||
|
||||
defineProps<{
|
||||
showing: boolean;
|
||||
|
@ -36,6 +36,8 @@ import { checkReactionPermissions } from '@/scripts/check-reaction-permissions.j
|
||||
import { customEmojisMap } from '@/custom-emojis.js';
|
||||
import { getUnicodeEmoji } from '@/scripts/emojilist.js';
|
||||
|
||||
const reactionChecksMuting = computed(defaultStore.makeGetterSetter('reactionChecksMuting'));
|
||||
|
||||
const props = defineProps<{
|
||||
reaction: string;
|
||||
count: number;
|
||||
@ -146,7 +148,9 @@ onMounted(() => {
|
||||
|
||||
if (!mock) {
|
||||
useTooltip(buttonEl, async (showing) => {
|
||||
const reactions = await misskeyApiGet('notes/reactions', {
|
||||
const useGet = !reactionChecksMuting.value;
|
||||
const apiCall = useGet ? misskeyApiGet : misskeyApi;
|
||||
const reactions = await apiCall('notes/reactions', {
|
||||
noteId: props.note.id,
|
||||
type: props.reaction,
|
||||
limit: 10,
|
||||
@ -154,12 +158,13 @@ if (!mock) {
|
||||
});
|
||||
|
||||
const users = reactions.map(x => x.user);
|
||||
const count = users.length;
|
||||
|
||||
const { dispose } = os.popup(XDetails, {
|
||||
showing,
|
||||
reaction: props.reaction,
|
||||
users,
|
||||
count: props.count,
|
||||
count,
|
||||
targetElement: buttonEl.value,
|
||||
}, {
|
||||
closed: () => dispose(),
|
||||
|
@ -235,6 +235,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<MkSwitch v-model="enableHorizontalSwipe">{{ i18n.ts.enableHorizontalSwipe }}</MkSwitch>
|
||||
<MkSwitch v-model="alwaysConfirmFollow">{{ i18n.ts.alwaysConfirmFollow }}</MkSwitch>
|
||||
<MkSwitch v-model="confirmWhenRevealingSensitiveMedia">{{ i18n.ts.confirmWhenRevealingSensitiveMedia }}</MkSwitch>
|
||||
|
||||
<MkSwitch v-model="reactionChecksMuting">
|
||||
{{ i18n.ts._reactionChecksMuting.title }}<span class="_beta">{{ i18n.ts.originalFeature }}</span>
|
||||
<template #caption>{{ i18n.ts._reactionChecksMuting.caption }}</template>
|
||||
</MkSwitch>
|
||||
</div>
|
||||
<MkSelect v-model="serverDisconnectedBehavior">
|
||||
<template #label>{{ i18n.ts.whenServerDisconnected }}</template>
|
||||
@ -435,6 +440,8 @@ const useNativeUIForVideoAudioPlayer = computed(defaultStore.makeGetterSetter('u
|
||||
const alwaysConfirmFollow = computed(defaultStore.makeGetterSetter('alwaysConfirmFollow'));
|
||||
const confirmWhenRevealingSensitiveMedia = computed(defaultStore.makeGetterSetter('confirmWhenRevealingSensitiveMedia'));
|
||||
const contextMenu = computed(defaultStore.makeGetterSetter('contextMenu'));
|
||||
const searchEngine = computed(defaultStore.makeGetterSetter('searchEngine'));
|
||||
const reactionChecksMuting = computed(defaultStore.makeGetterSetter('reactionChecksMuting'));
|
||||
|
||||
watch(lang, () => {
|
||||
miLocalStorage.setItem('lang', lang.value as string);
|
||||
|
@ -532,10 +532,10 @@ export const defaultStore = markRaw(new Storage('base', {
|
||||
where: 'device',
|
||||
default: false,
|
||||
},
|
||||
contextMenu: {
|
||||
contextMenu: {
|
||||
where: 'device',
|
||||
default: 'app' as 'app' | 'appWithShift' | 'native',
|
||||
},
|
||||
},
|
||||
|
||||
sound_masterVolume: {
|
||||
where: 'device',
|
||||
@ -565,6 +565,14 @@ export const defaultStore = markRaw(new Storage('base', {
|
||||
where: 'device',
|
||||
default: { type: 'syuilo/bubble2', volume: 1 } as SoundStore,
|
||||
},
|
||||
searchEngine: {
|
||||
where: 'device',
|
||||
default: 'https://google.com/search?q=',
|
||||
},
|
||||
reactionChecksMuting: {
|
||||
where: 'device',
|
||||
default: true,
|
||||
},
|
||||
}));
|
||||
|
||||
// TODO: 他のタブと永続化されたstateを同期
|
||||
|
Loading…
Reference in New Issue
Block a user