diff --git a/locales/index.d.ts b/locales/index.d.ts index 84a402b0de..694ee53a1f 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -5004,7 +5004,7 @@ export interface Locale extends ILocale { * お問い合わせ */ "inquiry": string; - /** + /** * もう一度お試しください。 */ "tryAgain": string; diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index c518c7dd41..13273a53b4 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -174,7 +174,7 @@ import MkPoll from '@/components/MkPoll.vue'; import MkUsersTooltip from '@/components/MkUsersTooltip.vue'; import MkUrlPreview from '@/components/MkUrlPreview.vue'; import MkInstanceTicker from '@/components/MkInstanceTicker.vue'; -import { pleaseLogin } from '@/scripts/please-login.js'; +import { pleaseLogin, type OpenOnRemoteOptions } from '@/scripts/please-login.js'; import { checkWordMute } from '@/scripts/check-word-mute.js'; import { userPage } from '@/filters/user.js'; import number from '@/filters/number.js'; @@ -279,10 +279,10 @@ const renoteCollapsed = ref( ), ); -const pleaseLoginContext = { +const pleaseLoginContext = computed(() => ({ type: 'lookup', - path: `https://${host}/notes/${appearNote.value.id}`, -} as const; + url: `https://${host}/notes/${appearNote.value.id}`, +})); /* Overload FunctionにLintが対応していないのでコメントアウト function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array | undefined | null, checkOnly: true): boolean; @@ -417,7 +417,7 @@ if (!props.mock) { } function renote(viaKeyboard = false) { - pleaseLogin(undefined, pleaseLoginContext); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); const { menu } = getRenoteMenu({ note: note.value, renoteButton, mock: props.mock }); @@ -427,7 +427,7 @@ function renote(viaKeyboard = false) { } function reply(): void { - pleaseLogin(undefined, pleaseLoginContext); + pleaseLogin(undefined, pleaseLoginContext.value); if (props.mock) { return; } @@ -440,7 +440,7 @@ function reply(): void { } function react(): void { - pleaseLogin(undefined, pleaseLoginContext); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); if (appearNote.value.reactionAcceptance === 'likeOnly') { sound.playMisskeySfx('reaction'); @@ -571,7 +571,7 @@ function showRenoteMenu(): void { } if (isMyRenote) { - pleaseLogin(undefined, pleaseLoginContext); + pleaseLogin(undefined, pleaseLoginContext.value); os.popupMenu([ getCopyNoteLinkMenu(note.value, i18n.ts.copyLinkRenote), { type: 'divider' }, diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index 737e9a853a..9a3e595789 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -209,7 +209,7 @@ import MkPoll from '@/components/MkPoll.vue'; import MkUsersTooltip from '@/components/MkUsersTooltip.vue'; import MkUrlPreview from '@/components/MkUrlPreview.vue'; import MkInstanceTicker from '@/components/MkInstanceTicker.vue'; -import { pleaseLogin } from '@/scripts/please-login.js'; +import { pleaseLogin, type OpenOnRemoteOptions } from '@/scripts/please-login.js'; import { checkWordMute } from '@/scripts/check-word-mute.js'; import { userPage } from '@/filters/user.js'; import { notePage } from '@/filters/note.js'; @@ -297,10 +297,10 @@ const conversation = ref([]); const replies = ref([]); const canRenote = computed(() => ['public', 'home'].includes(appearNote.value.visibility) || appearNote.value.userId === $i?.id); -const pleaseLoginContext = { +const pleaseLoginContext = computed(() => ({ type: 'lookup', - path: `https://${host}/notes/${appearNote.value.id}`, -} as const; + url: `https://${host}/notes/${appearNote.value.id}`, +})); const keymap = { 'r': () => reply(), @@ -402,7 +402,7 @@ if (appearNote.value.reactionAcceptance === 'likeOnly') { } function renote() { - pleaseLogin(undefined, pleaseLoginContext); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); const { menu } = getRenoteMenu({ note: note.value, renoteButton }); @@ -410,7 +410,7 @@ function renote() { } function reply(): void { - pleaseLogin(undefined, pleaseLoginContext); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); os.post({ reply: appearNote.value, @@ -421,7 +421,7 @@ function reply(): void { } function react(): void { - pleaseLogin(undefined, pleaseLoginContext); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); if (appearNote.value.reactionAcceptance === 'likeOnly') { sound.playMisskeySfx('reaction'); @@ -505,7 +505,7 @@ async function clip(): Promise { function showRenoteMenu(): void { if (!isMyRenote) return; - pleaseLogin(undefined, pleaseLoginContext); + pleaseLogin(undefined, pleaseLoginContext.value); os.popupMenu([{ text: i18n.ts.unrenote, icon: 'ti ti-trash', diff --git a/packages/frontend/src/components/MkPoll.vue b/packages/frontend/src/components/MkPoll.vue index 82e2a605f1..72bd8f4f6c 100644 --- a/packages/frontend/src/components/MkPoll.vue +++ b/packages/frontend/src/components/MkPoll.vue @@ -36,6 +36,7 @@ import { misskeyApi } from '@/scripts/misskey-api.js'; import { i18n } from '@/i18n.js'; import { host } from '@/config.js'; import { useInterval } from '@/scripts/use-interval.js'; +import type { OpenOnRemoteOptions } from '@/scripts/please-login.js'; const props = defineProps<{ noteId: string; @@ -61,10 +62,10 @@ const timer = computed(() => i18n.tsx._poll[ const showResult = ref(props.readOnly || isVoted.value); -const pleaseLoginContext = { +const pleaseLoginContext = computed(() => ({ type: 'lookup', - path: `https://${host}/notes/${props.note.id}`, -} as const; + url: `https://${host}/notes/${props.noteId}`, +})); // 期限付きアンケート if (props.poll.expiresAt) { @@ -82,7 +83,7 @@ if (props.poll.expiresAt) { } const vote = async (id) => { - pleaseLogin(undefined, pleaseLoginContext); + pleaseLogin(undefined, pleaseLoginContext.value); if (props.readOnly || closed.value || isVoted.value) return; diff --git a/packages/frontend/src/components/MkSignin.vue b/packages/frontend/src/components/MkSignin.vue index 746ddd7154..a123bbddc6 100644 --- a/packages/frontend/src/components/MkSignin.vue +++ b/packages/frontend/src/components/MkSignin.vue @@ -236,12 +236,14 @@ function openRemote(options: OpenOnRemoteOptions, targetHost?: string): void { switch (options.type) { case 'web': case 'lookup': { - let _path = options.path; + let _path: string; if (options.type === 'lookup') { - // TODO: v2024.2.0以降が浸透してきたら正式なURLに変更する▼ + // TODO: v2024.7.0以降が浸透してきたら正式なURLに変更する▼ // _path = `/lookup?uri=${encodeURIComponent(_path)}`; - _path = `/authorize-follow?acct=${encodeURIComponent(_path)}`; + _path = `/authorize-follow?acct=${encodeURIComponent(options.url)}`; + } else { + _path = options.path; } if (targetHost) { @@ -252,7 +254,7 @@ function openRemote(options: OpenOnRemoteOptions, targetHost?: string): void { break; } case 'share': { - const params = query(options.params); + const params = query(options.params); if (targetHost) { window.open(`https://${targetHost}/share?${params}`, '_blank', 'noopener'); } else { diff --git a/packages/frontend/src/scripts/please-login.ts b/packages/frontend/src/scripts/please-login.ts index b04062a58a..18f05bc7f4 100644 --- a/packages/frontend/src/scripts/please-login.ts +++ b/packages/frontend/src/scripts/please-login.ts @@ -9,13 +9,38 @@ import { i18n } from '@/i18n.js'; import { popup } from '@/os.js'; export type OpenOnRemoteOptions = { + /** + * 外部のMisskey Webで特定のパスを開く + */ type: 'web'; + + /** + * 内部パス(例: `/settings`) + */ path: string; } | { + /** + * 外部のMisskey Webで照会する + */ type: 'lookup'; - path: string; + + /** + * 照会したいエンティティのURL + * + * (例: `https://misskey.example.com/notes/abcdexxxxyz`) + */ + url: string; } | { + /** + * 外部のMisskeyでノートする + */ type: 'share'; + + /** + * `/share` ページに渡すクエリストリング + * + * @see https://go.misskey-hub.net/spec/share/ + */ params: Record; }; diff --git a/packages/frontend/src/scripts/url.ts b/packages/frontend/src/scripts/url.ts index c477fb5506..5a8265af9e 100644 --- a/packages/frontend/src/scripts/url.ts +++ b/packages/frontend/src/scripts/url.ts @@ -23,6 +23,6 @@ export function appendQuery(url: string, query: string): string { } export function extractDomain(url: string) { - const match = url.match(/^(https)?:?\/{0,2}([^\/]+)/); - return match ? match[2] : null; + const match = url.match(/^(?:https?:)?(?:\/\/)?(?:[^@\n]+@)?([^:\/\n]+)/im); + return match ? match[1] : null; }