Skip to content

Commit

Permalink
add PlayerPopup, add showTime to alerts
Browse files Browse the repository at this point in the history
  • Loading branch information
stCarolas committed Feb 6, 2024
1 parent dc91072 commit 5364583
Show file tree
Hide file tree
Showing 14 changed files with 169 additions and 78 deletions.
9 changes: 6 additions & 3 deletions src/components/ConfigurationPage/ConfigurationPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { WidgetsContext } from "./WidgetsContext";
import axios from "axios";
import { useLoaderData } from "react-router";
import { defaultSettings } from "./WidgetSettings";
import { log } from "../../logging";

const backgroundColor = (
<style
Expand Down Expand Up @@ -36,6 +37,7 @@ const types = [
{ name: "payments", description: "Payment History" },
{ name: "player-control", description: "Music Player Remote Control" },
{ name: "donation-timer", description: "Donation Timer" },
{ name: "player-popup", description: "Video Popup" },
];

export default function ConfigurationPage({}: {}) {
Expand Down Expand Up @@ -73,6 +75,7 @@ export default function ConfigurationPage({}: {}) {

widgets.forEach((it) => {
const settings = defaultSettings[it.type];
log.debug(`default settings for ${it.type} are ${JSON.stringify(settings)}`);
const mergedSettings = settings.properties.map((prop) => {
const value = it.config?.properties?.find((sameprop) => sameprop.name === prop.name)?.value;
const updatedProp = structuredClone(prop);
Expand All @@ -81,9 +84,9 @@ export default function ConfigurationPage({}: {}) {
}
return updatedProp;
});
if (it.config) {
it.config.properties = mergedSettings;
}
log.debug(`merged settings for ${it.type} are ${JSON.stringify(mergedSettings)}`);
it.config = it.config ?? {};
it.config.properties = mergedSettings;
widgetSettings.set(it.id, it.config);
});

Expand Down
10 changes: 1 addition & 9 deletions src/components/ConfigurationPage/WidgetConfiguration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,14 @@ interface WidgetConfigurationProps {

function getSettingsWidget(id: string, type: string, onChange: Function) {
switch (type) {
case "payments":
return <BaseSettings id={id} onChange={onChange} />;
case "media":
return <BaseSettings id={id} onChange={onChange} />;
case "player-info":
return <BaseSettings id={id} onChange={onChange} />;
case "player-control":
return <BaseSettings id={id} onChange={onChange} />;
case "payment-alerts":
return <PaymentAlertSettings id={id} onChange={onChange} />;
case "donaters-top-list":
return <DonatersTopListSettings id={id} onChange={onChange} />;
case "donation-timer":
return <DonationTimerSettings id={id} onChange={onChange} />;
default:
<></>;
return <BaseSettings id={id} onChange={onChange} />;
}
}

Expand Down
9 changes: 8 additions & 1 deletion src/components/ConfigurationPage/WidgetSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,14 @@ const defaultSettings = {
properties: [],
},
"player-popup": {
properties: [],
properties: [
{
name: "audioOnly",
type: "boolean",
value: false,
displayName: "Воспроизводить только звук",
}
],
},
payments: {
properties: [
Expand Down
1 change: 1 addition & 0 deletions src/components/ConfigurationPage/settings/BaseSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useContext } from "react";
import { WidgetsContext } from "../WidgetsContext";
import ColorPicker from "./ColorPicker";
import FontSelect from "./FontSelect";
import { log } from "../../../logging";

export default function BaseSettings({
id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ export default function PaymentAlertSettings({
value: null,
displayName: "Высота изображения в пикселях",
},
{
tab: "image",
name: "imageShowTime",
value: null,
displayName: "Сколько времени показывать изображение (сек)",
},
{
tab: "header",
name: "nicknameFont",
Expand Down
3 changes: 3 additions & 0 deletions src/components/MediaWidget/IPlayer.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { PlaylistController } from "./PlaylistController";
import { Song } from "./types";

interface IPlayer {
id: string;
play(song: Song): void;

playlistController: PlaylistController;
}

export { IPlayer };
15 changes: 11 additions & 4 deletions src/components/MediaWidget/MediaWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "bootstrap/dist/css/bootstrap.min.css";
import { useLoaderData, useNavigate } from "react-router";
import "./MediaWidget.css";
import { PlaylistController } from "./PlaylistController";
import { setupCommandListener } from "../../socket";
import { publish, setupCommandListener } from "../../socket";
import Menu from "../Menu/Menu";
import { PaymentPageConfig } from "./PaymentPageConfig";
import RequestsDisabledWarning from "./RequestsDisabledWarning";
Expand All @@ -31,9 +31,10 @@ export default function MediaWidget({}: {}) {
const [activeTab, setActiveTab] = useState(PLAYLIST_TYPE.REQUESTED);
const playlistController = useRef<PlaylistController>();
const [song, setSong] = useState<Song | null>(null);
const [isRemote, setIsRemote] = useState<boolean>(false);

useEffect(() => {
const playlistListener: IPlaylistChangesListener = {
const playlistListener = {
id: widgetId,
trigger(playlist: Playlist) {
log.debug(
Expand Down Expand Up @@ -77,12 +78,18 @@ export default function MediaWidget({}: {}) {
<RequestsDisabledWarning />
<div className="player-header">
<div className="song-title-container">{song?.title ?? ""}</div>
<VideoPopupToggler />
<VideoPopupToggler
onChange={() => {
publish(conf.topic.remoteplayer, { command: "stop" });
setIsRemote((old) => !old);
}}
/>
</div>
{song && playlistController.current && (
{playlistController.current && (
<VideoJSComponent
playlistController={playlistController.current}
song={song}
isRemote={isRemote}
/>
)}
<div className="playlist-controls">
Expand Down
5 changes: 5 additions & 0 deletions src/components/MediaWidget/PlaylistController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ export class PlaylistController {
this.handleNewRequestedSongEvent(song);
message.ack();
});
subscribe(widgetId, conf.topic.finishedmedia, (message) => {
const song = JSON.parse(message.body);
this.current.markListened(song.id);
message.ack();
});
}

handleNewRequestedSongEvent(song:Song){
Expand Down
80 changes: 56 additions & 24 deletions src/components/MediaWidget/VideoJSComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useLoaderData } from "react-router";
import ProgressBar from "./ProgressBar";
import VideoDuration from "./VideoDuration";
import { PlaylistController } from "./PlaylistController";
import { publish, subscribe } from "../../socket";
import { publish, subscribe, unsubscribe } from "../../socket";

let options: VideoJsPlayerOptions = {
autoplay: true,
Expand All @@ -31,9 +31,11 @@ enum PLAYER_STATE {
export default function VideoJSComponent({
song,
playlistController,
isRemote,
}: {
song: Song;
song: Song | null;
playlistController: PlaylistController;
isRemote: boolean;
}) {
const { conf, widgetId } = useLoaderData();
const videoRef = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -98,25 +100,33 @@ export default function VideoJSComponent({
}, [player]);

useEffect(() => {
subscribe(
widgetId,
conf.topic.playerCommands,
(message) => {
log.debug(`message: ${JSON.stringify(message)}`);
if (commandHandler.current){
commandHandler.current(message);
}
subscribe(widgetId, conf.topic.playerCommands, (message) => {
log.debug(`message: ${JSON.stringify(message)}`);
if (commandHandler.current) {
commandHandler.current(message);
}
);
});
return () => unsubscribe(widgetId, conf.topic.playerCommands);
}, [widgetId]);

useEffect(() => {
if (!isRemote || song === null) {
return;
}
log.debug(`sending song ${JSON.stringify(song)} to remote player`);
publish(conf.topic.remoteplayer, { command: "play", song: song });
}, [isRemote, song]);

function sendAlert(title: string) {
publish(conf.topic.player, {
title: title,
});
}

useEffect(() => {
if (isRemote || song === null) {
return;
}
log.debug("Creating new player instance");
log.debug(`playing song ${JSON.stringify(song)}`);

Expand All @@ -132,7 +142,9 @@ export default function VideoJSComponent({
player.on("play", () => {
log.debug("start playing");
setPlayerState(PLAYER_STATE.PLAYING);
sendAlert(song.title);
if (song) {
sendAlert(song.title);
}
});
player.on("pause", () => {
log.debug("pause player");
Expand All @@ -153,18 +165,20 @@ export default function VideoJSComponent({
return () => {
player.dispose();
};
}, [song]);
}, [song, isRemote]);

return (
<>
<div
className="video-player"
data-vjs-player
style={hideVideo ? { visibility: "hidden", height: "1px" } : {}}
>
<div ref={videoRef} />
</div>
<ProgressBar player={player} />
{!isRemote && song && (
<div
className="video-player"
data-vjs-player
style={hideVideo ? { visibility: "hidden", height: "1px" } : {}}
>
<div ref={videoRef} />
</div>
)}
{!isRemote && <ProgressBar player={player} />}
<div className="player-container">
<div className="video-controls">
<div className="video-buttons">
Expand All @@ -180,7 +194,17 @@ export default function VideoJSComponent({
<button
className="btn btn-outline-light"
disabled={song == null}
onClick={() => player.play()}
onClick={() => {
if (isRemote) {
publish(conf.topic.remoteplayer, {
command: "resume",
});
setPlayerState(PLAYER_STATE.PLAYING);
}
if (!isRemote) {
player.play();
}
}}
>
<span className="material-symbols-sharp">play_arrow</span>
</button>
Expand All @@ -190,7 +214,15 @@ export default function VideoJSComponent({
className="btn btn-outline-light"
disabled={song == null}
onClick={() => {
player.pause();
if (isRemote) {
publish(conf.topic.remoteplayer, {
command: "pause",
});
setPlayerState(PLAYER_STATE.PAUSED);
}
if (!isRemote) {
player.pause();
}
}}
>
<span className="material-symbols-sharp">pause</span>
Expand All @@ -205,7 +237,7 @@ export default function VideoJSComponent({
>
<span className="material-symbols-sharp">skip_next</span>
</button>
<VideoDuration player={player} />
{!isRemote && <VideoDuration player={player} />}
</div>
</div>
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/components/MediaWidget/VideoPopupToggler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ enum VIDEO_IMPL {
REMOTE,
}

export default function VideoPopupToggler({}) {
export default function VideoPopupToggler({ onChange }: { onChange: Function}) {
const [videoImpl, setVideoImpl] = useState<VIDEO_IMPL>(VIDEO_IMPL.EMBEDDED);
return (
<>
Expand All @@ -22,6 +22,7 @@ export default function VideoPopupToggler({}) {
if (videoImpl === VIDEO_IMPL.EMBEDDED) {
setVideoImpl(VIDEO_IMPL.REMOTE);
}
onChange();
}}
/>
<span className="videoImpl">{videoImpl === VIDEO_IMPL.REMOTE ? "Remote" : "Embedded"}</span>
Expand Down
Loading

0 comments on commit 5364583

Please sign in to comment.