mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-06-25 17:10:43 +00:00
fix(frontend): URLプレイヤーウィンドウでiframeが読み込まれるまでの間にinvalid urlと表示される問題を修正 (#17417)
* fix(frontend): URLプレイヤーウィンドウでiframeが読み込まれるまでの間にinvalid urlと表示される問題を修正 * Update Changelog * fix * fix lint * Update Changelog --------- Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
This commit is contained in:
parent
89ae64b077
commit
7e0eb61495
3 changed files with 71 additions and 49 deletions
|
|
@ -5,6 +5,7 @@
|
|||
- Feat: アンテナのタイムラインから個別のノートを削除できるように
|
||||
|
||||
### Client
|
||||
- Fix: URLプレビューのプレイヤーをウィンドウで開いたとき、プレイヤーが読み込まれるまでの間 `Invalid URL` と表示される問題を修正
|
||||
- Fix: 一部の実績が正しく表示されない問題を修正
|
||||
- Fix: アクセストークン発行時のダイアログのタイトルが「確認コード」となっているのを修正
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { defineAsyncComponent, onDeactivated, onUnmounted, ref } from 'vue';
|
||||
import { computed, defineAsyncComponent, onDeactivated, onUnmounted, ref } from 'vue';
|
||||
import { url as local } from '@@/js/config.js';
|
||||
import { versatileLang } from '@@/js/intl-const.js';
|
||||
import type { SummalyResult } from '@misskey-dev/summaly';
|
||||
|
|
@ -115,17 +115,14 @@ const self = maybeRelativeUrl !== props.url;
|
|||
const attr = self ? 'to' : 'href';
|
||||
const target = self ? null : '_blank';
|
||||
const fetching = ref(true);
|
||||
const title = ref<string | null>(null);
|
||||
const description = ref<string | null>(null);
|
||||
const thumbnail = ref<string | null>(null);
|
||||
const icon = ref<string | null>(null);
|
||||
const sitename = ref<string | null>(null);
|
||||
const sensitive = ref<boolean>(false);
|
||||
const player = ref({
|
||||
url: null,
|
||||
width: null,
|
||||
height: null,
|
||||
} as SummalyResult['player']);
|
||||
const summalyResult = ref<SummalyResult | null>(null);
|
||||
const title = computed(() => summalyResult.value?.title ?? null);
|
||||
const description = computed(() => summalyResult.value?.description ?? null);
|
||||
const thumbnail = computed(() => summalyResult.value?.thumbnail ?? null);
|
||||
const icon = computed(() => summalyResult.value?.icon ?? null);
|
||||
const sitename = computed(() => summalyResult.value?.sitename ?? null);
|
||||
const sensitive = computed(() => summalyResult.value?.sensitive ?? false);
|
||||
const player = computed(() => summalyResult.value?.player ?? { url: null, width: null, height: null });
|
||||
const playerEnabled = ref(false);
|
||||
const tweetId = ref<string | null>(null);
|
||||
const tweetExpanded = ref(props.detail);
|
||||
|
|
@ -137,7 +134,7 @@ onDeactivated(() => {
|
|||
playerEnabled.value = false;
|
||||
});
|
||||
|
||||
const requestUrl = new URL(props.url);
|
||||
const requestUrl = new URL(props.url, window.location.href);
|
||||
if (!['http:', 'https:'].includes(requestUrl.protocol)) throw new Error('invalid url');
|
||||
|
||||
if (requestUrl.hostname === 'twitter.com' || requestUrl.hostname === 'mobile.twitter.com' || requestUrl.hostname === 'x.com' || requestUrl.hostname === 'mobile.x.com') {
|
||||
|
|
@ -172,13 +169,7 @@ window.fetch(`/url?url=${encodeURIComponent(requestUrl.href)}&lang=${versatileLa
|
|||
fetching.value = false;
|
||||
unknownUrl.value = false;
|
||||
|
||||
title.value = info.title;
|
||||
description.value = info.description;
|
||||
thumbnail.value = info.thumbnail;
|
||||
icon.value = info.icon;
|
||||
sitename.value = info.sitename;
|
||||
player.value = info.player;
|
||||
sensitive.value = info.sensitive ?? false;
|
||||
summalyResult.value = info;
|
||||
});
|
||||
|
||||
function adjustTweetHeight(message: MessageEvent) {
|
||||
|
|
@ -191,8 +182,10 @@ function adjustTweetHeight(message: MessageEvent) {
|
|||
}
|
||||
|
||||
function openPlayer(): void {
|
||||
if (!summalyResult.value) return;
|
||||
|
||||
const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkYouTubePlayer.vue')), {
|
||||
url: requestUrl.href,
|
||||
urlOrSummalyResult: summalyResult.value,
|
||||
}, {
|
||||
closed: () => {
|
||||
dispose();
|
||||
|
|
|
|||
|
|
@ -11,14 +11,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</template>
|
||||
|
||||
<div class="poamfof">
|
||||
<Transition :name="prefer.s.animation ? 'fade' : ''" mode="out-in">
|
||||
<div v-if="player.url && (player.url.startsWith('http://') || player.url.startsWith('https://'))" class="player">
|
||||
<iframe v-if="!fetching" :src="transformPlayerUrl(player.url)" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
|
||||
</div>
|
||||
<span v-else>invalid url</span>
|
||||
</Transition>
|
||||
<MkLoading v-if="fetching"/>
|
||||
<MkError v-else-if="!player.url" @retry="ytFetch()"/>
|
||||
<MkLoading v-if="fetching || !iframeLoaded"/>
|
||||
<div v-if="!fetching && player?.url != null" class="player">
|
||||
<iframe
|
||||
:src="transformPlayerUrl(player.url)"
|
||||
frameborder="0"
|
||||
:allow="player.allow.join('; ')"
|
||||
allowfullscreen
|
||||
:style="{ opacity: iframeLoaded ? 1 : 0, transition: 'opacity 0.3s' }"
|
||||
@load="onFrameLoad"
|
||||
></iframe>
|
||||
</div>
|
||||
<MkError v-else @retry="ytFetch()"/>
|
||||
</div>
|
||||
</MkWindow>
|
||||
</template>
|
||||
|
|
@ -28,41 +32,65 @@ import { ref } from 'vue';
|
|||
import { versatileLang } from '@@/js/intl-const.js';
|
||||
import MkWindow from '@/components/MkWindow.vue';
|
||||
import { transformPlayerUrl } from '@/utility/url-preview.js';
|
||||
import { prefer } from '@/preferences.js';
|
||||
import type { SummalyResult } from '@misskey-dev/summaly';
|
||||
|
||||
const props = defineProps<{
|
||||
url: string;
|
||||
urlOrSummalyResult: string | SummalyResult;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const requestUrl = new URL(props.url);
|
||||
if (!['http:', 'https:'].includes(requestUrl.protocol)) throw new Error('invalid url');
|
||||
|
||||
const fetching = ref(true);
|
||||
const iframeLoaded = ref(false);
|
||||
const title = ref<string | null>(null);
|
||||
const player = ref({
|
||||
url: null as string | null,
|
||||
width: null,
|
||||
height: null,
|
||||
});
|
||||
const player = ref<SummalyResult['player'] | null>(null);
|
||||
|
||||
const ytFetch = (): void => {
|
||||
async function ytFetch() {
|
||||
title.value = null;
|
||||
player.value = null;
|
||||
fetching.value = true;
|
||||
window.fetch(`/url?url=${encodeURIComponent(requestUrl.href)}&lang=${versatileLang}`).then(res => {
|
||||
res.json().then(info => {
|
||||
if (info.url == null) return;
|
||||
title.value = info.title;
|
||||
iframeLoaded.value = false;
|
||||
|
||||
let info: SummalyResult;
|
||||
|
||||
if (typeof props.urlOrSummalyResult === 'string') {
|
||||
const requestUrl = new URL(props.urlOrSummalyResult, window.location.href);
|
||||
if (requestUrl.protocol !== 'http:' && requestUrl.protocol !== 'https:') {
|
||||
// Invalid URL
|
||||
fetching.value = false;
|
||||
player.value = info.player;
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await window.fetch(`/url?url=${encodeURIComponent(requestUrl.href)}&lang=${versatileLang}`);
|
||||
info = await res.json() as SummalyResult;
|
||||
} else {
|
||||
info = props.urlOrSummalyResult;
|
||||
}
|
||||
|
||||
if (info.url == null || info.player?.url == null) {
|
||||
// No URL or player info
|
||||
fetching.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info.player.url.startsWith('https://') && !info.player.url.startsWith('http://')) {
|
||||
// Invalid player URL
|
||||
fetching.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
title.value = info.title;
|
||||
player.value = info.player;
|
||||
fetching.value = false;
|
||||
}
|
||||
|
||||
const onFrameLoad = (): void => {
|
||||
iframeLoaded.value = true;
|
||||
};
|
||||
|
||||
ytFetch();
|
||||
|
||||
void ytFetch();
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue