mirror of
https://activitypub.software/TransFem-org/Sharkey
synced 2024-11-29 01:13:02 +00:00
respect word mutes
This commit is contained in:
parent
fcb1218bbc
commit
72d59b459a
6 changed files with 98 additions and 6 deletions
|
@ -696,6 +696,7 @@ regexpError: "Regular Expression error"
|
||||||
regexpErrorDescription: "An error occurred in the regular expression on line {line} of your {tab} word mutes:"
|
regexpErrorDescription: "An error occurred in the regular expression on line {line} of your {tab} word mutes:"
|
||||||
instanceMute: "Instance Mutes"
|
instanceMute: "Instance Mutes"
|
||||||
userSaysSomething: "{name} said something"
|
userSaysSomething: "{name} said something"
|
||||||
|
postFiltered: "post is hidden by a filter"
|
||||||
makeActive: "Activate"
|
makeActive: "Activate"
|
||||||
display: "Display"
|
display: "Display"
|
||||||
copy: "Copy"
|
copy: "Copy"
|
||||||
|
|
4
locales/index.d.ts
vendored
4
locales/index.d.ts
vendored
|
@ -2800,6 +2800,10 @@ export interface Locale extends ILocale {
|
||||||
* {name}が何かを言いました
|
* {name}が何かを言いました
|
||||||
*/
|
*/
|
||||||
"userSaysSomething": ParameterizedString<"name">;
|
"userSaysSomething": ParameterizedString<"name">;
|
||||||
|
/**
|
||||||
|
* post is hidden by a filter
|
||||||
|
*/
|
||||||
|
"postFiltered": string;
|
||||||
/**
|
/**
|
||||||
* アクティブにする
|
* アクティブにする
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -696,6 +696,7 @@ regexpError: "正規表現エラー"
|
||||||
regexpErrorDescription: "{tab}ワードミュートの{line}行目の正規表現にエラーが発生しました:"
|
regexpErrorDescription: "{tab}ワードミュートの{line}行目の正規表現にエラーが発生しました:"
|
||||||
instanceMute: "サーバーミュート"
|
instanceMute: "サーバーミュート"
|
||||||
userSaysSomething: "{name}が何かを言いました"
|
userSaysSomething: "{name}が何かを言いました"
|
||||||
|
postFiltered: "post is hidden by a filter"
|
||||||
makeActive: "アクティブにする"
|
makeActive: "アクティブにする"
|
||||||
display: "表示"
|
display: "表示"
|
||||||
copy: "コピー"
|
copy: "コピー"
|
||||||
|
|
|
@ -18,7 +18,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</MkA>
|
</MkA>
|
||||||
</header>
|
</header>
|
||||||
<div>
|
<div>
|
||||||
<Mfm :class="$style.text" :text="getNoteSummary(note)" :isBlock="true" :plain="true" :nowrap="false" :isNote="true" nyaize="respect" :author="note.user"/>
|
<div v-if="isMuted" :class="[$style.text, $style.muted]">({{ i18n.ts.postFiltered }})</div>
|
||||||
|
<Mfm v-else :class="$style.text" :text="getNoteSummary(note)" :isBlock="true" :plain="true" :nowrap="false" :isNote="true" nyaize="respect" :author="note.user"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -29,10 +30,14 @@ import * as Misskey from 'misskey-js';
|
||||||
import { getNoteSummary } from '@/scripts/get-note-summary.js';
|
import { getNoteSummary } from '@/scripts/get-note-summary.js';
|
||||||
import { userPage } from '@/filters/user.js';
|
import { userPage } from '@/filters/user.js';
|
||||||
import { notePage } from '@/filters/note.js';
|
import { notePage } from '@/filters/note.js';
|
||||||
|
import { i18n } from '@/i18n.js';
|
||||||
|
|
||||||
defineProps<{
|
withDefaults(defineProps<{
|
||||||
note: Misskey.entities.Note
|
note: Misskey.entities.Note,
|
||||||
}>();
|
isMuted: boolean
|
||||||
|
}>(), {
|
||||||
|
isMuted: false,
|
||||||
|
});
|
||||||
|
|
||||||
defineEmits<{
|
defineEmits<{
|
||||||
(event: 'select', user: Misskey.entities.UserLite): void
|
(event: 'select', user: Misskey.entities.UserLite): void
|
||||||
|
@ -98,6 +103,10 @@ defineEmits<{
|
||||||
height: 2.5em;
|
height: 2.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.muted {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
@container (max-width: 600px) {
|
@container (max-width: 600px) {
|
||||||
.root {
|
.root {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
|
|
|
@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<template #default="{ items: notes }">
|
<template #default="{ items: notes }">
|
||||||
<MkDateSeparatedList v-slot="{ item: note }" :items="notes" :class="$style.panel" :noGap="true">
|
<MkDateSeparatedList v-slot="{ item: note }" :items="notes" :class="$style.panel" :noGap="true">
|
||||||
<FollowingFeedEntry :note="note" @select="userSelected"/>
|
<FollowingFeedEntry v-if="!isHardMuted(note)" :isMuted="isSoftMuted(note)" :note="note" @select="userSelected"/>
|
||||||
</MkDateSeparatedList>
|
</MkDateSeparatedList>
|
||||||
</template>
|
</template>
|
||||||
</MkPagination>
|
</MkPagination>
|
||||||
|
@ -68,7 +68,9 @@ import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { useRouter } from '@/router/supplier.js';
|
import { useRouter } from '@/router/supplier.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import MkPageHeader from '@/components/global/MkPageHeader.vue';
|
import MkPageHeader from '@/components/global/MkPageHeader.vue';
|
||||||
|
import { $i } from '@/account.js';
|
||||||
import MkLoading from '@/components/global/MkLoading.vue';
|
import MkLoading from '@/components/global/MkLoading.vue';
|
||||||
|
import { getNoteText } from '@/scripts/check-word-mute.js';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
initialTab?: FollowingFeedTab,
|
initialTab?: FollowingFeedTab,
|
||||||
|
@ -158,6 +160,81 @@ async function onChangeTab(): Promise<void> {
|
||||||
await showUserNotes('');
|
await showUserNotes('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const softMutePatterns = ref(buildMutePatterns($i?.mutedWords));
|
||||||
|
const hardMutePatterns = ref(buildMutePatterns($i?.hardMutedWords));
|
||||||
|
|
||||||
|
function buildMutePatterns(mutedWords: (string | string[])[] | undefined): RegExp[] {
|
||||||
|
if (!mutedWords || mutedWords.length < 1) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// flags -> pattern[]
|
||||||
|
const patternMap = new Map<string, Set<string>>();
|
||||||
|
for (const mute of mutedWords) {
|
||||||
|
let flags: string;
|
||||||
|
let patterns: string[];
|
||||||
|
|
||||||
|
if (!mute) {
|
||||||
|
continue;
|
||||||
|
} else if (Array.isArray(mute)) {
|
||||||
|
patterns = mute;
|
||||||
|
flags = 'i';
|
||||||
|
} else {
|
||||||
|
const match = mute.match(/^\/(.+)\/(.*)$/);
|
||||||
|
if (!match) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
patterns = [match[1]];
|
||||||
|
flags = match[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let flagPatterns = patternMap.get(flags);
|
||||||
|
if (!flagPatterns) {
|
||||||
|
flagPatterns = new Set<string>();
|
||||||
|
patternMap.set(flags, flagPatterns);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const pattern of patterns) {
|
||||||
|
flagPatterns.add(pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Array
|
||||||
|
.from(patternMap)
|
||||||
|
.map(([flag, patterns]) => {
|
||||||
|
const pattern = Array.from(patterns).map(p => `(${p})`).join('|');
|
||||||
|
return new RegExp(pattern, flag);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adapted from MkNote.ts
|
||||||
|
function isSoftMuted(note: Misskey.entities.Note): boolean {
|
||||||
|
return isMuted(note, softMutePatterns.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isHardMuted(note: Misskey.entities.Note): boolean {
|
||||||
|
return isMuted(note, hardMutePatterns.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isMuted(note: Misskey.entities.Note, mutes: RegExp[]): boolean {
|
||||||
|
if (mutes.length < 1) return false;
|
||||||
|
|
||||||
|
return checkMute(note, mutes)
|
||||||
|
|| checkMute(note.reply, mutes)
|
||||||
|
|| checkMute(note.renote, mutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adapted from check-word-mute.ts
|
||||||
|
function checkMute(note: Misskey.entities.Note | undefined | null, mutes: RegExp[]): boolean {
|
||||||
|
if (!note) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const noteText = getNoteText(note);
|
||||||
|
return mutes.some(p => p.test(noteText));
|
||||||
|
}
|
||||||
|
|
||||||
const latestNotesPaging = shallowRef<InstanceType<typeof MkPagination>>();
|
const latestNotesPaging = shallowRef<InstanceType<typeof MkPagination>>();
|
||||||
|
|
||||||
const latestNotesPagination: Paging<'notes/following'> = {
|
const latestNotesPagination: Paging<'notes/following'> = {
|
||||||
|
|
|
@ -43,7 +43,7 @@ export function checkWordMute(note: Note, me: MeDetailed | null | undefined, mut
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNoteText(note: Note): string {
|
export function getNoteText(note: Note): string {
|
||||||
const textParts: string[] = [];
|
const textParts: string[] = [];
|
||||||
|
|
||||||
if (note.cw) textParts.push(note.cw);
|
if (note.cw) textParts.push(note.cw);
|
||||||
|
|
Loading…
Reference in a new issue