@@ -7,10 +7,11 @@
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
"@testing-library/react": "^16.3.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"ajv": "^8.17.1",
|
||||
"materialize-css": "^1.0.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"react": "^19.2.3",
|
||||
"react-dom": "^19.2.3",
|
||||
"react-materialize": "^3.10.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"sass": "^1.89.0",
|
||||
|
||||
37
src/App.js
37
src/App.js
@@ -1,5 +1,5 @@
|
||||
import "./App.css";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import WaveForm from "./WaveForm";
|
||||
import M from "materialize-css";
|
||||
import text from "./list.txt";
|
||||
@@ -13,11 +13,19 @@ import useBackgroundImages from "./hooks/useBackgroundImages";
|
||||
import Header from "./components/Header";
|
||||
import TrackInfo from "./components/TrackInfo";
|
||||
import AudioControls from "./components/AudioControls";
|
||||
import StreamSelector from "./components/StreamSelector";
|
||||
|
||||
/**
|
||||
* Main App component
|
||||
*/
|
||||
const App = () => {
|
||||
// State for current stream selection
|
||||
const [currentStream, setCurrentStream] = useState({
|
||||
id: 'stream-radio',
|
||||
name: 'Stream Radio',
|
||||
url: '/stream.mp3'
|
||||
});
|
||||
|
||||
// Custom hook for managing background images
|
||||
const { loadImages } = useBackgroundImages(text);
|
||||
|
||||
@@ -46,6 +54,26 @@ const App = () => {
|
||||
// Initialization flag to prevent multiple initializations
|
||||
const initialized = useRef(false);
|
||||
|
||||
// Handle stream change
|
||||
const handleStreamChange = (newStream) => {
|
||||
const wasPlaying = !paused;
|
||||
|
||||
// Pause current playback
|
||||
if (wasPlaying) {
|
||||
pause();
|
||||
}
|
||||
|
||||
// Update stream
|
||||
setCurrentStream(newStream);
|
||||
|
||||
// Resume playback if was playing
|
||||
if (wasPlaying) {
|
||||
setTimeout(() => {
|
||||
play();
|
||||
}, 100);
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize app and setup periodic data refresh
|
||||
useEffect(() => {
|
||||
if (initialized.current) return;
|
||||
@@ -100,8 +128,13 @@ const App = () => {
|
||||
onToggleMute={toggleMute}
|
||||
/>
|
||||
|
||||
<StreamSelector
|
||||
currentStream={currentStream.id}
|
||||
onStreamChange={handleStreamChange}
|
||||
/>
|
||||
|
||||
<audio
|
||||
src="/stream.mp3"
|
||||
src={currentStream.url}
|
||||
ref={audioElmRef}
|
||||
preload="none"
|
||||
muted={muted}
|
||||
|
||||
87
src/components/StreamSelector.js
Archivo normal
87
src/components/StreamSelector.js
Archivo normal
@@ -0,0 +1,87 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
/**
|
||||
* StreamSelector component
|
||||
* Displays a select dropdown to choose between different radio streams
|
||||
*/
|
||||
const StreamSelector = ({ currentStream, onStreamChange }) => {
|
||||
const streams = [
|
||||
{
|
||||
id: 'stream-radio',
|
||||
name: 'Stream Radio',
|
||||
url: '/stream.mp3'
|
||||
},
|
||||
{
|
||||
id: 'canal-sur',
|
||||
name: 'Canal Sur Radio',
|
||||
url: 'https://rtva-live-radio.flumotion.com/rtva/csr.mp3'
|
||||
},
|
||||
{
|
||||
id: 'radio-andalucia',
|
||||
name: 'Radio Andalucía Información',
|
||||
url: 'https://rtva-live-radio.flumotion.com/rtva/rai.mp3'
|
||||
}
|
||||
];
|
||||
|
||||
const handleChange = (e) => {
|
||||
const selectedStream = streams.find(stream => stream.id === e.target.value);
|
||||
if (selectedStream) {
|
||||
onStreamChange(selectedStream);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="stream-selector-container" style={{
|
||||
margin: '20px auto',
|
||||
maxWidth: '400px',
|
||||
padding: '0 20px'
|
||||
}}>
|
||||
<div className="input-field">
|
||||
<select
|
||||
value={currentStream}
|
||||
onChange={handleChange}
|
||||
className="browser-default"
|
||||
style={{
|
||||
display: 'block',
|
||||
width: '100%',
|
||||
padding: '10px 15px',
|
||||
fontSize: '16px',
|
||||
borderRadius: '4px',
|
||||
border: '1px solid rgba(255, 255, 255, 0.3)',
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.1)',
|
||||
color: '#fff',
|
||||
cursor: 'pointer',
|
||||
outline: 'none',
|
||||
transition: 'all 0.3s ease'
|
||||
}}
|
||||
>
|
||||
{streams.map(stream => (
|
||||
<option
|
||||
key={stream.id}
|
||||
value={stream.id}
|
||||
style={{ backgroundColor: '#333', color: '#fff' }}
|
||||
>
|
||||
{stream.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<label style={{
|
||||
color: 'rgba(255, 255, 255, 0.7)',
|
||||
fontSize: '14px',
|
||||
marginTop: '5px',
|
||||
display: 'block'
|
||||
}}>
|
||||
Selecciona una emisora
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
StreamSelector.propTypes = {
|
||||
currentStream: PropTypes.string.isRequired,
|
||||
onStreamChange: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default StreamSelector;
|
||||
Referencia en una nueva incidencia
Block a user