diff options
| author | Marie <github@yuugi.dev> | 2024-10-04 02:31:22 +0200 |
|---|---|---|
| committer | Marie <github@yuugi.dev> | 2024-10-04 02:31:22 +0200 |
| commit | d5b372f7a92e3892addb306fc6b62b169e2bfc41 (patch) | |
| tree | b17986d43be7213a56cefa8ccd7db05f472311c7 /packages/frontend/src/components | |
| parent | merge: Feat: Implement "Show Below Avatar" for Avatar Decorations (!645) (diff) | |
| download | sharkey-d5b372f7a92e3892addb306fc6b62b169e2bfc41.tar.gz sharkey-d5b372f7a92e3892addb306fc6b62b169e2bfc41.tar.bz2 sharkey-d5b372f7a92e3892addb306fc6b62b169e2bfc41.zip | |
upd&merge: Merge Cherrypick/MisskeyIO's external url popup, delete old popup warning and modify script to handle undefined domains
Diffstat (limited to 'packages/frontend/src/components')
| -rw-r--r-- | packages/frontend/src/components/MkLink.vue | 14 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkUrlWarningDialog.vue | 131 |
2 files changed, 133 insertions, 12 deletions
diff --git a/packages/frontend/src/components/MkLink.vue b/packages/frontend/src/components/MkLink.vue index d2819f9f4c..b04edd1150 100644 --- a/packages/frontend/src/components/MkLink.vue +++ b/packages/frontend/src/components/MkLink.vue @@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only :is="self ? 'MkA' : 'a'" ref="el" style="word-break: break-all;" class="_link" :[attr]="self ? url.substring(local.length) : url" :rel="rel ?? 'nofollow noopener'" :target="target" :behavior="props.navigationBehavior" :title="url" - @click.prevent="self ? true : promptConfirm()" + @click.prevent="self ? true : warningExternalWebsite(url)" @click.stop > <slot></slot> @@ -23,7 +23,7 @@ import { useTooltip } from '@/scripts/use-tooltip.js'; import * as os from '@/os.js'; import { isEnabledUrlPreview } from '@/instance.js'; import { MkABehavior } from '@/components/global/MkA.vue'; -import { i18n } from '@/i18n.js'; +import { warningExternalWebsite } from '@/scripts/warning-external-website.js'; const props = withDefaults(defineProps<{ url: string; @@ -49,16 +49,6 @@ if (isEnabledUrlPreview.value) { }); }); } - -async function promptConfirm() { - const { canceled } = await os.confirm({ - type: 'question', - text: i18n.tsx.confirmRemoteUrl({ x: props.url }), - plain: true, - }); - if (canceled) return; - window.open(props.url, '_blank', 'nofollow noopener popup=false'); -} </script> <style lang="scss" module> diff --git a/packages/frontend/src/components/MkUrlWarningDialog.vue b/packages/frontend/src/components/MkUrlWarningDialog.vue new file mode 100644 index 0000000000..5a37a36ee5 --- /dev/null +++ b/packages/frontend/src/components/MkUrlWarningDialog.vue @@ -0,0 +1,131 @@ +<!-- +SPDX-FileCopyrightText: syuilo and misskey-project +SPDX-License-Identifier: AGPL-3.0-only +--> + +<template> +<MkModal ref="modal" :preferType="'dialog'" :zPriority="'high'" @click="done(true)" @closed="emit('closed')"> + <div :class="$style.root" class="_gaps"> + <div class="_gaps_s"> + <div :class="$style.header"> + <div :class="$style.icon"> + <i class="ti ti-alert-triangle"></i> + </div> + <div :class="$style.title">{{ i18n.ts._externalNavigationWarning.title }}</div> + </div> + <div><Mfm :text="i18n.tsx._externalNavigationWarning.description({ host: instanceName })"/></div> + <div class="_monospace" :class="$style.urlAddress">{{ url }}</div> + <div> + <MkSwitch v-model="trustThisDomain">{{ i18n.ts._externalNavigationWarning.trustThisDomain }}</MkSwitch> + </div> + </div> + <div :class="$style.buttons"> + <MkButton data-cy-modal-dialog-cancel inline rounded @click="cancel">{{ i18n.ts.cancel }}</MkButton> + <MkButton data-cy-modal-dialog-ok inline primary rounded @click="ok"><i class="ti ti-external-link"></i> {{ i18n.ts.open }}</MkButton> + </div> + </div> +</MkModal> +</template> + +<script lang="ts" setup> +import { onBeforeUnmount, onMounted, ref, shallowRef, computed } from 'vue'; +import { instanceName } from '@/config.js'; +import MkModal from '@/components/MkModal.vue'; +import MkButton from '@/components/MkButton.vue'; +import MkSwitch from '@/components/MkSwitch.vue'; +import { i18n } from '@/i18n.js'; +import { defaultStore } from '@/store.js'; + +type Result = string | number | true | null; + +const props = defineProps<{ + url: string; +}>(); + +const emit = defineEmits<{ + (ev: 'done', v: { canceled: true } | { canceled: false, result: Result }): void; + (ev: 'closed'): void; +}>(); + +const modal = shallowRef<InstanceType<typeof MkModal>>(); +const trustThisDomain = ref(false); + +const domain = computed(() => new URL(props.url).hostname); + +// overload function を使いたいので lint エラーを無視する +function done(canceled: true): void; +function done(canceled: false, result: Result): void; // eslint-disable-line no-redeclare +function done(canceled: boolean, result?: Result): void { // eslint-disable-line no-redeclare + emit('done', { canceled, result } as { canceled: true } | { canceled: false, result: Result }); + modal.value?.close(); +} + +async function ok() { + const result = true; + if (!defaultStore.state.trustedDomains.includes(domain.value) && trustThisDomain.value) { + await defaultStore.set('trustedDomains', defaultStore.state.trustedDomains.concat(domain.value)); + } + done(false, result); +} + +function cancel() { + done(true); +} + +function onKeydown(evt: KeyboardEvent) { + if (evt.key === 'Escape') cancel(); +} + +onMounted(() => { + document.addEventListener('keydown', onKeydown); +}); + +onBeforeUnmount(() => { + document.removeEventListener('keydown', onKeydown); +}); +</script> + +<style lang="scss" module> +.root { + position: relative; + margin: auto; + padding: 32px; + width: 100%; + min-width: 320px; + max-width: 480px; + box-sizing: border-box; + background: var(--panel); + border-radius: 16px; +} + +.header { + display: flex; + align-items: center; + gap: 0.75em; +} + +.icon { + font-size: 18px; + color: var(--warn); +} + +.title { + font-weight: bold; + font-size: 1.1em; +} + +.urlAddress { + padding: 10px 14px; + border-radius: 8px; + border: 1px solid var(--divider); + overflow-x: auto; + white-space: nowrap; +} + +.buttons { + display: flex; + gap: 8px; + flex-wrap: wrap; + justify-content: right; +} +</style> |