diff --git a/CHANGELOG.md b/CHANGELOG.md index ed8a220e0..eb5ac2848 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ You should also include the user name that made the change. - コンディショナルロールもバッジとして表示可能に - enhance(client): ロールをより簡単に付与できるように - enhance(client): 一度見たノートのRenoteは省略して表示するように +- enhance(client): 迷惑になる可能性のある投稿を行う前に警告を表示 - 一部のMFM構文をopt-outに ### Bugfixes diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 031e90215..5c919c303 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -947,6 +947,10 @@ selectFromPresets: "プリセットから選択" achievements: "実績" gotInvalidResponseError: "サーバーの応答が無効です" gotInvalidResponseErrorDescription: "サーバーがダウンまたはメンテナンスしている可能性があります。しばらくしてから再度お試しください。" +thisPostMayBeAnnoying: "この投稿は迷惑になる可能性があります。" +thisPostMayBeAnnoyingHome: "ホームに投稿" +thisPostMayBeAnnoyingCancel: "やめる" +thisPostMayBeAnnoyingIgnore: "このまま投稿" _achievements: earnedAt: "獲得日時" diff --git a/packages/frontend/src/components/MkDialog.vue b/packages/frontend/src/components/MkDialog.vue index da4db6340..969035343 100644 --- a/packages/frontend/src/components/MkDialog.vue +++ b/packages/frontend/src/components/MkDialog.vue @@ -32,7 +32,7 @@ {{ cancelText ?? i18n.ts.cancel }}
- {{ action.text }} + {{ action.text }}
diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue index a06bdecaa..f15906c1c 100644 --- a/packages/frontend/src/components/MkPostForm.vue +++ b/packages/frontend/src/components/MkPostForm.vue @@ -579,6 +579,36 @@ async function post(ev?: MouseEvent) { os.popup(MkRippleEffect, { x, y }, {}, 'end'); } + const annoying = + text.includes('$[x2') || + text.includes('$[x3') || + text.includes('$[x4') || + text.includes('$[scale') || + text.includes('$[position'); + if (annoying) { + const { canceled, result } = await os.actions({ + type: 'warning', + text: i18n.ts.thisPostMayBeAnnoying, + actions: [{ + value: 'home', + text: i18n.ts.thisPostMayBeAnnoyingHome, + primary: true, + }, { + value: 'cancel', + text: i18n.ts.thisPostMayBeAnnoyingCancel, + }, { + value: 'ignore', + text: i18n.ts.thisPostMayBeAnnoyingIgnore, + }], + }); + + if (canceled) return; + if (result === 'cancel') return; + if (result === 'home') { + visibility = 'home'; + } + } + let postData = { text: text === '' ? undefined : text, fileIds: files.length > 0 ? files.map(f => f.id) : undefined, diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts index 499703066..639f4eaf1 100644 --- a/packages/frontend/src/os.ts +++ b/packages/frontend/src/os.ts @@ -186,6 +186,38 @@ export function confirm(props: { }); } +// TODO: const T extends ... にしたい +// https://zenn.dev/general_link/articles/813e47b7a0eef7#const-type-parameters +export function actions(props: { + type: 'error' | 'info' | 'success' | 'warning' | 'waiting' | 'question'; + title?: string | null; + text?: string | null; + actions: T; +}): Promise<{ canceled: true; result: undefined; } | { + canceled: false; result: T[number]['value']; +}> { + return new Promise((resolve, reject) => { + popup(MkDialog, { + ...props, + actions: props.actions.map(a => ({ + text: a.text, + primary: a.primary, + callback: () => { + resolve({ canceled: false, result: a.value }); + }, + })), + }, { + done: result => { + resolve(result ? result : { canceled: true }); + }, + }, 'closed'); + }); +} + export function inputText(props: { type?: 'text' | 'email' | 'password' | 'url'; title?: string | null;