From f74c38f3135a5a84bd18fb8abca8639fa2107154 Mon Sep 17 00:00:00 2001
From: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
Date: Tue, 20 May 2025 13:42:30 +0900
Subject: enhance(frontend): URLプレビューをユーザーサイドで無効化できるように
(#16064)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* enhance(frontend): URLプレビューをユーザーサイドで無効化できるように
* fix lint
* Update Changelog
* fix: 設定項目をデータセーバーに移動
---
packages/frontend/src/components/MkLink.vue | 2 +-
packages/frontend/src/components/MkNote.vue | 2 +-
.../frontend/src/components/MkNoteDetailed.vue | 2 +-
packages/frontend/src/components/MkUrlPreview.vue | 4 +--
.../frontend/src/components/MkYouTubePlayer.vue | 2 +-
packages/frontend/src/components/global/MkUrl.vue | 2 +-
.../frontend/src/components/page/page.text.vue | 2 +-
packages/frontend/src/instance.ts | 2 --
.../frontend/src/pages/settings/preferences.vue | 10 ++++---
packages/frontend/src/preferences/def.ts | 5 ++--
.../frontend/src/utility/player-url-transform.ts | 26 ------------------
packages/frontend/src/utility/url-preview.ts | 31 ++++++++++++++++++++++
12 files changed, 49 insertions(+), 41 deletions(-)
delete mode 100644 packages/frontend/src/utility/player-url-transform.ts
create mode 100644 packages/frontend/src/utility/url-preview.ts
(limited to 'packages')
diff --git a/packages/frontend/src/components/MkLink.vue b/packages/frontend/src/components/MkLink.vue
index 7589c4900b..309ef727da 100644
--- a/packages/frontend/src/components/MkLink.vue
+++ b/packages/frontend/src/components/MkLink.vue
@@ -19,7 +19,7 @@ import { defineAsyncComponent, ref } from 'vue';
import { url as local } from '@@/js/config.js';
import { useTooltip } from '@/composables/use-tooltip.js';
import * as os from '@/os.js';
-import { isEnabledUrlPreview } from '@/instance.js';
+import { isEnabledUrlPreview } from '@/utility/url-preview.js';
import type { MkABehavior } from '@/components/global/MkA.vue';
import { maybeMakeRelative } from '@@/js/url.js';
diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 7d3986a036..ee8a470b0e 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -234,7 +234,7 @@ import { claimAchievement } from '@/utility/achievements.js';
import { getNoteSummary } from '@/utility/get-note-summary.js';
import MkRippleEffect from '@/components/MkRippleEffect.vue';
import { showMovedDialog } from '@/utility/show-moved-dialog.js';
-import { isEnabledUrlPreview } from '@/instance.js';
+import { isEnabledUrlPreview } from '@/utility/url-preview.js';
import { focusPrev, focusNext } from '@/utility/focus.js';
import { getAppearNote } from '@/utility/get-appear-note.js';
import { prefer } from '@/preferences.js';
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index ea59254f3d..767f4c88ce 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -268,7 +268,7 @@ import MkUserCardMini from '@/components/MkUserCardMini.vue';
import MkPagination from '@/components/MkPagination.vue';
import MkReactionIcon from '@/components/MkReactionIcon.vue';
import MkButton from '@/components/MkButton.vue';
-import { isEnabledUrlPreview } from '@/instance.js';
+import { isEnabledUrlPreview } from '@/utility/url-preview.js';
import { getAppearNote } from '@/utility/get-appear-note.js';
import { prefer } from '@/preferences.js';
import { getPluginHandlers } from '@/plugin.js';
diff --git a/packages/frontend/src/components/MkUrlPreview.vue b/packages/frontend/src/components/MkUrlPreview.vue
index 71c8a6a6e8..7c0c06398b 100644
--- a/packages/frontend/src/components/MkUrlPreview.vue
+++ b/packages/frontend/src/components/MkUrlPreview.vue
@@ -45,7 +45,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
+
@@ -91,7 +91,7 @@ import { i18n } from '@/i18n.js';
import * as os from '@/os.js';
import { deviceKind } from '@/utility/device-kind.js';
import MkButton from '@/components/MkButton.vue';
-import { transformPlayerUrl } from '@/utility/player-url-transform.js';
+import { transformPlayerUrl } from '@/utility/url-preview.js';
import { store } from '@/store.js';
import { prefer } from '@/preferences.js';
import { maybeMakeRelative } from '@@/js/url.js';
diff --git a/packages/frontend/src/components/MkYouTubePlayer.vue b/packages/frontend/src/components/MkYouTubePlayer.vue
index ab62a5113d..2375bcc9eb 100644
--- a/packages/frontend/src/components/MkYouTubePlayer.vue
+++ b/packages/frontend/src/components/MkYouTubePlayer.vue
@@ -27,7 +27,7 @@ SPDX-License-Identifier: AGPL-3.0-only
import { ref } from 'vue';
import { versatileLang } from '@@/js/intl-const.js';
import MkWindow from '@/components/MkWindow.vue';
-import { transformPlayerUrl } from '@/utility/player-url-transform.js';
+import { transformPlayerUrl } from '@/utility/url-preview.js';
import { prefer } from '@/preferences.js';
const props = defineProps<{
diff --git a/packages/frontend/src/components/global/MkUrl.vue b/packages/frontend/src/components/global/MkUrl.vue
index 2478b59f00..1da16b8923 100644
--- a/packages/frontend/src/components/global/MkUrl.vue
+++ b/packages/frontend/src/components/global/MkUrl.vue
@@ -30,7 +30,7 @@ import { toUnicode as decodePunycode } from 'punycode.js';
import { url as local } from '@@/js/config.js';
import * as os from '@/os.js';
import { useTooltip } from '@/composables/use-tooltip.js';
-import { isEnabledUrlPreview } from '@/instance.js';
+import { isEnabledUrlPreview } from '@/utility/url-preview.js';
import type { MkABehavior } from '@/components/global/MkA.vue';
import { maybeMakeRelative } from '@@/js/url.js';
diff --git a/packages/frontend/src/components/page/page.text.vue b/packages/frontend/src/components/page/page.text.vue
index 7702e250e4..a00eb0b5ca 100644
--- a/packages/frontend/src/components/page/page.text.vue
+++ b/packages/frontend/src/components/page/page.text.vue
@@ -17,7 +17,7 @@ import { defineAsyncComponent } from 'vue';
import * as mfm from 'mfm-js';
import * as Misskey from 'misskey-js';
import { extractUrlFromMfm } from '@/utility/extract-url-from-mfm.js';
-import { isEnabledUrlPreview } from '@/instance.js';
+import { isEnabledUrlPreview } from '@/utility/url-preview.js';
const MkUrlPreview = defineAsyncComponent(() => import('@/components/MkUrlPreview.vue'));
diff --git a/packages/frontend/src/instance.ts b/packages/frontend/src/instance.ts
index 2943e60e43..a5397f0c0d 100644
--- a/packages/frontend/src/instance.ts
+++ b/packages/frontend/src/instance.ts
@@ -29,8 +29,6 @@ if (providedAt > cachedAt) {
export const instance: Misskey.entities.MetaDetailed = reactive(cachedMeta ?? {});
-export const isEnabledUrlPreview = computed(() => instance.enableUrlPreview ?? true);
-
export async function fetchInstance(force = false): Promise {
if (!force) {
const cachedAt = miLocalStorage.getItem('instanceCachedAt') ? parseInt(miLocalStorage.getItem('instanceCachedAt')!) : 0;
diff --git a/packages/frontend/src/pages/settings/preferences.vue b/packages/frontend/src/pages/settings/preferences.vue
index 8a8774fcd0..18dfc2250c 100644
--- a/packages/frontend/src/pages/settings/preferences.vue
+++ b/packages/frontend/src/pages/settings/preferences.vue
@@ -644,9 +644,13 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts._dataSaver._avatar.title }}
{{ i18n.ts._dataSaver._avatar.description }}
-
- {{ i18n.ts._dataSaver._urlPreview.title }}
- {{ i18n.ts._dataSaver._urlPreview.description }}
+
+ {{ i18n.ts._dataSaver._disableUrlPreview.title }}
+ {{ i18n.ts._dataSaver._disableUrlPreview.description }}
+
+
+ {{ i18n.ts._dataSaver._urlPreviewThumbnail.title }}
+ {{ i18n.ts._dataSaver._urlPreviewThumbnail.description }}
{{ i18n.ts._dataSaver._code.title }}
diff --git a/packages/frontend/src/preferences/def.ts b/packages/frontend/src/preferences/def.ts
index b3af8cab87..7b0628e937 100644
--- a/packages/frontend/src/preferences/def.ts
+++ b/packages/frontend/src/preferences/def.ts
@@ -290,9 +290,10 @@ export const PREF_DEF = {
default: {
media: false,
avatar: false,
- urlPreview: false,
+ urlPreviewThumbnail: false,
+ disableUrlPreview: false,
code: false,
- } as Record,
+ } satisfies Record,
},
hemisphere: {
default: hemisphere as 'N' | 'S',
diff --git a/packages/frontend/src/utility/player-url-transform.ts b/packages/frontend/src/utility/player-url-transform.ts
deleted file mode 100644
index 39c6df6500..0000000000
--- a/packages/frontend/src/utility/player-url-transform.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * SPDX-FileCopyrightText: syuilo and misskey-project
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-import { hostname } from '@@/js/config.js';
-
-export function transformPlayerUrl(url: string): string {
- const urlObj = new URL(url);
- if (!['https:', 'http:'].includes(urlObj.protocol)) throw new Error('Invalid protocol');
-
- const urlParams = new URLSearchParams(urlObj.search);
-
- if (urlObj.hostname === 'player.twitch.tv') {
- // TwitchはCSPの制約あり
- // https://dev.twitch.tv/docs/embed/video-and-clips/
- urlParams.set('parent', hostname);
- urlParams.set('allowfullscreen', '');
- urlParams.set('autoplay', 'true');
- } else {
- urlParams.set('autoplay', '1');
- urlParams.set('auto_play', '1');
- }
- urlObj.search = urlParams.toString();
-
- return urlObj.toString();
-}
diff --git a/packages/frontend/src/utility/url-preview.ts b/packages/frontend/src/utility/url-preview.ts
new file mode 100644
index 0000000000..e7379f4202
--- /dev/null
+++ b/packages/frontend/src/utility/url-preview.ts
@@ -0,0 +1,31 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+import { computed } from 'vue';
+import { hostname } from '@@/js/config.js';
+import { instance } from '@/instance.js';
+import { prefer } from '@/preferences.js';
+
+export const isEnabledUrlPreview = computed(() => (instance.enableUrlPreview && !prefer.r.dataSaver.value.disableUrlPreview));
+
+export function transformPlayerUrl(url: string): string {
+ const urlObj = new URL(url);
+ if (!['https:', 'http:'].includes(urlObj.protocol)) throw new Error('Invalid protocol');
+
+ const urlParams = new URLSearchParams(urlObj.search);
+
+ if (urlObj.hostname === 'player.twitch.tv') {
+ // TwitchはCSPの制約あり
+ // https://dev.twitch.tv/docs/embed/video-and-clips/
+ urlParams.set('parent', hostname);
+ urlParams.set('allowfullscreen', '');
+ urlParams.set('autoplay', 'true');
+ } else {
+ urlParams.set('autoplay', '1');
+ urlParams.set('auto_play', '1');
+ }
+ urlObj.search = urlParams.toString();
+
+ return urlObj.toString();
+}
--
cgit v1.2.3-freya