File indexing completed on 2025-05-04 05:31:15
0001 import React, { useState, useEffect, useRef} from "react"; 0002 import Slider from 'rc-slider'; 0003 import { Scrollbars } from 'react-custom-scrollbars'; 0004 0005 function MusicPlayerWrapper(props){ 0006 0007 return ( 0008 <div> 0009 <MusicPlayer 0010 product={props.product} 0011 items={props.slide.items} 0012 containerWidth={props.width} 0013 /> 0014 </div> 0015 ) 0016 } 0017 0018 function MusicPlayer(props){ 0019 0020 /* COMPONENT */ 0021 0022 const [ playIndex, setPlayIndex ] = useState(0); 0023 const prevIndex = usePrevious(playIndex); 0024 const [ isPlaying, setIsPlaying ] = useState(); 0025 const [ isPaused, setIsPaused ] = useState(); 0026 const [ audioVolume, setAudioVolume ] = useState(0.5); 0027 const [ isMuted, setIsMuted ] = useState(false); 0028 const [ currentTrackTime, setCurrentTrackTime ] = useState(0); 0029 const [ currentTrackTimeSeconds, setCurrentTrackTimeSeconds ] = useState(0); 0030 const [ currentTrackDuration, setcurrentTrackDuration ] = useState(0); 0031 const [ currentTrackProgress, setCurrentTrackProgress ] = useState(0); 0032 const [ theme, setTheme ] = useState('dark'); 0033 let initialPLayedAudioArray = [] 0034 props.items.forEach(function(i,index){ 0035 let pl = 0; 0036 if (index === 0) pl = -1; 0037 const pa = { 0038 ...i, 0039 played:0, 0040 stopped:0 0041 } 0042 initialPLayedAudioArray.push(pa); 0043 }) 0044 const [ playedAudioArray, setPlayedAudioArray ] = useState(initialPLayedAudioArray); 0045 const [ randomSupporter, setRandomSupporter ] = useState(); 0046 0047 const initialIsMobileValue = props.containerWidth < 600 ? true : false; 0048 const [ isMobile, setIsMobile ] = useState(initialIsMobileValue); 0049 const initialShowPlaylistValue = isMobile === true ? false : true; 0050 const [ showPlaylist, setShowPlaylist ] = useState(initialShowPlaylistValue); 0051 0052 useEffect(() => { 0053 getRandomMusicsupporter(); 0054 },[]) 0055 0056 useEffect(() => { 0057 const playerElement = document.getElementById("music-player-container").getElementsByTagName('audio'); 0058 playerElement[0].volume = audioVolume; 0059 },[audioVolume]) 0060 0061 useEffect(() => { 0062 if (isPlaying) onPlayClick(true); 0063 if (isPaused){ 0064 if (prevIndex === playIndex) onPlayClick(); 0065 else onPlayClick(true); 0066 } 0067 if (isPlaying === true) onReportAudioStop(props.items[prevIndex].musicSrc,playIndex) 0068 },[playIndex]) 0069 0070 // audio player 0071 0072 function onPlayClick(reload,newPlayIndex){ 0073 0074 const playerElement = document.getElementById("music-player-container").getElementsByTagName('audio'); 0075 let pi = newPlayIndex ? newPlayIndex : playIndex; 0076 const currentSrc = props.items[pi].musicSrc; 0077 0078 if (isPaused === false || playerElement[0].currentTime && playerElement[0].currentTime === 0 || reload === true){ 0079 playerElement[0].src = currentSrc; 0080 setCurrentTrackProgress(0); 0081 } 0082 playerElement[0].play(); 0083 setIsPlaying(true); 0084 setIsPaused(false); 0085 onReportAudioPlay(currentSrc,newPlayIndex); 0086 } 0087 0088 function onPauseClick(){ 0089 const playerElement = document.getElementById("music-player-container").getElementsByTagName('audio'); 0090 playerElement[0].pause(); 0091 setIsPlaying(false); 0092 setIsPaused(true); 0093 onReportAudioStop(props.items[playIndex].musicSrc) 0094 } 0095 0096 function onPrevTrackPlayClick(){ 0097 let prevTrackIndex; 0098 if (playIndex === 0){ 0099 prevTrackIndex = props.items.length - 1; 0100 } else { 0101 prevTrackIndex = playIndex - 1; 0102 } 0103 setPlayIndex(prevTrackIndex); 0104 } 0105 0106 function onNextTrackPlayClick(){ 0107 let nextTrackIndex; 0108 if (playIndex + 1 === props.items.length){ 0109 nextTrackIndex = 0; 0110 } else { 0111 nextTrackIndex = playIndex + 1; 0112 } 0113 setPlayIndex(nextTrackIndex); 0114 } 0115 0116 function onReportAudioPlay(musicSrc,newPlayIndex){ 0117 const audioItem = playedAudioArray.find((i => i.musicSrc === musicSrc)); 0118 const audioItemIndex = newPlayIndex ? newPlayIndex : playedAudioArray.findIndex((i => i.musicSrc === musicSrc)); 0119 const newAudioItem = { 0120 ...audioItem, 0121 played:audioItem.played + 1 0122 } 0123 const newPLayedAudioArray = [ 0124 ...playedAudioArray.slice(0,audioItemIndex), 0125 newAudioItem, 0126 ...playedAudioArray.slice(audioItemIndex + 1, playedAudioArray.length) 0127 ]; 0128 0129 /*console.log('played audio array - '); 0130 console.log(playedAudioArray); 0131 console.log('audio item index - ' + audioItemIndex); 0132 console.log('audio item - ') 0133 console.log(audioItem); 0134 console.log( playedAudioArray[audioItemIndex]); 0135 console.log('is played - ' + playedAudioArray[audioItemIndex].played)*/ 0136 0137 if (playedAudioArray[audioItemIndex].played === 0){ 0138 0139 const audioStartUrl = "https://" + window.location.hostname + "/p/" + props.product.project_id + '/startmediaviewajax?collection_id='+audioItem.collection_id+'&file_id='+audioItem.file_id+'&type_id=2'; 0140 //console.log('audio start url - ' + audioStartUrl); 0141 $.ajax({url: audioStartUrl}).done(function(res) { 0142 //console.log('ajax res - '); 0143 //console.log(res); 0144 const newAudioItem = { 0145 ...audioItem, 0146 mediaViewId:res.MediaViewId, 0147 played:audioItem.played + 1 0148 } 0149 const newPLayedAudioArray = [ 0150 ...playedAudioArray.slice(0,audioItemIndex), 0151 newAudioItem, 0152 ...playedAudioArray.slice(audioItemIndex + 1, playedAudioArray.length) 0153 ]; 0154 setPlayedAudioArray(newPLayedAudioArray); 0155 }); 0156 } else { 0157 setPlayedAudioArray(newPLayedAudioArray); 0158 } 0159 } 0160 0161 function onReportAudioStop(musicSrc){ 0162 0163 const audioItem = playedAudioArray.find((i => i.musicSrc === musicSrc)); 0164 const audioItemIndex = playedAudioArray.findIndex((i => i.musicSrc === musicSrc)); 0165 const newAudioItem = { 0166 ...audioItem, 0167 stopped:audioItem.stopped + 1 0168 } 0169 const newPLayedAudioArray = [ 0170 ...playedAudioArray.slice(0,audioItemIndex), 0171 newAudioItem, 0172 ...playedAudioArray.slice(audioItemIndex + 1, playedAudioArray.length) 0173 ]; 0174 0175 if (playedAudioArray[audioItemIndex].stopped === 0){ 0176 0177 const audioStopUrl = "https://" + window.location.hostname + "/p/" + props.product.project_id + "/stopmediaviewajax?media_view_id=" + playedAudioArray[audioItemIndex].mediaViewId; 0178 0179 //console.log(audioStopUrl); 0180 0181 $.ajax({url: audioStopUrl}).done(function(res) { 0182 //console.log(res); 0183 setPlayedAudioArray(newPLayedAudioArray); 0184 }); 0185 } else { 0186 setPlayedAudioArray(newPLayedAudioArray); 0187 } 0188 } 0189 0190 function onUpdateCurrentTrackProgress(newTrackProgress){ 0191 console.log(newTrackProgress); 0192 setCurrentTrackProgress(newTrackProgress); 0193 const newCurrentTrackTime = (currentTrackTimeSeconds / 100) * newTrackProgress; 0194 const playerElement = document.getElementById("music-player-container").getElementsByTagName('audio'); 0195 playerElement[0].currentTime = newCurrentTrackTime; 0196 // playerElement[0].ontimeupdate = function(){ onPlayerTimeUpdate(playerElement[0]) } 0197 playerElement[0].play(); 0198 setIsPlaying(true); 0199 setIsPaused(false); 0200 const currentSrc = props.items[playIndex].musicSrc; 0201 onReportAudioPlay(currentSrc); 0202 } 0203 0204 // random supporter 0205 0206 function getRandomMusicsupporter(){ 0207 $.ajax({url: "https://"+window.location.hostname +"/json/fetchrandomsupporter/s/3"}).done(function(res) { 0208 // console.log(res); 0209 setRandomSupporter(res.supporter) 0210 }); 0211 } 0212 0213 // time progress bar 0214 0215 function onPlayerTimeUpdate(e){ 0216 const playerElement = e.target; 0217 const newCurrentTrackTime = millisToMinutesAndSeconds(playerElement.currentTime); 0218 setCurrentTrackTime(newCurrentTrackTime); 0219 setCurrentTrackTimeSeconds(playerElement.duration); 0220 let newcurrentTrackDuration = playerElement.duration; 0221 if (isNaN(newcurrentTrackDuration)){ newcurrentTrackDuration = 0; } 0222 newcurrentTrackDuration = millisToMinutesAndSeconds(newcurrentTrackDuration); 0223 setcurrentTrackDuration(newcurrentTrackDuration ); 0224 const newCurrentTrackProgress = (playerElement.currentTime / playerElement.duration) * 100; 0225 setCurrentTrackProgress(newCurrentTrackProgress); 0226 0227 if (playerElement.currentTime === playerElement.duration){ 0228 console.log('song ended'); 0229 onNextTrackPlayClick(); 0230 } 0231 0232 } 0233 0234 function millisToMinutesAndSeconds(time) { 0235 let minutes = Math.floor(time / 60); 0236 let seconds = time - minutes * 60; 0237 seconds = Math.floor(seconds); 0238 if (minutes < 10) minutes = "0" + minutes; 0239 if (seconds < 10) seconds = "0" + seconds; 0240 const timestamp = minutes + ":" + seconds; 0241 return timestamp; 0242 } 0243 0244 // volume 0245 0246 function toggleAudioMuted(){ 0247 const newIsMuted = isMuted === true ? false : true; 0248 const playerElement = document.getElementById("music-player-container").getElementsByTagName('audio'); 0249 if (newIsMuted === true) playerElement[0].volume = 0; 0250 else playerElement[0].volume = audioVolume; 0251 setIsMuted(newIsMuted); 0252 } 0253 0254 // playlist 0255 0256 function togglePlaylistDisplay(){ 0257 const newShowPlaylistValue = showPlaylist === true ? false : true; 0258 setShowPlaylist(newShowPlaylistValue); 0259 } 0260 0261 // key press 0262 0263 function handleKeyPress(e){ 0264 // console.log(e.key) 0265 if (e.key === 'Space'){ 0266 if (isPlaying === true) onPauseClick(); 0267 else onPlayClick(); 0268 } 0269 } 0270 0271 /* RENDER */ 0272 0273 let musicPlayerContainerCssClass = ""; 0274 if (showPlaylist === true) musicPlayerContainerCssClass += "show-playlist "; 0275 if (isMobile === true) musicPlayerContainerCssClass += " is-mobile"; 0276 0277 const audioElVolume = isMuted === true ? 0.0 : audioVolume; 0278 0279 const currentSrc = props.items[playIndex].musicSrc; 0280 0281 return ( 0282 <div id="music-player-container" className={musicPlayerContainerCssClass + " " + theme} onKeyPress={(e) => handleKeyPress(e)}> 0283 <audio 0284 volume={audioElVolume} 0285 onTimeUpdate={(e) => onPlayerTimeUpdate(e)} 0286 onLoadedMetadata={(e) => onPlayerTimeUpdate(e)} 0287 src={currentSrc} 0288 id="music-player-audio"></audio> 0289 <MusicPlayerControlPanel 0290 playIndex={playIndex} 0291 isPlaying={isPlaying} 0292 isPaused={isPaused} 0293 isMuted={isMuted} 0294 isMobile={isMobile} 0295 audioVolume={audioVolume} 0296 currentTrackTime={currentTrackTime} 0297 currentTrackDuration={currentTrackDuration} 0298 currentTrackProgress={currentTrackProgress} 0299 items={props.items} 0300 theme={theme} 0301 setTheme={(val) => setTheme(val)} 0302 onUpdateCurrentTrackProgress={(val) => onUpdateCurrentTrackProgress(val)} 0303 onChangeAudioVolume={(val) => setAudioVolume(val)} 0304 onPlayClick={(reload) => onPlayClick(reload)} 0305 onPauseClick={onPauseClick} 0306 onPrevTrackPlayClick={onPrevTrackPlayClick} 0307 onNextTrackPlayClick={onNextTrackPlayClick} 0308 togglePlaylistDisplay={togglePlaylistDisplay} 0309 toggleAudioMuted={() => toggleAudioMuted()} 0310 /> 0311 <MusicPlayerPlaylist 0312 containerWidth={props.containerWidth} 0313 title={props.product.title} 0314 randomSupporter={randomSupporter} 0315 items={props.items} 0316 playIndex={playIndex} 0317 isPlaying={isPlaying} 0318 isPaused={isPaused} 0319 isMobile={isMobile} 0320 currentTrackTime={currentTrackTime} 0321 currentTrackDuration={currentTrackDuration} 0322 currentTrackProgress={currentTrackProgress} 0323 togglePlaylistDisplay={togglePlaylistDisplay} 0324 setPlayIndex={setPlayIndex} 0325 onPlayClick={(reload) => onPlayClick(reload)} 0326 onPauseClick={onPauseClick} 0327 /> 0328 </div> 0329 ) 0330 } 0331 0332 // Hook 0333 function usePrevious(value) { 0334 // The ref object is a generic container whose current property is mutable ... 0335 // ... and can hold any value, similar to an instance property on a class 0336 const ref = useRef(); 0337 0338 // Store current value in ref 0339 useEffect(() => { 0340 ref.current = value; 0341 }, [value]); // Only re-run if value changes 0342 0343 // Return previous value (happens before update in useEffect above) 0344 return ref.current; 0345 } 0346 0347 function MusicPlayerControlPanel(props){ 0348 0349 // console.log(props); 0350 0351 React.useEffect(() => { 0352 // console.log('music player controls panel'); 0353 // console.log(props); 0354 },[]) 0355 0356 /* COMPONENT */ 0357 0358 function onChangeTrackProgressPosition(e){ 0359 console.log(e); 0360 props.onUpdateCurrentTrackProgress(e); 0361 } 0362 0363 function onAfterChangeTrackProgressPosition(e){ 0364 // console.log(e); 0365 } 0366 0367 function onChangeVolumeSliderPosition(e){ 0368 if (props.isMuted === false){ 0369 const newVolumeValue = e / 100; 0370 props.onChangeAudioVolume(newVolumeValue); 0371 } 0372 } 0373 0374 function onAfterChangeVolumeSliderPosition(e){ 0375 // console.log(e); 0376 } 0377 0378 function onVolumeIconClick(){ 0379 props.toggleAudioMuted() 0380 } 0381 0382 function onThemeSwitchClick(){ 0383 const newThemeValue = props.theme === "dark" ? "light" : "dark"; 0384 props.setTheme(newThemeValue); 0385 } 0386 0387 /* DISPLAY */ 0388 0389 const playIndex = props.playIndex; 0390 0391 // audio controls display 0392 0393 const playButtonElement = ( 0394 <svg fill="currentColor" preserveAspectRatio="xMidYMid meet" height="1em" width="1em" viewBox="0 0 40 40" className="play-icon"> 0395 <g><path d="m20.1 2.9q4.7 0 8.6 2.3t6.3 6.2 2.3 8.6-2.3 8.6-6.3 6.2-8.6 2.3-8.6-2.3-6.2-6.2-2.3-8.6 2.3-8.6 6.2-6.2 8.6-2.3z m8.6 18.3q0.7-0.4 0.7-1.2t-0.7-1.2l-12.1-7.2q-0.7-0.4-1.5 0-0.7 0.4-0.7 1.3v14.2q0 0.9 0.7 1.3 0.4 0.2 0.8 0.2 0.3 0 0.7-0.2z"></path></g> 0396 </svg> 0397 ) 0398 0399 const pauseButtonElement = ( 0400 <svg fill="currentColor" preserveAspectRatio="xMidYMid meet" height="1em" width="1em" viewBox="0 0 40 40" className="pause-icon"> 0401 <g><path d="m18.7 26.4v-12.8q0-0.3-0.2-0.5t-0.5-0.2h-5.7q-0.3 0-0.5 0.2t-0.2 0.5v12.8q0 0.3 0.2 0.5t0.5 0.2h5.7q0.3 0 0.5-0.2t0.2-0.5z m10 0v-12.8q0-0.3-0.2-0.5t-0.5-0.2h-5.7q-0.3 0-0.5 0.2t-0.2 0.5v12.8q0 0.3 0.2 0.5t0.5 0.2h5.7q0.3 0 0.5-0.2t0.2-0.5z m8.6-6.4q0 4.7-2.3 8.6t-6.3 6.2-8.6 2.3-8.6-2.3-6.2-6.2-2.3-8.6 2.3-8.6 6.2-6.2 8.6-2.3 8.6 2.3 6.3 6.2 2.3 8.6z"></path></g> 0402 </svg> 0403 ) 0404 0405 const prevButtonElement = ( 0406 <svg fill="currentColor" preserveAspectRatio="xMidYMid meet" height="1em" width="1em" viewBox="0 0 40 40" className="prev-icon"> 0407 <g><path d="m15.9 20l14.1-10v20z m-5.9-10h3.4v20h-3.4v-20z"></path></g> 0408 </svg> 0409 ) 0410 0411 const nextButtonElement = ( 0412 <svg fill="currentColor" preserveAspectRatio="xMidYMid meet" height="1em" width="1em" viewBox="0 0 40 40" className="next-icon"> 0413 <g><path d="m26.6 10h3.4v20h-3.4v-20z m-16.6 20v-20l14.1 10z"></path></g> 0414 </svg> 0415 ) 0416 0417 let playButtonDisplay; 0418 if (props.isPlaying === true){ 0419 if (props.isMobile === true) playButtonDisplay = <span onTouchStart={() => props.onPauseClick()}>{pauseButtonElement}</span> 0420 else playButtonDisplay = <span onClick={() => props.onPauseClick()}>{pauseButtonElement}</span> 0421 } else { 0422 if (props.isMobile === true) playButtonDisplay = <span onTouchStart={() => props.onPlayClick()}>{playButtonElement}</span> 0423 else playButtonDisplay = <span onClick={() => props.onPlayClick()}>{playButtonElement}</span> 0424 } 0425 0426 let audioControlsDisplay; 0427 0428 if (props.isMobile === true){ 0429 audioControlsDisplay = ( 0430 <div className="music-player-audio-control"> 0431 <span onTouchStart={() => props.onPrevTrackPlayClick()}>{prevButtonElement}</span> 0432 {playButtonDisplay} 0433 <span onTouchStart={() => props.onNextTrackPlayClick()}>{nextButtonElement}</span> 0434 </div> 0435 ) 0436 } else { 0437 audioControlsDisplay = ( 0438 <div className="music-player-audio-control"> 0439 <span onClick={() => props.onPrevTrackPlayClick()}>{prevButtonElement}</span> 0440 {playButtonDisplay} 0441 <span onClick={() => props.onNextTrackPlayClick()}>{nextButtonElement}</span> 0442 </div> 0443 ) 0444 } 0445 0446 // volume control 0447 0448 const volumeIcon = ( 0449 <svg fill="currentColor" preserveAspectRatio="xMidYMid meet" height="1em" width="1em" viewBox="0 0 40 40" style={{"verticalAlign":"middle"}}> 0450 <g><path d="m23.4 5.4c6.7 1.5 11.6 7.5 11.6 14.6s-4.9 13.1-11.6 14.6v-3.4c4.8-1.4 8.2-5.9 8.2-11.2s-3.4-9.8-8.2-11.2v-3.4z m4.1 14.6c0 3-1.6 5.5-4.1 6.7v-13.4c2.5 1.2 4.1 3.7 4.1 6.7z m-22.5-5h6.6l8.4-8.4v26.8l-8.4-8.4h-6.6v-10z"></path></g> 0451 </svg> 0452 ) 0453 0454 const noVolumeIcon = ( 0455 <svg fill="currentColor" preserveAspectRatio="xMidYMid meet" height="1em" width="1em" viewBox="0 0 40 40" style={{"verticalAlign":"middle"}}> 0456 <g><path d="m20 6.6v7.1l-3.5-3.5z m-12.9-1.6l27.9 27.9-2.1 2.1-3.4-3.4c-1.8 1.4-3.9 2.5-6.1 3v-3.4c1.4-0.4 2.6-1.1 3.7-2l-7.1-7.1v11.3l-8.4-8.4h-6.6v-10h7.9l-7.9-7.9z m24.5 15c0-5.3-3.4-9.8-8.2-11.2v-3.4c6.7 1.5 11.6 7.5 11.6 14.6 0 2.5-0.6 4.9-1.7 7l-2.5-2.6c0.5-1.4 0.8-2.8 0.8-4.4z m-4.1 0c0 0.4 0 0.7-0.1 1l-4-4.1v-3.6c2.5 1.2 4.1 3.7 4.1 6.7z"></path></g> 0457 </svg> 0458 ) 0459 0460 const volumeIconDisplay = props.isMuted === false ? volumeIcon : noVolumeIcon; 0461 let musicPlayerVolumeControlCssClass = "music-player-volume-control"; 0462 if (props.isMuted) musicPlayerVolumeControlCssClass += " is-muted"; 0463 0464 const volumeControlDisplay = ( 0465 <div className={musicPlayerVolumeControlCssClass}> 0466 <span className="volume-icon" onClick={onVolumeIconClick}> 0467 {volumeIconDisplay} 0468 </span> 0469 <span className="volume-bar-container progress_bar"> 0470 <Slider 0471 min={0} 0472 max={100} 0473 value={props.audioVolume * 100} 0474 vertical={props.isMobile ? false : true} 0475 onChange={onChangeVolumeSliderPosition} 0476 onAfterChange={onAfterChangeVolumeSliderPosition} 0477 /> 0478 </span> 0479 </div> 0480 ); 0481 0482 // cover 0483 0484 const musicPlayerCoverDisplay = ( 0485 <div className="music-player-cover"> 0486 <figure><img src={props.items[playIndex].cover}/></figure> 0487 </div> 0488 ) 0489 0490 // title 0491 0492 const musicPlayerTitleDisplay = ( 0493 <div className="music-player-track-title"> 0494 <h2>{props.items[playIndex].title}</h2> 0495 </div> 0496 ) 0497 0498 // time display 0499 0500 let currentTrackTimeDisplay = props.currentTrackTime; 0501 if (props.currentTrackTime === 0){ 0502 currentTrackTimeDisplay = '00:00' 0503 } 0504 0505 let currentTrackDurationDisplay = props.currentTrackDuration; 0506 if (props.currentTrackDuration === 0){ 0507 currentTrackDurationDisplay = <span className="infinite">∞</span> 0508 } 0509 0510 const musicPlayerTimeDisplay = ( 0511 <div className="music-player-time-display"> 0512 <span className="current-track-time">{currentTrackTimeDisplay} </span> 0513 <span className="current-track-progress"> 0514 <Slider 0515 min={0} 0516 max={100} 0517 value={props.currentTrackProgress} 0518 onChange={onChangeTrackProgressPosition} 0519 onAfterChange={onAfterChangeTrackProgressPosition} 0520 /> 0521 </span> 0522 <span className="current-track-duration">{currentTrackDurationDisplay}</span> 0523 </div> 0524 ) 0525 0526 // mobile / desktop switch display 0527 0528 let musicPlayerControlPanelDisplay; 0529 if (props.isMobile === true){ 0530 0531 musicPlayerControlPanelDisplay = ( 0532 <div className="mobile-control-panel-wrapper"> 0533 {musicPlayerTitleDisplay} 0534 {musicPlayerCoverDisplay} 0535 {musicPlayerTimeDisplay} 0536 <div className="music-player-controls-bar"> 0537 <div className="music-player-controls-wrapper"> 0538 {audioControlsDisplay} 0539 <div className="bottom-controls"> 0540 {volumeControlDisplay} 0541 <div className="playlist-toggle-container"> 0542 <span className="playlist-toggle-button" onTouchStart={() => props.togglePlaylistDisplay()}> 0543 <svg fill="currentColor" preserveAspectRatio="xMidYMid meet" height="1em" width="1em" viewBox="0 0 40 40" style={{"vertical-align": "middle"}}> 0544 <g><path d="m28.4 10h8.2v3.4h-5v15c0 2.7-2.2 5-5 5s-5-2.3-5-5 2.3-5 5-5c0.6 0 1.2 0.1 1.8 0.3v-13.7z m-23.4 16.6v-3.2h13.4v3.2h-13.4z m20-10v3.4h-20v-3.4h20z m0-6.6v3.4h-20v-3.4h20z"></path></g> 0545 </svg> 0546 </span> 0547 </div> 0548 </div> 0549 </div> 0550 </div> 0551 </div> 0552 ) 0553 0554 } else { 0555 0556 let themeSwitchCssClass = "theme-switch-container rc-switch "; 0557 /*<div className="theme-switch-wrapper"> 0558 <span className="theme-switch"> 0559 <button onClick={() => onThemeSwitchClick()} type="button" role="switch" aria-checked="false" className={ themeSwitchCssClass }> 0560 <span className="rc-switch-inner">{props.theme === "dark" ? "light" : "dark"}</span> 0561 </button> 0562 </span> 0563 </div>*/ 0564 0565 if (props.theme === "light") themeSwitchCssClass += " checked"; 0566 0567 musicPlayerControlPanelDisplay = ( 0568 <div className="desktop-control-panel-wrapper"> 0569 {musicPlayerCoverDisplay} 0570 {musicPlayerTitleDisplay} 0571 {musicPlayerTimeDisplay} 0572 <div className="music-player-controls-bar"> 0573 <div className="music-player-controls-wrapper"> 0574 {audioControlsDisplay} 0575 {volumeControlDisplay} 0576 <div className="playlist-toggle-container"> 0577 <span className="playlist-toggle-button" onClick={() => props.togglePlaylistDisplay()}>PL</span> 0578 </div> 0579 </div> 0580 </div> 0581 </div> 0582 ) 0583 } 0584 0585 /* RENDER */ 0586 0587 return ( 0588 <div id="music-player-control-panel"> 0589 {musicPlayerControlPanelDisplay} 0590 </div> 0591 ) 0592 } 0593 0594 function MusicPlayerPlaylist(props){ 0595 0596 function onMusicPlayerPlaylistItemClick(val){ 0597 if (props.isPlaying === false){ 0598 if (props.playIndex === val) props.onPlayClick(); 0599 // else props.onPlayClick(true,props.playIndex); 0600 } 0601 else { 0602 if (props.playIndex === val) props.onPauseClick(); 0603 // else props.onPlayClick(true,props.playIndex); 0604 } 0605 props.setPlayIndex(val); 0606 } 0607 0608 const musicPlayerPlaylistItems = props.items.map((item,index) => ( 0609 <MusicPlayerPlaylistItem 0610 key={index} 0611 index={index} 0612 item={item} 0613 playIndex={props.playIndex} 0614 isPlaying={props.isPlaying} 0615 isPaused={props.isPaused} 0616 isMobile={props.isMobile} 0617 onMusicPlayerPlaylistItemClick={(val) => onMusicPlayerPlaylistItemClick(val)} 0618 /> 0619 )); 0620 0621 const musicPlayerPlaylistDisplay = <ul>{musicPlayerPlaylistItems}</ul> 0622 0623 0624 let randomSupporterDisplay; 0625 if (props.randomSupporter && props.randomSupporter !== null){ 0626 randomSupporterDisplay = ( 0627 <div id="music-sponsor-display"> 0628 <span>made possible by supporters like</span> 0629 <span className="sponsor-avatar"> 0630 <a href={"/u/" + props.randomSupporter.username}> 0631 <img src={props.randomSupporter.profile_image_url}/> 0632 </a> 0633 </span> 0634 <span> 0635 {props.randomSupporter.username} 0636 </span> 0637 </div> 0638 ) 0639 } 0640 0641 let closeButtonDisplay = <a className="toggle-playlist" onClick={props.togglePlaylistDisplay}>X</a> 0642 if (props.isMobile === true) closeButtonDisplay = <a className="toggle-playlist" onTouchStart={props.togglePlaylistDisplay}>X</a> 0643 0644 return ( 0645 <div id="music-player-playlist-panel"> 0646 <div id="music-player-playlist-header"> 0647 <h2>{props.title + " / " + props.items.length }</h2> 0648 {closeButtonDisplay} 0649 </div> 0650 <div id="music-player-playlist"> 0651 <Scrollbars 0652 width={props.containerWidth / 2} 0653 height={250} 0654 > 0655 {musicPlayerPlaylistDisplay} 0656 </Scrollbars> 0657 </div> 0658 <div id="music-player-playlist-footer"> 0659 {randomSupporterDisplay} 0660 </div> 0661 </div> 0662 ) 0663 } 0664 0665 function MusicPlayerPlaylistItem(props){ 0666 0667 const playButtonElement = ( 0668 <svg fill="currentColor" preserveAspectRatio="xMidYMid meet" height="1em" width="1em" viewBox="0 0 40 40" className="play-icon"> 0669 <g><path d="m20.1 2.9q4.7 0 8.6 2.3t6.3 6.2 2.3 8.6-2.3 8.6-6.3 6.2-8.6 2.3-8.6-2.3-6.2-6.2-2.3-8.6 2.3-8.6 6.2-6.2 8.6-2.3z m8.6 18.3q0.7-0.4 0.7-1.2t-0.7-1.2l-12.1-7.2q-0.7-0.4-1.5 0-0.7 0.4-0.7 1.3v14.2q0 0.9 0.7 1.3 0.4 0.2 0.8 0.2 0.3 0 0.7-0.2z"></path></g> 0670 </svg> 0671 ) 0672 0673 const pauseButtonElement = ( 0674 <svg fill="currentColor" preserveAspectRatio="xMidYMid meet" height="1em" width="1em" viewBox="0 0 40 40" className="pause-icon"> 0675 <g><path d="m18.7 26.4v-12.8q0-0.3-0.2-0.5t-0.5-0.2h-5.7q-0.3 0-0.5 0.2t-0.2 0.5v12.8q0 0.3 0.2 0.5t0.5 0.2h5.7q0.3 0 0.5-0.2t0.2-0.5z m10 0v-12.8q0-0.3-0.2-0.5t-0.5-0.2h-5.7q-0.3 0-0.5 0.2t-0.2 0.5v12.8q0 0.3 0.2 0.5t0.5 0.2h5.7q0.3 0 0.5-0.2t0.2-0.5z m8.6-6.4q0 4.7-2.3 8.6t-6.3 6.2-8.6 2.3-8.6-2.3-6.2-6.2-2.3-8.6 2.3-8.6 6.2-6.2 8.6-2.3 8.6 2.3 6.3 6.2 2.3 8.6z"></path></g> 0676 </svg> 0677 ) 0678 0679 const playlistItemPlayButtonDisplay = props.playIndex === props.index ? props.isPlaying === true ? pauseButtonElement : playButtonElement : ''; 0680 const playlistItemCssClass = props.playIndex === props.index ? props.isPlaying === true ? 'is-playing' : 'is-paused' : ''; 0681 0682 let musicPlayerPlaylistItemDisplay; 0683 if (props.isMobile === true){ 0684 musicPlayerPlaylistItemDisplay = ( 0685 <a onTouchStart={() => props.onMusicPlayerPlaylistItemClick(props.index)}> 0686 {playlistItemPlayButtonDisplay} 0687 {props.item.title} 0688 </a> 0689 ) 0690 } else { 0691 musicPlayerPlaylistItemDisplay = ( 0692 <a onClick={() => props.onMusicPlayerPlaylistItemClick(props.index)}> 0693 {playlistItemPlayButtonDisplay} 0694 {props.item.title} 0695 </a> 0696 ) 0697 } 0698 0699 return ( 0700 <li className={"music-player-playlist-item " + playlistItemCssClass} > 0701 {musicPlayerPlaylistItemDisplay} 0702 </li> 0703 ) 0704 } 0705 0706 export default MusicPlayerWrapper;