feat: use api for initial information

This commit is contained in:
Ante Brähler
2024-11-20 22:24:07 +00:00
parent 5a0253abe2
commit 938b2bba87
6 changed files with 62 additions and 34 deletions

View File

@@ -4,7 +4,7 @@ const Channel = require('../models/Channel');
class ChannelService {
constructor() {
this.channels = [new Channel('DEFAULT_CHANNEL', process.env.DEFAULT_CHANNEL_URL, "https://images.unsplash.com/photo-1534308143481-c55f00be8bd7?w=64&h=64&fit=crop&crop=faces")];
this.channels = [new Channel('DEFAULT_CHANNEL', process.env.DEFAULT_CHANNEL_URL, "https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/Das_Erste-Logo_klein.svg/768px-Das_Erste-Logo_klein.svg.png")];
this.currentChannel = this.channels[0];
}

View File

@@ -6,35 +6,11 @@ import Chat from './components/chat/Chat';
import AddChannelModal from './components/AddChannelModal';
import { Channel } from './types';
import socketService from './services/SocketService';
import apiService from './services/ApiService';
function App() {
const [channels, setChannels] = useState<Channel[]>([
{
id: 100,
name: 'Das Erste',
url: 'https://mcdn.daserste.de/daserste/de/master1080p5000.m3u8',
avatar: 'https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/Das_Erste-Logo_klein.svg/768px-Das_Erste-Logo_klein.svg.png'
},
{
id: 200,
name: 'ZDF',
url: 'https://mcdn.daserste.de/daserste/de/master1080p5000.m3u8',
avatar: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/ZDF_logo.svg/2560px-ZDF_logo.svg.png'
},
{
id: 300,
name: 'Creative Studio',
url: 'https://mcdn.daserste.de/daserste/de/master1080p5000.m3u8',
avatar: 'https://images.unsplash.com/photo-1534308143481-c55f00be8bd7?w=64&h=64&fit=crop&crop=faces'
},
{
id: 400,
name: 'Creative Studio',
url: 'https://mcdn.daserste.de/daserste/de/master1080p5000.m3u8',
avatar: 'https://images.unsplash.com/photo-1534308143481-c55f00be8bd7?w=64&h=64&fit=crop&crop=faces'
},
]);
const [selectedChannel, setSelectedChannel] = useState<Channel>(channels[0]);
const [channels, setChannels] = useState<Channel[]>([]);
const [selectedChannel, setSelectedChannel] = useState<Channel | null>(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const [searchQuery, setSearchQuery] = useState('');
@@ -42,6 +18,17 @@ function App() {
useEffect(() => {
apiService
.request<Channel[]>('/channels/', 'GET')
.then((data) => setChannels(data))
.catch((error) => console.error('Error loading channels:', error));
apiService
.request<Channel | null>('/channels/current', 'GET')
.then((data) => setSelectedChannel(data))
.catch((error) => console.error('Error loading current channel:', error));
socketService.connect();
console.log('Subscribing to events');

View File

@@ -4,7 +4,7 @@ import socketService from '../services/SocketService';
interface ChannelListProps {
channels: Channel[];
selectedChannel: Channel;
selectedChannel: Channel | null;
}
function ChannelList({ channels, selectedChannel}: ChannelListProps) {
@@ -20,7 +20,7 @@ function ChannelList({ channels, selectedChannel}: ChannelListProps) {
key={channel.id}
onClick={() => onSelectChannel(channel)}
className={`group relative p-2 rounded-lg transition-all ${
selectedChannel.id === channel.id
selectedChannel?.id === channel.id
? 'bg-blue-500 bg-opacity-20 ring-2 ring-blue-500'
: 'hover:bg-gray-700'
}`}

View File

@@ -3,7 +3,7 @@ import Hls from 'hls.js';
import { Channel } from '../types';
interface VideoPlayerProps {
channel: Channel;
channel: Channel | null;
}
function VideoPlayer({ channel }: VideoPlayerProps) {
@@ -11,7 +11,7 @@ function VideoPlayer({ channel }: VideoPlayerProps) {
const hlsRef = useRef<Hls | null>(null);
useEffect(() => {
if (!videoRef.current) return;
if (!videoRef.current || !channel?.url) return;
const video = videoRef.current;
if (Hls.isSupported()) {
@@ -84,7 +84,7 @@ function VideoPlayer({ channel }: VideoPlayerProps) {
hlsRef.current.destroy();
}
};
}, [channel.url]);
}, [channel?.url]);
const handleVideoClick = (event: React.MouseEvent<HTMLVideoElement>) => {
if (videoRef.current?.muted) {

View File

@@ -0,0 +1,41 @@
const API_BASE_URL = import.meta.env.ITE_BACKEND_URL || '';
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
const apiService = {
/**
* Execute API request
* @param path - Path (e.g. "/channels/")
* @param method - HTTP-Method (GET, POST, etc.)
* @param body - The request body (e.g. POST)
* @returns Ein Promise with the parsed JSON response to class T
*/
async request<T>(path: string, method: HttpMethod = 'GET', body?: unknown): Promise<T> {
try {
const options: RequestInit = {
method,
headers: {
'Content-Type': 'application/json',
},
};
if (body) {
options.body = JSON.stringify(body);
}
const response = await fetch(`${API_BASE_URL}${path}`, options);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = (await response.json()) as T;
return data;
} catch (error) {
console.error(`Error in API request to ${path}:`, error);
throw error;
}
},
};
export default apiService;

View File

@@ -11,7 +11,7 @@ class SocketService {
if (this.socket?.connected) return;
console.log('Connecting to WebSocket server');
this.socket = io(import.meta.env.BACKEND_WS_URL);
this.socket = io(import.meta.env.ITE_BACKEND_URL);
this.socket.on('connect', () => {
console.log('Connected to WebSocket server');