diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 31b02821bf..e869f5b015 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -758,6 +758,10 @@ low: "低" emailNotConfiguredWarning: "メールアドレスの設定がされていません。" ratio: "比率" +_ad: + back: "戻る" + reduceFrequencyOfThisAd: "この広告の表示頻度を下げる" + _forgotPassword: enterEmail: "アカウントに登録したメールアドレスを入力してください。そのアドレス宛てに、パスワードリセット用のリンクが送信されます。" ifNoEmail: "メールアドレスを登録していない場合は、管理者までお問い合わせください。" diff --git a/src/client/components/global/ad.vue b/src/client/components/global/ad.vue index e340f846ee..8397b2229e 100644 --- a/src/client/components/global/ad.vue +++ b/src/client/components/global/ad.vue @@ -9,8 +9,9 @@ @@ -22,6 +23,8 @@ import { defineComponent, ref } from 'vue'; import { Instance, instance } from '@client/instance'; import { host } from '@client/config'; import MkButton from '@client/components/ui/button.vue'; +import { defaultStore } from '@client/store'; +import * as os from '@client/os'; export default defineComponent({ components: { @@ -50,10 +53,15 @@ export default defineComponent({ return props.specify as Instance['ads'][number]; } - let ads = instance.ads.filter(ad => props.prefer.includes(ad.place)); + const allAds = instance.ads.map(ad => defaultStore.state.mutedAds.includes(ad.id) ? { + ...ad, + ratio: 0 + } : ad); + + let ads = allAds.filter(ad => props.prefer.includes(ad.place)); if (ads.length === 0) { - ads = instance.ads.filter(ad => ad.place === 'square'); + ads = allAds.filter(ad => ad.place === 'square'); } const lowPriorityAds = ads.filter(ad => ad.ratio === 0); @@ -82,11 +90,23 @@ export default defineComponent({ return null; }; + const chosen = ref(choseAd()); + + const reduceFrequency = () => { + if (chosen.value == null) return; + if (defaultStore.state.mutedAds.includes(chosen.value.id)) return; + defaultStore.push('mutedAds', chosen.value.id); + os.success(); + chosen.value = choseAd(); + showMenu.value = false; + }; + return { - ad: choseAd(), + ad: chosen, showMenu, toggleMenu, host, + reduceFrequency, }; } }); @@ -170,6 +190,10 @@ export default defineComponent({ margin: 0 auto; max-width: 400px; border: solid 1px var(--divider); + + > .button { + margin: 8px auto; + } } } } diff --git a/src/client/instance.ts b/src/client/instance.ts index ad9e1a95fd..024ff1acbd 100644 --- a/src/client/instance.ts +++ b/src/client/instance.ts @@ -8,6 +8,7 @@ export type Instance = { category: string; }[]; ads: { + id: string; ratio: number; place: string; url: string; diff --git a/src/client/store.ts b/src/client/store.ts index 376135a99d..1a3286554d 100644 --- a/src/client/store.ts +++ b/src/client/store.ts @@ -55,6 +55,10 @@ export const defaultStore = markRaw(new Storage('base', { where: 'account', default: [] }, + mutedAds: { + where: 'account', + default: [] as string[] + }, menu: { where: 'deviceAccount', diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts index d170317f1c..26d9110ea9 100644 --- a/src/server/api/endpoints/meta.ts +++ b/src/server/api/endpoints/meta.ts @@ -509,6 +509,7 @@ export default define(meta, async (ps, me) => { maxNoteTextLength: Math.min(instance.maxNoteTextLength, DB_MAX_NOTE_TEXT_LENGTH), emojis: await Emojis.packMany(emojis), ads: ads.map(ad => ({ + id: ad.id, url: ad.url, place: ad.place, ratio: ad.ratio,