summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsyuilo <4439005+syuilo@users.noreply.github.com>2025-05-11 14:17:08 +0900
committersyuilo <4439005+syuilo@users.noreply.github.com>2025-05-11 14:17:08 +0900
commit4d08c0a82b6bdda43c1b7255c9c89d44c8958294 (patch)
tree475c645ec743615592a868a806cfabdff656961b
parentrefactor(frontend): better type def of usePagination (diff)
downloadmisskey-4d08c0a82b6bdda43c1b7255c9c89d44c8958294.tar.gz
misskey-4d08c0a82b6bdda43c1b7255c9c89d44c8958294.tar.bz2
misskey-4d08c0a82b6bdda43c1b7255c9c89d44c8958294.zip
enhance(frontend): blurhash無効化オプションを追加
-rw-r--r--CHANGELOG.md1
-rw-r--r--locales/index.d.ts4
-rw-r--r--locales/ja-JP.yml1
-rw-r--r--packages/frontend-embed/src/components/EmMediaImage.vue4
-rw-r--r--packages/frontend/src/components/MkDriveFileThumbnail.vue20
-rw-r--r--packages/frontend/src/components/MkGalleryPostPreview.vue4
-rw-r--r--packages/frontend/src/components/MkMediaImage.vue4
-rw-r--r--packages/frontend/src/components/global/MkAvatar.vue3
-rw-r--r--packages/frontend/src/pages/settings/preferences.vue11
-rw-r--r--packages/frontend/src/preferences/def.ts3
10 files changed, 45 insertions, 10 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bf98a44ac4..e98a09c66e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@
- 従来のWebsocket接続を行うモードはリアルタイムモードとして再定義されました
- チャットなど、一部の機能は引き続き設定に関わらずWebsocket接続が行われます
- Enhance: メモリ使用量を軽減しました
+- Enhance: 画像の高品質なプレースホルダを無効化してパフォーマンスを向上させるオプションを追加
- Enhance: 招待されているが参加していないルームを開いたときに、招待を承認するかどうか尋ねるように
- Enhance: リプライ元にアンケートがあることが表示されるように
- Enhance: ノートのサーバー情報のデザインを改善・パフォーマンス向上
diff --git a/locales/index.d.ts b/locales/index.d.ts
index a49f7b4d35..8774cc4aee 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -5714,6 +5714,10 @@ export interface Locale extends ILocale {
*/
"useStickyIcons": string;
/**
+ * 高品質な画像のプレースホルダを表示
+ */
+ "enableHighQualityImagePlaceholders": string;
+ /**
* ナビゲーションバーに副ボタンを表示
*/
"showNavbarSubButtons": string;
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 8b2d31f7cd..79cb4b41d5 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1428,6 +1428,7 @@ _settings:
makeEveryTextElementsSelectable: "全てのテキスト要素を選択可能にする"
makeEveryTextElementsSelectable_description: "有効にすると、一部のシチュエーションでのユーザビリティが低下する場合があります。"
useStickyIcons: "アイコンをスクロールに追従させる"
+ enableHighQualityImagePlaceholders: "高品質な画像のプレースホルダを表示"
showNavbarSubButtons: "ナビゲーションバーに副ボタンを表示"
ifOn: "オンのとき"
ifOff: "オフのとき"
diff --git a/packages/frontend-embed/src/components/EmMediaImage.vue b/packages/frontend-embed/src/components/EmMediaImage.vue
index 2c96ce3215..94f0268da4 100644
--- a/packages/frontend-embed/src/components/EmMediaImage.vue
+++ b/packages/frontend-embed/src/components/EmMediaImage.vue
@@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
target="_blank"
rel="noopener"
>
- <ImgWithBlurhash
+ <EmImgWithBlurhash
:hash="image.blurhash"
:src="hide ? null : url"
:forceBlurhash="hide"
@@ -45,7 +45,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { ref, computed } from 'vue';
import * as Misskey from 'misskey-js';
-import ImgWithBlurhash from '@/components/EmImgWithBlurhash.vue';
+import EmImgWithBlurhash from '@/components/EmImgWithBlurhash.vue';
import { i18n } from '@/i18n.js';
const props = withDefaults(defineProps<{
diff --git a/packages/frontend/src/components/MkDriveFileThumbnail.vue b/packages/frontend/src/components/MkDriveFileThumbnail.vue
index 6e0ae36880..88afdef114 100644
--- a/packages/frontend/src/components/MkDriveFileThumbnail.vue
+++ b/packages/frontend/src/components/MkDriveFileThumbnail.vue
@@ -11,15 +11,24 @@ SPDX-License-Identifier: AGPL-3.0-only
[$style.large]: large,
}]"
>
- <ImgWithBlurhash
- v-if="isThumbnailAvailable"
+ <MkImgWithBlurhash
+ v-if="isThumbnailAvailable && prefer.s.enableHighQualityImagePlaceholders"
:hash="file.blurhash"
:src="file.thumbnailUrl"
:alt="file.name"
:title="file.name"
+ :class="$style.thumbnail"
:cover="fit !== 'contain'"
:forceBlurhash="forceBlurhash"
/>
+ <img
+ v-else-if="isThumbnailAvailable"
+ :src="file.thumbnailUrl"
+ :alt="file.name"
+ :title="file.name"
+ :class="$style.thumbnail"
+ :style="{ objectFit: fit }"
+ />
<i v-else-if="is === 'image'" class="ti ti-photo" :class="$style.icon"></i>
<i v-else-if="is === 'video'" class="ti ti-video" :class="$style.icon"></i>
<i v-else-if="is === 'audio' || is === 'midi'" class="ti ti-file-music" :class="$style.icon"></i>
@@ -36,7 +45,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { computed } from 'vue';
import * as Misskey from 'misskey-js';
-import ImgWithBlurhash from '@/components/MkImgWithBlurhash.vue';
+import MkImgWithBlurhash from '@/components/MkImgWithBlurhash.vue';
+import { prefer } from '@/preferences.js';
const props = defineProps<{
file: Misskey.entities.DriveFile;
@@ -115,4 +125,8 @@ const isThumbnailAvailable = computed(() => {
.large .icon {
font-size: 40px;
}
+
+.thumbnail {
+ width: 100%;
+}
</style>
diff --git a/packages/frontend/src/components/MkGalleryPostPreview.vue b/packages/frontend/src/components/MkGalleryPostPreview.vue
index 49a6c65170..e6fae285b3 100644
--- a/packages/frontend/src/components/MkGalleryPostPreview.vue
+++ b/packages/frontend/src/components/MkGalleryPostPreview.vue
@@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkA :to="`/gallery/${post.id}`" class="ttasepnz _panel" tabindex="-1" @pointerenter="enterHover" @pointerleave="leaveHover">
<div class="thumbnail">
<Transition>
- <ImgWithBlurhash
+ <MkImgWithBlurhash
class="img layered"
:transition="safe ? null : {
duration: 500,
@@ -34,7 +34,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import * as Misskey from 'misskey-js';
import { computed, ref } from 'vue';
-import ImgWithBlurhash from '@/components/MkImgWithBlurhash.vue';
+import MkImgWithBlurhash from '@/components/MkImgWithBlurhash.vue';
import { prefer } from '@/preferences.js';
const props = defineProps<{
diff --git a/packages/frontend/src/components/MkMediaImage.vue b/packages/frontend/src/components/MkMediaImage.vue
index bb42cbecf9..68ba7dfbe9 100644
--- a/packages/frontend/src/components/MkMediaImage.vue
+++ b/packages/frontend/src/components/MkMediaImage.vue
@@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
style: 'cursor: zoom-in;'
}"
>
- <ImgWithBlurhash
+ <MkImgWithBlurhash
:hash="image.blurhash"
:src="(prefer.s.dataSaver.media && hide) ? null : url"
:forceBlurhash="hide"
@@ -57,7 +57,7 @@ import type { MenuItem } from '@/types/menu.js';
import { copyToClipboard } from '@/utility/copy-to-clipboard';
import { getStaticImageUrl } from '@/utility/media-proxy.js';
import bytes from '@/filters/bytes.js';
-import ImgWithBlurhash from '@/components/MkImgWithBlurhash.vue';
+import MkImgWithBlurhash from '@/components/MkImgWithBlurhash.vue';
import { i18n } from '@/i18n.js';
import * as os from '@/os.js';
import { $i, iAmModerator } from '@/i.js';
diff --git a/packages/frontend/src/components/global/MkAvatar.vue b/packages/frontend/src/components/global/MkAvatar.vue
index 97c2069a2f..8a9cc5286a 100644
--- a/packages/frontend/src/components/global/MkAvatar.vue
+++ b/packages/frontend/src/components/global/MkAvatar.vue
@@ -5,7 +5,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<component :is="link ? MkA : 'span'" v-user-preview="preview ? user.id : undefined" v-bind="bound" class="_noSelect" :class="[$style.root, { [$style.animation]: animation, [$style.cat]: user.isCat, [$style.square]: squareAvatars }]" :style="{ color }" :title="acct(user)" @click="onClick">
- <MkImgWithBlurhash :class="$style.inner" :src="url" :hash="user.avatarBlurhash" :cover="true" :onlyAvgColor="true"/>
+ <MkImgWithBlurhash v-if="prefer.s.enableHighQualityImagePlaceholders" :class="$style.inner" :src="url" :hash="user.avatarBlurhash" :cover="true" :onlyAvgColor="true"/>
+ <img v-else :class="$style.inner" :src="url" alt="" decoding="async" style="pointer-events: none;"/>
<MkUserOnlineIndicator v-if="indicator" :class="$style.indicator" :user="user"/>
<div v-if="user.isCat" :class="[$style.ears]">
<div :class="$style.earLeft">
diff --git a/packages/frontend/src/pages/settings/preferences.vue b/packages/frontend/src/pages/settings/preferences.vue
index c6732e7787..5d2b09bbc1 100644
--- a/packages/frontend/src/pages/settings/preferences.vue
+++ b/packages/frontend/src/pages/settings/preferences.vue
@@ -575,6 +575,15 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkPreferenceContainer>
</SearchMarker>
+ <SearchMarker :keywords="['blurhash', 'image', 'photo', 'picture', 'thumbnail', 'placeholder']">
+ <MkPreferenceContainer k="enableHighQualityImagePlaceholders">
+ <MkSwitch v-model="enableHighQualityImagePlaceholders">
+ <template #label><SearchLabel>{{ i18n.ts._settings.enableHighQualityImagePlaceholders }}</SearchLabel></template>
+ <template #caption><SearchKeyword>{{ i18n.ts.turnOffToImprovePerformance }}</SearchKeyword></template>
+ </MkSwitch>
+ </MkPreferenceContainer>
+ </SearchMarker>
+
<SearchMarker :keywords="['sticky']">
<MkPreferenceContainer k="useStickyIcons">
<MkSwitch v-model="useStickyIcons">
@@ -808,6 +817,7 @@ const defaultFollowWithReplies = prefer.model('defaultFollowWithReplies');
const chatShowSenderName = prefer.model('chat.showSenderName');
const chatSendOnEnter = prefer.model('chat.sendOnEnter');
const useStickyIcons = prefer.model('useStickyIcons');
+const enableHighQualityImagePlaceholders = prefer.model('enableHighQualityImagePlaceholders');
const reduceAnimation = prefer.model('animation', v => !v, v => !v);
const animatedMfm = prefer.model('animatedMfm');
const disableShowingAnimatedImages = prefer.model('disableShowingAnimatedImages');
@@ -866,6 +876,7 @@ watch([
enableSeasonalScreenEffect,
chatShowSenderName,
useStickyIcons,
+ enableHighQualityImagePlaceholders,
keepScreenOn,
contextMenu,
fontSize,
diff --git a/packages/frontend/src/preferences/def.ts b/packages/frontend/src/preferences/def.ts
index af4423c6a4..f6cd2c0cb9 100644
--- a/packages/frontend/src/preferences/def.ts
+++ b/packages/frontend/src/preferences/def.ts
@@ -202,6 +202,9 @@ export const PREF_DEF = {
useStickyIcons: {
default: true,
},
+ enableHighQualityImagePlaceholders: {
+ default: true,
+ },
showFixedPostForm: {
default: false,
},