Initial commit
This commit is contained in:
26
discord-bot/client/src/components/CurrentSong.tsx
Normal file
26
discord-bot/client/src/components/CurrentSong.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import { useWebSocket } from "../contexts/useWebSocket";
|
||||
import { Slider } from "./Slider";
|
||||
|
||||
export const CurrentSong = () => {
|
||||
const { ws, playbackInfo, sendMessage } = useWebSocket();
|
||||
return (
|
||||
<>
|
||||
{playbackInfo && (
|
||||
<div className="rounded border p-3 my-5 bg-body-tertiary bg-opacity-50">
|
||||
<h2>Playing Song</h2>
|
||||
<h5>{playbackInfo.file_name}</h5>
|
||||
{ws && (
|
||||
<Slider
|
||||
min={0}
|
||||
max={playbackInfo.duration}
|
||||
current={playbackInfo.current_position}
|
||||
onChange={(v) => {
|
||||
sendMessage({ action: "set_playback", position: v });
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
22
discord-bot/client/src/components/PlaybackInfo.tsx
Normal file
22
discord-bot/client/src/components/PlaybackInfo.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import React from "react";
|
||||
import { useInfoTask } from "./useInfoTask";
|
||||
import { useWebSocket } from "../contexts/useWebSocket";
|
||||
|
||||
export const PlaybackInfo: React.FC = () => {
|
||||
const { ws, error, message, botStatus } = useWebSocket();
|
||||
|
||||
useInfoTask(ws);
|
||||
|
||||
return (
|
||||
<div className="row justify-content-end my-3">
|
||||
<div className="col-auto">
|
||||
<div className="border rounded-3 p-3 bg-secondary-subtle">
|
||||
<h5 className="text-center">Status Messages</h5>
|
||||
{botStatus && <div>status: {botStatus}</div>}
|
||||
{error && <div>error: {error}</div>}
|
||||
{message && <div>message: {message}</div>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
38
discord-bot/client/src/components/Slider.scss
Normal file
38
discord-bot/client/src/components/Slider.scss
Normal file
@@ -0,0 +1,38 @@
|
||||
@import "../../node_modules/bootstrap/scss/bootstrap.scss";
|
||||
|
||||
:root {
|
||||
--slider-color: var(--bs-primary);
|
||||
--slider-background-color: var(--bs-primary-bg-subtle);
|
||||
}
|
||||
|
||||
|
||||
.slider {
|
||||
height: 15px;
|
||||
border-radius: 5px;
|
||||
background: var(--slider-background-color);
|
||||
outline: none;
|
||||
transition: opacity 0.2s;
|
||||
opacity: .5;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
border-radius: 50%;
|
||||
background: var(--slider-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&::-moz-range-thumb {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
border-radius: 50%;
|
||||
background: var(--slider-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
44
discord-bot/client/src/components/Slider.tsx
Normal file
44
discord-bot/client/src/components/Slider.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import { ChangeEvent, FC, useEffect, useState } from "react";
|
||||
import "./Slider.scss";
|
||||
|
||||
interface SliderProps {
|
||||
min: number;
|
||||
max: number;
|
||||
current: number;
|
||||
onChange: (value: number) => void;
|
||||
}
|
||||
export const Slider: FC<SliderProps> = ({ min, max, current, onChange }) => {
|
||||
const [localValue, setLocalValue] = useState<number>(current);
|
||||
const [isDragging, setIsDragging] = useState<boolean>(false);
|
||||
|
||||
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
setLocalValue(Number(e.target.value));
|
||||
};
|
||||
|
||||
const handleMouseDown = () => {
|
||||
setIsDragging(true);
|
||||
};
|
||||
|
||||
const handleMouseUp = () => {
|
||||
setIsDragging(false);
|
||||
onChange(localValue);
|
||||
};
|
||||
useEffect(() => {
|
||||
if (!isDragging) setLocalValue(current);
|
||||
}, [current, isDragging]);
|
||||
|
||||
return (
|
||||
<div className="w-100">
|
||||
<input
|
||||
type="range"
|
||||
min={min}
|
||||
max={max}
|
||||
value={localValue}
|
||||
onChange={handleChange}
|
||||
onMouseDown={handleMouseDown}
|
||||
onMouseUp={handleMouseUp}
|
||||
className="slider w-100"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
8
discord-bot/client/src/components/SongQueue.module.scss
Normal file
8
discord-bot/client/src/components/SongQueue.module.scss
Normal file
@@ -0,0 +1,8 @@
|
||||
@import "../../node_modules/bootstrap/scss/bootstrap.scss";
|
||||
|
||||
.songListItem {
|
||||
height: 3em;
|
||||
&:hover {
|
||||
@extend .bg-dark-subtle;
|
||||
}
|
||||
}
|
||||
63
discord-bot/client/src/components/SongQueue.tsx
Normal file
63
discord-bot/client/src/components/SongQueue.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
import { useWebSocket } from "../contexts/useWebSocket";
|
||||
import classes from "./SongQueue.module.scss";
|
||||
|
||||
export const SongQueue = () => {
|
||||
const { songQueue, sendMessage } = useWebSocket();
|
||||
|
||||
return (
|
||||
<div>
|
||||
{songQueue && (
|
||||
<div>
|
||||
<ul className="list-group">
|
||||
{songQueue.song_file_list.map((s, i) => {
|
||||
const isCurrent = i === songQueue.position;
|
||||
return (
|
||||
<li
|
||||
key={i}
|
||||
className={` list-group-item m-0 p-0 ${
|
||||
isCurrent && "bg-primary-subtle"
|
||||
} ${classes.songListItem}`}
|
||||
>
|
||||
<div className="row h-100">
|
||||
<div className="col-1 text-end my-auto">
|
||||
{!isCurrent && (
|
||||
<i
|
||||
className="bi bi-play-circle text-primary fs-3 "
|
||||
role="button"
|
||||
onClick={() => {
|
||||
sendMessage({
|
||||
action: "set_position",
|
||||
position: i,
|
||||
});
|
||||
}}
|
||||
></i>
|
||||
)}
|
||||
{isCurrent && (
|
||||
<i
|
||||
className="bi bi-pause-circle text-primary fs-3 "
|
||||
role="button"
|
||||
onClick={() => {
|
||||
// send pause message
|
||||
// sendMessage({
|
||||
// action: "set_position",
|
||||
// position: i,
|
||||
// });
|
||||
}}
|
||||
></i>
|
||||
)}
|
||||
</div>
|
||||
<div className="col my-auto">
|
||||
{s.filename
|
||||
.substring(s.filename.lastIndexOf("/") + 1)
|
||||
.replace(".mp3", "")}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
17
discord-bot/client/src/components/useInfoTask.ts
Normal file
17
discord-bot/client/src/components/useInfoTask.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { useEffect } from "react";
|
||||
|
||||
const updateInterval = 100;
|
||||
|
||||
const getPlaybackInfo = (ws: WebSocket) => {
|
||||
ws.send(JSON.stringify({ action: "get_playback_info" }));
|
||||
};
|
||||
export const useInfoTask = (websocket?: WebSocket) => {
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
if(websocket)
|
||||
getPlaybackInfo(websocket);
|
||||
}, updateInterval);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [websocket]);
|
||||
};
|
||||
Reference in New Issue
Block a user