diff options
| -rw-r--r-- | CHANGELOG.md | 2 | ||||
| -rw-r--r-- | locales/ja-JP.yml | 4 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkImgWithBlurhash.vue | 8 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkMediaImage.vue | 10 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkMediaVideo.vue | 7 | ||||
| -rw-r--r-- | packages/frontend/src/pages/settings/general.vue | 2 | ||||
| -rw-r--r-- | packages/frontend/src/store.ts | 4 |
7 files changed, 28 insertions, 9 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index ab593c1b1c..0c18b47f0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -118,6 +118,8 @@ - 猫耳のアバター内部部分をぼかしでマスク表示してより猫耳っぽく見えるように - 「UIのアニメーションを減らす」 (`reduceAnimation`) で猫耳を撫でられなくなります - Add Minimizing ("folding") of windows +- 「データセーバー」モードを追加 +- 非NSFWメディアが隠れている際にも「閲覧注意」が出てしまう問題を修正 ### Server - PostgreSQLのレプリケーション対応 diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 5f5bcfd879..b991ec2e9b 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -271,6 +271,7 @@ home: "ホーム" remoteUserCaution: "リモートユーザーのため、情報が不完全です。" activity: "アクティビティ" images: "画像" +image: "画像" birthday: "誕生日" yearsOld: "{age}歳" registeredDate: "登録日" @@ -990,6 +991,9 @@ enableChartsForFederatedInstances: "リモートサーバーのチャートを showClipButtonInNoteFooter: "ノートのアクションにクリップを追加" largeNoteReactions: "ノートのリアクションを大きく表示" noteIdOrUrl: "ノートIDまたはURL" +video: "動画" +videos: "動画" +dataSaver: "データセーバー" accountMigration: "アカウントの引っ越し" accountMoved: "このユーザーは新しいアカウントに引っ越しました:" forceShowAds: "常に広告を表示する" diff --git a/packages/frontend/src/components/MkImgWithBlurhash.vue b/packages/frontend/src/components/MkImgWithBlurhash.vue index 944c76d7dc..9b3dbf8618 100644 --- a/packages/frontend/src/components/MkImgWithBlurhash.vue +++ b/packages/frontend/src/components/MkImgWithBlurhash.vue @@ -1,7 +1,7 @@ <template> <div :class="[$style.root, { [$style.cover]: cover }]" :title="title"> - <canvas v-if="!loaded" ref="canvas" :class="$style.canvas" :width="size" :height="size" :title="title"/> - <img v-if="src" :class="$style.img" :src="src" :title="title" :alt="alt" @load="onLoad"/> + <canvas v-if="!loaded || forceBlurhash" ref="canvas" :class="$style.canvas" :width="size" :height="size" :title="title"/> + <img v-if="src && !forceBlurhash" :class="$style.img" :src="src" :title="title" :alt="alt" @load="onLoad"/> </div> </template> @@ -12,16 +12,18 @@ import { decode } from 'blurhash'; const props = withDefaults(defineProps<{ src?: string | null; hash?: string; - alt?: string; + alt?: string | null; title?: string | null; size?: number; cover?: boolean; + forceBlurhash?: boolean; }>(), { src: null, alt: '', title: null, size: 64, cover: true, + forceBlurhash: false, }); const canvas = $shallowRef<HTMLCanvasElement>(); diff --git a/packages/frontend/src/components/MkMediaImage.vue b/packages/frontend/src/components/MkMediaImage.vue index a4065dcd07..8d0877ef61 100644 --- a/packages/frontend/src/components/MkMediaImage.vue +++ b/packages/frontend/src/components/MkMediaImage.vue @@ -1,9 +1,10 @@ <template> <div v-if="hide" :class="$style.hidden" @click="hide = false"> - <ImgWithBlurhash style="filter: brightness(0.5);" :hash="image.blurhash" :title="image.comment" :alt="image.comment"/> + <ImgWithBlurhash style="filter: brightness(0.5);" :hash="image.blurhash" :title="image.comment" :alt="image.comment" :force-blurhash="defaultStore.state.enableDataSaverMode" /> <div :class="$style.hiddenText"> <div :class="$style.hiddenTextWrapper"> - <b style="display: block;"><i class="ti ti-alert-triangle"></i> {{ i18n.ts.sensitive }}</b> + <b v-if="image.isSensitive" style="display: block;"><i class="ti ti-alert-triangle"></i> {{ i18n.ts.sensitive }}{{ defaultStore.state.enableDataSaverMode ? ` (${i18n.ts.image}${image.size ? ' ' + bytes(image.size) : ''})` : '' }}</b> + <b v-else style="display: block;"><i class="ti ti-photo"></i> {{ defaultStore.state.enableDataSaverMode && image.size ? bytes(image.size) : i18n.ts.image }}</b> <span style="display: block;">{{ i18n.ts.clickToShow }}</span> </div> </div> @@ -28,6 +29,7 @@ import { watch } from 'vue'; import * as misskey from 'misskey-js'; import { getStaticImageUrl } from '@/scripts/media-proxy'; +import bytes from '@/filters/bytes'; import ImgWithBlurhash from '@/components/MkImgWithBlurhash.vue'; import { defaultStore } from '@/store'; import { i18n } from '@/i18n'; @@ -38,7 +40,7 @@ const props = defineProps<{ }>(); let hide = $ref(true); -let darkMode = $ref(defaultStore.state.darkMode); +let darkMode: boolean = $ref(defaultStore.state.darkMode); const url = (props.raw || defaultStore.state.loadRawImages) ? props.image.url @@ -48,7 +50,7 @@ const url = (props.raw || defaultStore.state.loadRawImages) // Plugin:register_note_view_interruptor を使って書き換えられる可能性があるためwatchする watch(() => props.image, () => { - hide = (defaultStore.state.nsfw === 'force') ? true : props.image.isSensitive && (defaultStore.state.nsfw !== 'ignore'); + hide = (defaultStore.state.nsfw === 'force' || defaultStore.state.enableDataSaverMode) ? true : (props.image.isSensitive && defaultStore.state.nsfw !== 'ignore'); }, { deep: true, immediate: true, diff --git a/packages/frontend/src/components/MkMediaVideo.vue b/packages/frontend/src/components/MkMediaVideo.vue index e02a7af09e..a4b76300e6 100644 --- a/packages/frontend/src/components/MkMediaVideo.vue +++ b/packages/frontend/src/components/MkMediaVideo.vue @@ -1,7 +1,9 @@ <template> <div v-if="hide" class="icozogqfvdetwohsdglrbswgrejoxbdj" @click="hide = false"> + <!-- 【注意】dataSaverMode が有効になっている際には、hide が false になるまでサムネイルや動画を読み込まないようにすること --> <div> - <b><i class="ti ti-alert-triangle"></i> {{ i18n.ts.sensitive }}</b> + <b v-if="video.isSensitive"><i class="ti ti-alert-triangle"></i> {{ i18n.ts.sensitive }}{{ defaultStore.state.enableDataSaverMode ? ` (${i18n.ts.video}${video.size ? ' ' + bytes(video.size) : ''})` : '' }}</b> + <b v-else><i class="ti ti-movie"></i> {{ defaultStore.state.enableDataSaverMode && video.size ? bytes(video.size) : i18n.ts.video }}</b> <span>{{ i18n.ts.clickToShow }}</span> </div> </div> @@ -25,6 +27,7 @@ <script lang="ts" setup> import { ref } from 'vue'; import * as misskey from 'misskey-js'; +import bytes from '@/filters/bytes'; import VuePlyr from 'vue-plyr'; import { defaultStore } from '@/store'; import 'vue-plyr/dist/vue-plyr.css'; @@ -34,7 +37,7 @@ const props = defineProps<{ video: misskey.entities.DriveFile; }>(); -const hide = ref((defaultStore.state.nsfw === 'force') ? true : props.video.isSensitive && (defaultStore.state.nsfw !== 'ignore')); +const hide = ref((defaultStore.state.nsfw === 'force' || defaultStore.state.enableDataSaverMode) ? true : (props.video.isSensitive && defaultStore.state.nsfw !== 'ignore')); </script> <style lang="scss" scoped> diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue index 904fd3f952..29657c04ac 100644 --- a/packages/frontend/src/pages/settings/general.vue +++ b/packages/frontend/src/pages/settings/general.vue @@ -62,6 +62,7 @@ <MkSwitch v-model="useSystemFont">{{ i18n.ts.useSystemFont }}</MkSwitch> <MkSwitch v-model="disableDrawer">{{ i18n.ts.disableDrawer }}</MkSwitch> <MkSwitch v-model="forceShowAds">{{ i18n.ts.forceShowAds }}</MkSwitch> + <MkSwitch v-model="enableDataSaverMode">{{ i18n.ts.dataSaver }}</MkSwitch> </div> <div> <MkRadios v-model="emojiStyle"> @@ -160,6 +161,7 @@ const disableDrawer = computed(defaultStore.makeGetterSetter('disableDrawer')); const disableShowingAnimatedImages = computed(defaultStore.makeGetterSetter('disableShowingAnimatedImages')); const forceShowAds = computed(defaultStore.makeGetterSetter('forceShowAds')); const loadRawImages = computed(defaultStore.makeGetterSetter('loadRawImages')); +const enableDataSaverMode = computed(defaultStore.makeGetterSetter('enableDataSaverMode')); const imageNewTab = computed(defaultStore.makeGetterSetter('imageNewTab')); const nsfw = computed(defaultStore.makeGetterSetter('nsfw')); const showFixedPostForm = computed(defaultStore.makeGetterSetter('showFixedPostForm')); diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index a935093240..a8e01b9385 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -182,6 +182,10 @@ export const defaultStore = markRaw(new Storage('base', { where: 'device', default: false, }, + enableDataSaverMode: { + where: 'device', + default: false, + }, disableShowingAnimatedImages: { where: 'device', default: matchMedia('(prefers-reduced-motion)').matches, |