diff --git a/locales/index.d.ts b/locales/index.d.ts
index 880ee4bf56..4d86c69384 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -12525,6 +12525,14 @@ export interface Locale extends ILocale {
* Failed to load note
*/
"cannotLoadNote": string;
+ /**
+ * Please click [OK] to unsubscribe from announcement e-mails.
+ */
+ "clickToUnsubscribe": string;
+ /**
+ * There was a problem unsubscribing.
+ */
+ "unsubscribeError": string;
"_flash": {
/**
* Flash Content Hidden
diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue
index 357744da9c..43efa5bc11 100644
--- a/packages/frontend/src/components/SkNoteDetailed.vue
+++ b/packages/frontend/src/components/SkNoteDetailed.vue
@@ -79,7 +79,7 @@ Detailed view of a note in the Sharkey style. Used when opening a note onto its
-
+
@@ -290,6 +290,7 @@ import SkNoteTranslation from '@/components/SkNoteTranslation.vue';
import { getSelfNoteIds } from '@/utility/get-self-note-ids.js';
import SkUrlPreviewGroup from '@/components/SkUrlPreviewGroup.vue';
import MkNoteSub from '@/components/MkNoteSub.vue';
+import { showOnRemote } from '@/utility/show-on-remote.js';
const props = withDefaults(defineProps<{
note: Misskey.entities.Note;
diff --git a/packages/frontend/src/components/SkNoteHeader.vue b/packages/frontend/src/components/SkNoteHeader.vue
index c9c3b5de08..6cf03ed473 100644
--- a/packages/frontend/src/components/SkNoteHeader.vue
+++ b/packages/frontend/src/components/SkNoteHeader.vue
@@ -40,7 +40,7 @@ Header for a note in the Sharkey style, displaying info such as username and cre
@@ -89,6 +89,7 @@ import { prefer } from '@/preferences';
import { useRouter } from '@/router';
import { deviceKind } from '@/utility/device-kind';
import SkInstanceTicker from '@/components/SkInstanceTicker.vue';
+import { showOnRemote } from '@/utility/show-on-remote.js';
const props = defineProps<{
note: Misskey.entities.Note;
@@ -107,11 +108,6 @@ async function menuVersions(): Promise {
popupMenu(menu, menuVersionsButton.value).then(focus).finally(cleanup);
}
-function showOnRemote() {
- if (props.note.url ?? props.note.uri === undefined) router.push(notePage(props.note));
- else window.open(props.note.url ?? props.note.uri);
-}
-
const mock = inject(DI.mock, false);
diff --git a/packages/frontend/src/utility/get-note-menu.ts b/packages/frontend/src/utility/get-note-menu.ts
index 1698124623..9e699bb139 100644
--- a/packages/frontend/src/utility/get-note-menu.ts
+++ b/packages/frontend/src/utility/get-note-menu.ts
@@ -25,6 +25,7 @@ import { getAppearNote } from '@/utility/get-appear-note.js';
import { genEmbedCode } from '@/utility/get-embed-code.js';
import { prefer } from '@/preferences.js';
import { getPluginHandlers } from '@/plugin.js';
+import { showOnRemote } from '@/utility/show-on-remote.js';
export async function getNoteClipMenu(props: {
note: Misskey.entities.Note;
@@ -359,7 +360,7 @@ export function getNoteMenu(props: {
icon: 'ti ti-external-link',
text: i18n.ts.showOnRemote,
action: () => {
- window.open(appearNote.url ?? appearNote.uri, '_blank', 'noopener');
+ showOnRemote(appearNote);
},
});
} else {
@@ -548,7 +549,7 @@ export function getNoteMenu(props: {
icon: 'ti ti-external-link',
text: i18n.ts.showOnRemote,
action: () => {
- window.open(appearNote.url ?? appearNote.uri, '_blank', 'noopener');
+ showOnRemote(appearNote);
},
});
} else {
diff --git a/packages/frontend/src/utility/get-user-menu.ts b/packages/frontend/src/utility/get-user-menu.ts
index 1bad4b9d01..5003ddd7ae 100644
--- a/packages/frontend/src/utility/get-user-menu.ts
+++ b/packages/frontend/src/utility/get-user-menu.ts
@@ -20,6 +20,7 @@ import { mainRouter } from '@/router.js';
import { genEmbedCode } from '@/utility/get-embed-code.js';
import { prefer } from '@/preferences.js';
import { getPluginHandlers } from '@/plugin.js';
+import { warningExternalWebsite } from '@/utility/warning-external-website.js';
export function getUserMenu(user: Misskey.entities.UserDetailed, router: Router = mainRouter) {
const meId = $i ? $i.id : null;
@@ -211,7 +212,7 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: Router
text: i18n.ts.showOnRemote,
action: () => {
if (user.url == null) return;
- window.open(user.url, '_blank', 'noopener');
+ warningExternalWebsite(user.url);
},
});
} else {
diff --git a/packages/frontend/src/utility/show-on-remote.ts b/packages/frontend/src/utility/show-on-remote.ts
new file mode 100644
index 0000000000..121866af3a
--- /dev/null
+++ b/packages/frontend/src/utility/show-on-remote.ts
@@ -0,0 +1,23 @@
+/*
+ * SPDX-FileCopyrightText: bunnybeam and other Sharkey contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { entities } from 'misskey-js';
+import { warningExternalWebsite } from './warning-external-website';
+import { useRouter } from '@/router';
+import { notePage } from '@/filters/note.js';
+
+const router = useRouter();
+
+/**
+ * Show a note on the remote instance, if possible. Otherwise, show the local note.
+ */
+export function showOnRemote(note: entities.Note) {
+ const remoteUrl = note.url ?? note.uri;
+ if (remoteUrl) {
+ warningExternalWebsite(remoteUrl);
+ } else {
+ router.push(notePage(note));
+ }
+}