74 lines
2.7 KiB
TypeScript
74 lines
2.7 KiB
TypeScript
export const loadYouTubeIframeApi = (): Promise<typeof window.YT> => {
|
|
return new Promise((resolve, reject) => {
|
|
if (window.YT && window.YT.Player) {
|
|
resolve(window.YT);
|
|
return;
|
|
}
|
|
|
|
const existingScript = document.getElementById('youtube-iframe-api');
|
|
|
|
const checkReady = () => {
|
|
if (window.YT && window.YT.Player) {
|
|
resolve(window.YT);
|
|
} else {
|
|
// API script might be loaded but YT object not yet initialized
|
|
// This can happen if onYouTubeIframeAPIReady hasn't fired or was missed.
|
|
// We poll briefly.
|
|
let attempts = 0;
|
|
const interval = setInterval(() => {
|
|
attempts++;
|
|
if (window.YT && window.YT.Player) {
|
|
clearInterval(interval);
|
|
resolve(window.YT);
|
|
} else if (attempts > 20) { // Try for ~2 seconds
|
|
clearInterval(interval);
|
|
reject(new Error('YouTube Iframe API loaded but YT object not found after timeout.'));
|
|
}
|
|
}, 100);
|
|
}
|
|
};
|
|
|
|
if (existingScript) {
|
|
// If script tag exists, it might be loading or loaded.
|
|
if (window.YT && window.YT.Player) {
|
|
resolve(window.YT);
|
|
return;
|
|
}
|
|
// Cast to access readyState, which might not be in default TS lib HTMLScriptElement
|
|
const scriptElement = existingScript as HTMLScriptElement & { readyState?: string };
|
|
if (scriptElement.readyState === 'loaded' || scriptElement.readyState === 'complete') {
|
|
checkReady();
|
|
} else {
|
|
existingScript.addEventListener('load', checkReady);
|
|
existingScript.addEventListener('error', () => reject(new Error('Failed to load existing YouTube API script.')));
|
|
}
|
|
return;
|
|
}
|
|
|
|
const tag = document.createElement('script');
|
|
tag.id = 'youtube-iframe-api';
|
|
tag.src = 'https://www.youtube.com/iframe_api';
|
|
const firstScriptTag = document.getElementsByTagName('script')[0];
|
|
if (firstScriptTag && firstScriptTag.parentNode) {
|
|
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
|
|
} else {
|
|
// Fallback if no script tags exist (unlikely for a working app)
|
|
document.head.appendChild(tag);
|
|
}
|
|
|
|
(window as any).onYouTubeIframeAPIReady = () => {
|
|
if (window.YT && window.YT.Player) {
|
|
resolve(window.YT);
|
|
} else {
|
|
// This case should ideally not happen if API is working correctly
|
|
reject(new Error('onYouTubeIframeAPIReady fired but YT.Player not found.'));
|
|
}
|
|
};
|
|
|
|
tag.addEventListener('error', (e) => {
|
|
// Use a more generic error message or inspect 'e' for details if needed
|
|
reject(new Error('Failed to load YouTube Iframe API script.'));
|
|
});
|
|
});
|
|
};
|