From fe0bb21b37833e33f44b8e6ef697ac3259518b0c Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Mon, 16 Jan 2023 11:21:04 +0900 Subject: [PATCH] enhance(client): make possible to hide ads Resolve #9590 Resolve #8996 --- locales/ja-JP.yml | 2 ++ packages/backend/src/core/RoleService.ts | 3 +++ .../frontend/src/components/global/MkAd.vue | 12 ++++++++++- .../frontend/src/pages/admin/roles.editor.vue | 21 +++++++++++++++++++ packages/frontend/src/pages/admin/roles.vue | 9 ++++++++ packages/frontend/src/store.ts | 6 +++++- 6 files changed, 51 insertions(+), 2 deletions(-) diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 174c28f4a1..f0e53cb814 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -982,6 +982,7 @@ _role: userEachUserListsMax: "ユーザーリスト内ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®æœ€å¤§æ•°" rateLimitFactor: "レートリミット" descriptionOfRateLimitFactor: "å°ã•ã„ã»ã©åˆ¶é™ãŒç·©å’Œã•ã‚Œã€å¤§ãã„ã»ã©åˆ¶é™ãŒå¼·åŒ–ã•ã‚Œã¾ã™ã€‚" + canHideAds: "広告ã®éžè¡¨ç¤º" _condition: isLocal: "ãƒãƒ¼ã‚«ãƒ«ãƒ¦ãƒ¼ã‚¶ãƒ¼" isRemote: "リモートユーザー" @@ -1032,6 +1033,7 @@ _accountDelete: _ad: back: "戻る" reduceFrequencyOfThisAd: "ã“ã®åºƒå‘Šã®è¡¨ç¤ºé »åº¦ã‚’下ã’ã‚‹" + hide: "表示ã—ãªã„" _forgotPassword: enterEmail: "アカウントã«ç™»éŒ²ã—ãŸãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’入力ã—ã¦ãã ã•ã„。ãã®ã‚¢ãƒ‰ãƒ¬ã‚¹å®›ã¦ã«ã€ãƒ‘スワードリセット用ã®ãƒªãƒ³ã‚¯ãŒé€ä¿¡ã•ã‚Œã¾ã™ã€‚" diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index 0ba5ca9a03..c0f5eae3d7 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -19,6 +19,7 @@ export type RolePolicies = { canPublicNote: boolean; canInvite: boolean; canManageCustomEmojis: boolean; + canHideAds: boolean; driveCapacityMb: number; pinLimit: number; antennaLimit: number; @@ -37,6 +38,7 @@ export const DEFAULT_POLICIES: RolePolicies = { canPublicNote: true, canInvite: false, canManageCustomEmojis: false, + canHideAds: false, driveCapacityMb: 100, pinLimit: 5, antennaLimit: 5, @@ -223,6 +225,7 @@ export class RoleService implements OnApplicationShutdown { canPublicNote: calc('canPublicNote', vs => vs.some(v => v === true)), canInvite: calc('canInvite', vs => vs.some(v => v === true)), canManageCustomEmojis: calc('canManageCustomEmojis', vs => vs.some(v => v === true)), + canHideAds: calc('canHideAds', vs => vs.some(v => v === true)), driveCapacityMb: calc('driveCapacityMb', vs => Math.max(...vs)), pinLimit: calc('pinLimit', vs => Math.max(...vs)), antennaLimit: calc('antennaLimit', vs => Math.max(...vs)), diff --git a/packages/frontend/src/components/global/MkAd.vue b/packages/frontend/src/components/global/MkAd.vue index a1ac682a45..a518484a5d 100644 --- a/packages/frontend/src/components/global/MkAd.vue +++ b/packages/frontend/src/components/global/MkAd.vue @@ -1,5 +1,5 @@ <template> -<div v-if="chosen" :class="$style.root"> +<div v-if="chosen && !shouldHide" :class="$style.root"> <div v-if="!showMenu" :class="[$style.main, $style['form_' + chosen.place]]"> <a :href="chosen.url" target="_blank" :class="$style.link"> <img :src="chosen.imageUrl" :class="$style.img"> @@ -11,6 +11,7 @@ <div>Ads by {{ host }}</div> <!--<MkButton class="button" primary>{{ $ts._ad.like }}</MkButton>--> <MkButton v-if="chosen.ratio !== 0" :class="$style.menuButton" @click="reduceFrequency">{{ $ts._ad.reduceFrequencyOfThisAd }}</MkButton> + <MkButton v-if="$i && $i.policies.canHideAds" :class="$style.menuButton" @click="hide">{{ $ts._ad.hide }}</MkButton> <button class="_textButton" @click="toggleMenu">{{ $ts._ad.back }}</button> </div> </div> @@ -25,6 +26,7 @@ import { host } from '@/config'; import MkButton from '@/components/MkButton.vue'; import { defaultStore } from '@/store'; import * as os from '@/os'; +import { $i } from '@/account'; type Ad = (typeof instance)['ads'][number]; @@ -81,6 +83,7 @@ const choseAd = (): Ad | null => { }; const chosen = ref(choseAd()); +let shouldHide = $ref(chosen.value && $i && $i.policies.canHideAds && defaultStore.state.hiddenAds.includes(chosen.value.id)); function reduceFrequency(): void { if (chosen.value == null) return; @@ -90,6 +93,13 @@ function reduceFrequency(): void { chosen.value = choseAd(); showMenu.value = false; } + +function hide() { + if (chosen.value == null) return; + defaultStore.push('hiddenAds', chosen.value.id); + os.success(); + shouldHide = true; +} </script> <style lang="scss" module> diff --git a/packages/frontend/src/pages/admin/roles.editor.vue b/packages/frontend/src/pages/admin/roles.editor.vue index e5f4675c19..ae5ef39bae 100644 --- a/packages/frontend/src/pages/admin/roles.editor.vue +++ b/packages/frontend/src/pages/admin/roles.editor.vue @@ -335,6 +335,26 @@ </MkRange> </div> </MkFolder> + + <MkFolder v-if="matchQuery([i18n.ts._role._options.canHideAds, 'canHideAds'])"> + <template #label>{{ i18n.ts._role._options.canHideAds }}</template> + <template #suffix> + <span v-if="policies.canHideAds.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span> + <span v-else>{{ policies.canHideAds.value ? i18n.ts.yes : i18n.ts.no }}</span> + <span :class="$style.priorityIndicator"><i :class="getPriorityIcon(policies.canHideAds)"></i></span> + </template> + <div class="_gaps"> + <MkSwitch v-model="policies.canHideAds.useDefault" :readonly="readonly"> + <template #label>{{ i18n.ts._role.useBaseValue }}</template> + </MkSwitch> + <MkSwitch v-model="policies.canHideAds.value" :disabled="policies.canHideAds.useDefault" :readonly="readonly"> + <template #label>{{ i18n.ts.enable }}</template> + </MkSwitch> + <MkRange v-model="policies.canHideAds.priority" :min="0" :max="2" :step="1" easing :text-converter="(v) => v === 0 ? i18n.ts._role._priority.low : v === 1 ? i18n.ts._role._priority.middle : v === 2 ? i18n.ts._role._priority.high : ''"> + <template #label>{{ i18n.ts._role.priority }}</template> + </MkRange> + </div> + </MkFolder> </div> </FormSlot> @@ -376,6 +396,7 @@ const ROLE_POLICIES = [ 'canPublicNote', 'canInvite', 'canManageCustomEmojis', + 'canHideAds', 'driveCapacityMb', 'pinLimit', 'antennaLimit', diff --git a/packages/frontend/src/pages/admin/roles.vue b/packages/frontend/src/pages/admin/roles.vue index f074069df0..6e0c038982 100644 --- a/packages/frontend/src/pages/admin/roles.vue +++ b/packages/frontend/src/pages/admin/roles.vue @@ -121,6 +121,14 @@ </MkInput> </MkFolder> + <MkFolder> + <template #label>{{ i18n.ts._role._options.canHideAds }}</template> + <template #suffix>{{ policies.canHideAds ? i18n.ts.yes : i18n.ts.no }}</template> + <MkSwitch v-model="policies.canHideAds"> + <template #label>{{ i18n.ts.enable }}</template> + </MkSwitch> + </MkFolder> + <MkButton primary rounded @click="updateBaseRole">{{ i18n.ts.save }}</MkButton> </div> </MkFolder> @@ -156,6 +164,7 @@ const ROLE_POLICIES = [ 'canPublicNote', 'canInvite', 'canManageCustomEmojis', + 'canHideAds', 'driveCapacityMb', 'pinLimit', 'antennaLimit', diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index b2bf8db646..b29d9355ba 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -86,6 +86,10 @@ export const defaultStore = markRaw(new Storage('base', { where: 'account', default: [] as string[], }, + hiddenAds: { + where: 'account', + default: [] as string[], + }, menu: { where: 'deviceAccount', @@ -293,10 +297,10 @@ interface Watcher { /** * 常ã«ãƒ¡ãƒ¢ãƒªã«ãƒãƒ¼ãƒ‰ã—ã¦ãŠãå¿…è¦ãŒãªã„よã†ãªè¨å®šæƒ…å ±ã‚’ä¿ç®¡ã™ã‚‹ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸(éžãƒªã‚¢ã‚¯ãƒ†ã‚£ãƒ–) */ +import { miLocalStorage } from './local-storage'; import lightTheme from '@/themes/l-light.json5'; import darkTheme from '@/themes/d-green-lime.json5'; import { Note, UserDetailed } from 'misskey-js/built/entities'; -import { miLocalStorage } from './local-storage'; export class ColdDeviceStorage { public static default = { -- GitLab