123 lines
4.6 KiB
React
123 lines
4.6 KiB
React
|
|
import React, { useState, useEffect } from 'react';
|
||
|
|
import Skeleton from 'react-loading-skeleton';
|
||
|
|
|
||
|
|
const MediaViewer = ({ mediaUrls }) => {
|
||
|
|
const [loadedMedia, setLoadedMedia] = useState([]);
|
||
|
|
const [loading, setLoading] = useState(true);
|
||
|
|
|
||
|
|
function isMediaUrl(url) {
|
||
|
|
const urls = url[0];
|
||
|
|
const audioExtensions = ['.mp3', '.wav', '.ogg', '.m4a', '.aac', '.flac'];
|
||
|
|
const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.svg', '.webp'];
|
||
|
|
|
||
|
|
const lowercasedUrl = urls.toLowerCase();
|
||
|
|
const isAudio = audioExtensions.some(extension => lowercasedUrl.endsWith(extension));
|
||
|
|
const isImage = imageExtensions.some(extension => lowercasedUrl.endsWith(extension));
|
||
|
|
|
||
|
|
return isAudio || isImage;
|
||
|
|
}
|
||
|
|
|
||
|
|
const preloadMedia = (urls) => {
|
||
|
|
return Promise.all(
|
||
|
|
urls.map((url) => {
|
||
|
|
return new Promise((resolve, reject) => {
|
||
|
|
const mediaType = url.split('.').pop();
|
||
|
|
|
||
|
|
if (['jpg', 'jpeg', 'png', 'gif'].includes(mediaType)) {
|
||
|
|
const img = new Image();
|
||
|
|
img.src = url;
|
||
|
|
img.onload = () => resolve({ type: 'image', url });
|
||
|
|
img.onerror = () => reject(`Failed to load image: ${url}`);
|
||
|
|
} else if (['mp3', 'wav'].includes(mediaType)) {
|
||
|
|
const audio = new Audio();
|
||
|
|
audio.src = url;
|
||
|
|
audio.onloadedmetadata = () => resolve({ type: 'audio', url });
|
||
|
|
audio.onerror = () => reject(`Failed to load audio: ${url}`);
|
||
|
|
} else {
|
||
|
|
resolve({ type: 'unknown', url });
|
||
|
|
}
|
||
|
|
});
|
||
|
|
})
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
const renderVideo = (url) => {
|
||
|
|
// Cek apakah ini link YouTube
|
||
|
|
if (url.includes('youtube.com') || url.includes('youtu.be')) {
|
||
|
|
const youtubeId = url.includes('youtube.com')
|
||
|
|
? new URLSearchParams(new URL(url).search).get('v') // Ambil ID dari link YouTube
|
||
|
|
: url.split('/').pop(); // Ambil ID dari youtu.be link
|
||
|
|
|
||
|
|
return (
|
||
|
|
<iframe
|
||
|
|
src={`https://www.youtube.com/embed/${youtubeId}`}
|
||
|
|
frameBorder="0"
|
||
|
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||
|
|
allowFullScreen
|
||
|
|
title="YouTube Video"
|
||
|
|
className='video-box'
|
||
|
|
></iframe>
|
||
|
|
);
|
||
|
|
} else if (url.includes('drive.google.com')) {
|
||
|
|
const driveId = url.includes('file/d/') ? url.split('file/d/')[1].split('/')[0] : '';
|
||
|
|
return (
|
||
|
|
<iframe
|
||
|
|
src={`https://drive.google.com/file/d/${driveId}/preview`}
|
||
|
|
allow="autoplay"
|
||
|
|
title="Google Drive Video"
|
||
|
|
className='video-box'
|
||
|
|
></iframe>
|
||
|
|
);
|
||
|
|
} else {
|
||
|
|
return (
|
||
|
|
<video controls className='video-box'>
|
||
|
|
<source src={url} type="video/mp4" />
|
||
|
|
Your browser does not support the video tag.
|
||
|
|
</video>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
if (mediaUrls && mediaUrls.length > 0 && isMediaUrl(mediaUrls)) {
|
||
|
|
preloadMedia(mediaUrls)
|
||
|
|
.then((loaded) => {
|
||
|
|
setLoadedMedia(loaded);
|
||
|
|
setLoading(false);
|
||
|
|
})
|
||
|
|
.catch((error) => {
|
||
|
|
console.error(error);
|
||
|
|
setLoading(false);
|
||
|
|
});
|
||
|
|
} else {
|
||
|
|
setLoading(false);
|
||
|
|
}
|
||
|
|
}, [mediaUrls]);
|
||
|
|
|
||
|
|
if (loading) {
|
||
|
|
return (
|
||
|
|
<Skeleton containerClassName='w-50 d-block' className='w-100 mb-1 rounded-3' style={{height:"20vh"}} />
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className='my-1'>
|
||
|
|
{isMediaUrl(mediaUrls) ? (
|
||
|
|
loadedMedia.map((media, index) => {
|
||
|
|
if (media.type === 'image') {
|
||
|
|
return <img key={index} src={media.url} alt={`Media ${index}`} />;
|
||
|
|
} else if (media.type === 'audio') {
|
||
|
|
return <audio key={index} controls src={media.url}></audio>;
|
||
|
|
} else {
|
||
|
|
return <div key={index}>Unknown media type</div>;
|
||
|
|
}
|
||
|
|
})
|
||
|
|
) : (
|
||
|
|
renderVideo(mediaUrls[0]) // Panggil fungsi renderVideo dengan URL yang benar
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
export default MediaViewer;
|