diff --git a/CHANGELOG_CHERRYPICK.md b/CHANGELOG_CHERRYPICK.md index 91afc93186..7b5dbc942c 100644 --- a/CHANGELOG_CHERRYPICK.md +++ b/CHANGELOG_CHERRYPICK.md @@ -20,7 +20,7 @@ Misskey의 전체 변경 사항을 확인하려면, [CHANGELOG.md#2024xx](CHANGE --> -# 릴리즈 노트 +# 릴리스 노트 이 문서는 CherryPick의 변경 사항만 포함합니다. ## 4.x.x @@ -32,6 +32,9 @@ Misskey의 전체 변경 사항을 확인하려면, [CHANGELOG.md#2024xx](CHANGE - Enhance: 미디어 그리드 레이아옷 조정 - 여러 장의 이미지가 있을 때 표시되는 아이콘을 보다 명확하게 볼 수 있도록 개선됨 - 배경과 같은 이미지를 구분하기 쉽도록 배경색 및 구분선 추가 +- Enhance: 외부 사이트 이동 경고 표시 개선 (kokonect-link/cherrypick#533) + - 신뢰할 수 있는 도메인 목록을 편집할 수 있음 + - 경고를 표시하지 않도록 설정할 수 있음 - Fix: 아바타 장식에서 가이드라인이 표시되지 않음 - Fix: 설정 페이지에서 글자수가 긴 일부 항목의 디자인이 잘못 표시될 수 있음 - Fix: 서브 노트의 동작 버튼이 정상적으로 작동하지 않을 수 있음 (kokonect-link/cherrypick#536) diff --git a/locales/en-US.yml b/locales/en-US.yml index a57846e01c..bd6b32c9ad 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -3126,6 +3126,12 @@ _externalNavigationWarning: title: "Navigate to an external site" description: "Leave {host} and go to an external site" trustThisDomain: "Trust this domain on this device in the future" + externalNavigationWarning: "Navigate to an external site warning" + enableExternalNavigationWarning: "Display warning when navigate to an external site" + trustedDomainList: "Trusted domain list" + trustedDomainListDescription: "Please input omitting `http://` and `https://`." + trustedDomainListDescription2: "Separate with newlines" + deleteTrustedDomainList: "Reset trusted domain list" _altWarning: noAltWarning: "No alternate text is configured in the file." noAltWarningDescription: "You can change this setting in \"Settings - Appearance\"." diff --git a/locales/index.d.ts b/locales/index.d.ts index 1a75af0de0..03fcdd5044 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -12146,6 +12146,30 @@ export interface Locale extends ILocale { * このデバイスで今後このドメインを信頼する */ "trustThisDomain": string; + /** + * 外部サイトに移動する際の警告 + */ + "externalNavigationWarning": string; + /** + * 外部サイトに移動する際の警告を表示 + */ + "enableExternalNavigationWarning": string; + /** + * 信頼するドメインリスト + */ + "trustedDomainList": string; + /** + * `http://`と`https://`を省略して入力してください。 + */ + "trustedDomainListDescription": string; + /** + * 改行で区切って設定します + */ + "trustedDomainListDescription2": string; + /** + * 信頼するドメインリストのリセット + */ + "deleteTrustedDomainList": string; }; "_altWarning": { /** diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index ea3c7d8759..eda0ed56c1 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -3230,6 +3230,12 @@ _externalNavigationWarning: title: "外部サイトに移動します" description: "{host}を離れて外部サイトに移動します" trustThisDomain: "このデバイスで今後このドメインを信頼する" + externalNavigationWarning: "外部サイトに移動する際の警告" + enableExternalNavigationWarning: "外部サイトに移動する際の警告を表示" + trustedDomainList: "信頼するドメインリスト" + trustedDomainListDescription: "`http://`と`https://`を省略して入力してください。" + trustedDomainListDescription2: "改行で区切って設定します" + deleteTrustedDomainList: "信頼するドメインリストのリセット" _altWarning: noAltWarning: "ファイルに代替テキストが設定されていません。" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index d312dec186..088158b542 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -3107,6 +3107,12 @@ _externalNavigationWarning: title: "외부 사이트로 이동할까요?" description: "{host}을(를) 떠나 외부 사이트로 이동하려고 해요" trustThisDomain: "이 장치에서 앞으로 이 도메인을 신뢰할게요" + externalNavigationWarning: "외부 사이트 이동 경고" + enableExternalNavigationWarning: "외부 사이트 이동 시 경고 표시" + trustedDomainList: "신뢰하는 도메인 목록" + trustedDomainListDescription: "`http://`와 `https://`를 생략하고 입력해 주세요." + trustedDomainListDescription2: "한 줄에 하나씩 입력해 주세요" + deleteTrustedDomainList: "신뢰하는 도메인 목록 재설정" _altWarning: noAltWarning: "파일에 캡션이 설정되어 있지 않아요." noAltWarningDescription: "이 설정은 [설정 - 모양]에서 변경할 수 있어요." diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue index 4a69cfce8f..e041ce1f09 100644 --- a/packages/frontend/src/pages/settings/general.vue +++ b/packages/frontend/src/pages/settings/general.vue @@ -119,6 +119,26 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + +
+
+ + {{ i18n.ts._externalNavigationWarning.enableExternalNavigationWarning }} + + + + + +
+ {{ i18n.ts.save }} + {{ i18n.ts._externalNavigationWarning.deleteTrustedDomainList }} +
+
+
+
@@ -161,6 +181,7 @@ import FormSection from '@/components/form/section.vue'; import FormLink from '@/components/form/link.vue'; import MkLink from '@/components/MkLink.vue'; import MkInfo from '@/components/MkInfo.vue'; +import MkTextarea from '@/components/MkTextarea.vue'; import { defaultStore } from '@/store.js'; import * as os from '@/os.js'; import { misskeyApi } from '@/scripts/misskey-api.js'; @@ -173,6 +194,7 @@ import { $i } from '@/account.js'; const lang = ref(miLocalStorage.getItem('lang')); const dataSaver = ref(defaultStore.state.dataSaver); +const trustedDomains = ref(defaultStore.state.trustedDomains.join('\n')); function reloadTimeline() { globalEvents.emit('reloadTimeline'); @@ -200,6 +222,7 @@ const autoLoadMoreConversation = computed(defaultStore.makeGetterSetter('autoLoa const useAutoTranslate = computed(defaultStore.makeGetterSetter('useAutoTranslate')); const welcomeBackToast = computed(defaultStore.makeGetterSetter('welcomeBackToast')); const disableNyaize = computed(defaultStore.makeGetterSetter('disableNyaize')); +const externalNavigationWarning = computed(defaultStore.makeGetterSetter('externalNavigationWarning')); watch(lang, () => { miLocalStorage.setItem('lang', lang.value as string); @@ -321,12 +344,47 @@ function learnMoreCantUseAutoTranslate() { }); } +function removeTrustedDomains() { + async function main() { + await defaultStore.set('trustedDomains', []); + + // Refresh filtered list to signal to the user how they've been saved + trustedDomains.value = ''; + } + + os.promiseDialog(main()); +} + +const trustedDomainsChanged = ref(false); + +async function trustedDomainsSave() { + async function main() { + let domains = trustedDomains.value + .trim().split('\n') + .map(el => el.trim()) + .filter(el => el); + + await defaultStore.set('trustedDomains', domains); + + trustedDomainsChanged.value = false; + + // Refresh filtered list to signal to the user how they've been saved + trustedDomains.value = domains.join('\n'); + } + + await os.promiseDialog(main()); +} + watch(dataSaver, (to) => { defaultStore.set('dataSaver', to); }, { deep: true, }); +watch(trustedDomains, () => { + trustedDomainsChanged.value = true; +}); + const headerActions = computed(() => []); const headerTabs = computed(() => []); diff --git a/packages/frontend/src/scripts/warning-external-website.ts b/packages/frontend/src/scripts/warning-external-website.ts index 82da143be0..80bafc430e 100644 --- a/packages/frontend/src/scripts/warning-external-website.ts +++ b/packages/frontend/src/scripts/warning-external-website.ts @@ -24,7 +24,7 @@ export async function warningExternalWebsite(ev: MouseEvent, url: string) { }); const isTrustedByUser = defaultStore.reactiveState.trustedDomains.value.includes(domain); - if (!self && !isTrustedByInstance && !isTrustedByUser) { + if (!self && !isTrustedByInstance && !isTrustedByUser && defaultStore.state.externalNavigationWarning) { ev.preventDefault(); ev.stopPropagation(); diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index a77b139acb..4ad64d2f5e 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -498,6 +498,10 @@ export const defaultStore = markRaw(new Storage('base', { where: 'deviceAccount', default: false, }, + externalNavigationWarning: { + where: 'device', + default: true, + }, trustedDomains: { where: 'device', default: [] as string[],