summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components
diff options
context:
space:
mode:
authorMarie <github@yuugi.dev>2024-10-04 02:31:22 +0200
committerMarie <github@yuugi.dev>2024-10-04 02:31:22 +0200
commitd5b372f7a92e3892addb306fc6b62b169e2bfc41 (patch)
treeb17986d43be7213a56cefa8ccd7db05f472311c7 /packages/frontend/src/components
parentmerge: Feat: Implement "Show Below Avatar" for Avatar Decorations (!645) (diff)
downloadsharkey-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.vue14
-rw-r--r--packages/frontend/src/components/MkUrlWarningDialog.vue131
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>