This commit is contained in:
syuilo 2023-10-01 21:11:12 +09:00
parent 783a97fe06
commit 72f7413f40
6 changed files with 20 additions and 59 deletions

View file

@ -1636,11 +1636,6 @@ _wordMute:
muteWords: "ミュートするワード" muteWords: "ミュートするワード"
muteWordsDescription: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります。" muteWordsDescription: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります。"
muteWordsDescription2: "キーワードをスラッシュで囲むと正規表現になります。" muteWordsDescription2: "キーワードをスラッシュで囲むと正規表現になります。"
softDescription: "指定した条件のノートをタイムラインから隠します。"
hardDescription: "指定した条件のノートをタイムラインに追加しないようにします。追加されなかったノートは、条件を変更しても除外されたままになります。"
soft: "ソフト"
hard: "ハード"
mutedNotes: "ミュートされたノート"
_instanceMute: _instanceMute:
instanceMuteDescription: "ミュートしたサーバーのユーザーへの返信を含めて、設定したサーバーの全てのートとRenoteをミュートします。" instanceMuteDescription: "ミュートしたサーバーのユーザーへの返信を含めて、設定したサーバーの全てのートとRenoteをミュートします。"

View file

@ -165,7 +165,7 @@ import { deepClone } from '@/scripts/clone.js';
import { useTooltip } from '@/scripts/use-tooltip.js'; import { useTooltip } from '@/scripts/use-tooltip.js';
import { claimAchievement } from '@/scripts/achievements.js'; import { claimAchievement } from '@/scripts/achievements.js';
import { getNoteSummary } from '@/scripts/get-note-summary.js'; import { getNoteSummary } from '@/scripts/get-note-summary.js';
import { MenuItem } from '@/types/menu'; import { MenuItem } from '@/types/menu.js';
import MkRippleEffect from '@/components/MkRippleEffect.vue'; import MkRippleEffect from '@/components/MkRippleEffect.vue';
import { showMovedDialog } from '@/scripts/show-moved-dialog.js'; import { showMovedDialog } from '@/scripts/show-moved-dialog.js';
import { shouldCollapsed } from '@/scripts/collapsed.js'; import { shouldCollapsed } from '@/scripts/collapsed.js';
@ -211,7 +211,7 @@ const urls = appearNote.text ? extractUrlFromMfm(mfm.parse(appearNote.text)) : n
const isLong = shouldCollapsed(appearNote); const isLong = shouldCollapsed(appearNote);
const collapsed = ref(appearNote.cw == null && isLong); const collapsed = ref(appearNote.cw == null && isLong);
const isDeleted = ref(false); const isDeleted = ref(false);
const muted = ref(checkWordMute(appearNote, $i, defaultStore.state.mutedWords)); const muted = ref($i ? checkWordMute(appearNote, $i, $i.mutedWords) : false);
const translation = ref<any>(null); const translation = ref<any>(null);
const translating = ref(false); const translating = ref(false);
const showTicker = (defaultStore.state.instanceTicker === 'always') || (defaultStore.state.instanceTicker === 'remote' && appearNote.user.instance); const showTicker = (defaultStore.state.instanceTicker === 'always') || (defaultStore.state.instanceTicker === 'remote' && appearNote.user.instance);

View file

@ -214,7 +214,7 @@ import { useNoteCapture } from '@/scripts/use-note-capture.js';
import { deepClone } from '@/scripts/clone.js'; import { deepClone } from '@/scripts/clone.js';
import { useTooltip } from '@/scripts/use-tooltip.js'; import { useTooltip } from '@/scripts/use-tooltip.js';
import { claimAchievement } from '@/scripts/achievements.js'; import { claimAchievement } from '@/scripts/achievements.js';
import { MenuItem } from '@/types/menu'; import { MenuItem } from '@/types/menu.js';
import MkRippleEffect from '@/components/MkRippleEffect.vue'; import MkRippleEffect from '@/components/MkRippleEffect.vue';
import { showMovedDialog } from '@/scripts/show-moved-dialog.js'; import { showMovedDialog } from '@/scripts/show-moved-dialog.js';
import MkUserCardMini from '@/components/MkUserCardMini.vue'; import MkUserCardMini from '@/components/MkUserCardMini.vue';
@ -258,7 +258,7 @@ let appearNote = $computed(() => isRenote ? note.renote as Misskey.entities.Note
const isMyRenote = $i && ($i.id === note.userId); const isMyRenote = $i && ($i.id === note.userId);
const showContent = ref(false); const showContent = ref(false);
const isDeleted = ref(false); const isDeleted = ref(false);
const muted = ref(checkWordMute(appearNote, $i, defaultStore.state.mutedWords)); const muted = ref($i ? checkWordMute(appearNote, $i, $i.mutedWords) : false);
const translation = ref(null); const translation = ref(null);
const translating = ref(false); const translating = ref(false);
const urls = appearNote.text ? extractUrlFromMfm(mfm.parse(appearNote.text)) : null; const urls = appearNote.text ? extractUrlFromMfm(mfm.parse(appearNote.text)) : null;

View file

@ -49,9 +49,9 @@ import { notePage } from '@/filters/note.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { $i } from '@/account.js'; import { $i } from '@/account.js';
import { userPage } from "@/filters/user"; import { userPage } from '@/filters/user.js';
import { checkWordMute } from "@/scripts/check-word-mute"; import { checkWordMute } from '@/scripts/check-word-mute.js';
import { defaultStore } from "@/store"; import { defaultStore } from '@/store.js';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
note: Misskey.entities.Note; note: Misskey.entities.Note;
@ -63,7 +63,7 @@ const props = withDefaults(defineProps<{
depth: 1, depth: 1,
}); });
const muted = ref(checkWordMute(props.note, $i, defaultStore.state.mutedWords)); const muted = ref($i ? checkWordMute(props.note, $i, $i.mutedWords) : false);
let showContent = $ref(false); let showContent = $ref(false);
let replies: Misskey.entities.Note[] = $ref([]); let replies: Misskey.entities.Note[] = $ref([]);

View file

@ -5,29 +5,11 @@ SPDX-License-Identifier: AGPL-3.0-only
<template> <template>
<div class="_gaps_m"> <div class="_gaps_m">
<MkTab v-model="tab">
<option value="soft">{{ i18n.ts._wordMute.soft }}</option>
<option value="hard">{{ i18n.ts._wordMute.hard }}</option>
</MkTab>
<div> <div>
<div v-show="tab === 'soft'" class="_gaps_m"> <MkTextarea v-model="mutedWords">
<MkInfo>{{ i18n.ts._wordMute.softDescription }}</MkInfo> <span>{{ i18n.ts._wordMute.muteWords }}</span>
<MkTextarea v-model="softMutedWords"> <template #caption>{{ i18n.ts._wordMute.muteWordsDescription }}<br>{{ i18n.ts._wordMute.muteWordsDescription2 }}</template>
<span>{{ i18n.ts._wordMute.muteWords }}</span> </MkTextarea>
<template #caption>{{ i18n.ts._wordMute.muteWordsDescription }}<br>{{ i18n.ts._wordMute.muteWordsDescription2 }}</template>
</MkTextarea>
</div>
<div v-show="tab === 'hard'" class="_gaps_m">
<MkInfo>{{ i18n.ts._wordMute.hardDescription }} {{ i18n.ts.reflectMayTakeTime }}</MkInfo>
<MkTextarea v-model="hardMutedWords">
<span>{{ i18n.ts._wordMute.muteWords }}</span>
<template #caption>{{ i18n.ts._wordMute.muteWordsDescription }}<br>{{ i18n.ts._wordMute.muteWordsDescription2 }}</template>
</MkTextarea>
<MkKeyValue v-if="hardWordMutedNotesCount != null">
<template #key>{{ i18n.ts._wordMute.mutedNotes }}</template>
<template #value>{{ number(hardWordMutedNotesCount) }}</template>
</MkKeyValue>
</div>
</div> </div>
<MkButton primary inline :disabled="!changed" @click="save()"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton> <MkButton primary inline :disabled="!changed" @click="save()"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton>
</div> </div>
@ -56,25 +38,15 @@ const render = (mutedWords) => mutedWords.map(x => {
}).join('\n'); }).join('\n');
const tab = ref('soft'); const tab = ref('soft');
const softMutedWords = ref(render(defaultStore.state.mutedWords)); const mutedWords = ref(render($i!.mutedWords));
const hardMutedWords = ref(render($i!.mutedWords));
const hardWordMutedNotesCount = ref(null);
const changed = ref(false); const changed = ref(false);
os.api('i/get-word-muted-notes-count', {}).then(response => { watch(mutedWords, () => {
hardWordMutedNotesCount.value = response?.count;
});
watch(softMutedWords, () => {
changed.value = true;
});
watch(hardMutedWords, () => {
changed.value = true; changed.value = true;
}); });
async function save() { async function save() {
const parseMutes = (mutes, tab) => { const parseMutes = (mutes) => {
// split into lines, remove empty lines and unnecessary whitespace // split into lines, remove empty lines and unnecessary whitespace
let lines = mutes.trim().split('\n').map(line => line.trim()).filter(line => line !== ''); let lines = mutes.trim().split('\n').map(line => line.trim()).filter(line => line !== '');
@ -92,7 +64,7 @@ async function save() {
os.alert({ os.alert({
type: 'error', type: 'error',
title: i18n.ts.regexpError, title: i18n.ts.regexpError,
text: i18n.t('regexpErrorDescription', { tab, line: i + 1 }) + '\n' + err.toString(), text: i18n.t('regexpErrorDescription', { tab: 'word mute', line: i + 1 }) + '\n' + err.toString(),
}); });
// re-throw error so these invalid settings are not saved // re-throw error so these invalid settings are not saved
throw err; throw err;
@ -105,18 +77,16 @@ async function save() {
return lines; return lines;
}; };
let softMutes, hardMutes; let parsed;
try { try {
softMutes = parseMutes(softMutedWords.value, i18n.ts._wordMute.soft); parsed = parseMutes(mutedWords.value);
hardMutes = parseMutes(hardMutedWords.value, i18n.ts._wordMute.hard);
} catch (err) { } catch (err) {
// already displayed error message in parseMutes // already displayed error message in parseMutes
return; return;
} }
defaultStore.set('mutedWords', softMutes);
await os.api('i/update', { await os.api('i/update', {
mutedWords: hardMutes, mutedWords: parsed,
}); });
changed.value = false; changed.value = false;

View file

@ -5,7 +5,7 @@
import { markRaw, ref } from 'vue'; import { markRaw, ref } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import { miLocalStorage } from './local-storage'; import { miLocalStorage } from './local-storage.js';
import { Storage } from '@/pizzax.js'; import { Storage } from '@/pizzax.js';
interface PostFormAction { interface PostFormAction {
@ -101,10 +101,6 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'account', where: 'account',
default: 'nonSensitiveOnly' as 'likeOnly' | 'likeOnlyForRemote' | 'nonSensitiveOnly' | 'nonSensitiveOnlyForLocalLikeOnlyForRemote' | null, default: 'nonSensitiveOnly' as 'likeOnly' | 'likeOnlyForRemote' | 'nonSensitiveOnly' | 'nonSensitiveOnlyForLocalLikeOnlyForRemote' | null,
}, },
mutedWords: {
where: 'account',
default: [],
},
mutedAds: { mutedAds: {
where: 'account', where: 'account',
default: [] as string[], default: [] as string[],