Split out navbar so that it doesn't rerender everything so much.
This commit is contained in:
parent
9613363e20
commit
81d443123a
1 changed files with 169 additions and 121 deletions
|
@ -1,5 +1,5 @@
|
|||
import React, { useRef, useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { shallowEqual, useDispatch, useSelector } from "react-redux";
|
||||
import Clock from "react-live-clock";
|
||||
import Stopwatch from "react-stopwatch";
|
||||
|
||||
|
@ -161,31 +161,6 @@ export function NavBarMyRadio() {
|
|||
}
|
||||
|
||||
export function NavBarMain() {
|
||||
const dispatch = useDispatch();
|
||||
const broadcastState = useSelector((state: RootState) => state.broadcast);
|
||||
const settings = useSelector((state: RootState) => state.settings);
|
||||
const playerState = useSelector((state: RootState) => state.mixer.players);
|
||||
|
||||
let playerPFLs: boolean[] = [];
|
||||
playerState.forEach((player) => {
|
||||
playerPFLs.push(player.pfl);
|
||||
});
|
||||
const isPFL = useSelector((state) => playerPFLs).some((x) => x === true);
|
||||
|
||||
const [connectButtonAnimating, setConnectButtonAnimating] = useState(false);
|
||||
|
||||
const prevRegistrationStage = useRef(broadcastState.stage);
|
||||
useEffect(() => {
|
||||
if (broadcastState.stage !== prevRegistrationStage.current) {
|
||||
setConnectButtonAnimating(false);
|
||||
}
|
||||
prevRegistrationStage.current = broadcastState.stage;
|
||||
}, [broadcastState.stage]);
|
||||
|
||||
const { planSaveError, planSaving } = useSelector(
|
||||
(state: RootState) => state.showplan
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ul className="nav navbar-nav navbar-left">
|
||||
|
@ -207,115 +182,188 @@ export function NavBarMain() {
|
|||
timezone={"europe/london"}
|
||||
/>
|
||||
</li>
|
||||
{planSaving && (
|
||||
<li className="btn rounded-0 py-2 nav-item alert-info">
|
||||
<FaSpinner className="nav-spin mb-1" /> Saving show plan...
|
||||
</li>
|
||||
)}
|
||||
{planSaveError && (
|
||||
<li className="btn rounded-0 py-2 nav-item alert-danger">
|
||||
<FaExclamationTriangle className="p-0 mr-1" />
|
||||
{planSaveError}
|
||||
</li>
|
||||
)}
|
||||
<SavingAlert />
|
||||
</ul>
|
||||
|
||||
<ul className="nav navbar-nav navbar-right mr-0 pr-0">
|
||||
<li className="nav-item" style={{ color: "white" }}>
|
||||
<div className="nav-link">
|
||||
<b>{nicifyConnectionState(broadcastState.connectionState)}</b>
|
||||
</div>
|
||||
<RegisterButton />
|
||||
<RecordingButton />
|
||||
<OptionsButton />
|
||||
<MeterBridge />
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
}
|
||||
function SavingAlert() {
|
||||
const { planSaveError, planSaving } = useSelector(
|
||||
(state: RootState) => state.showplan
|
||||
);
|
||||
return (
|
||||
<>
|
||||
{planSaving && (
|
||||
<li className="btn rounded-0 py-2 nav-item alert-info">
|
||||
<FaSpinner className="nav-spin mb-1" /> Saving show plan...
|
||||
</li>
|
||||
)}
|
||||
{planSaveError && (
|
||||
<li className="btn rounded-0 py-2 nav-item alert-danger">
|
||||
<FaExclamationTriangle className="p-0 mr-1" />
|
||||
{planSaveError}
|
||||
</li>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
function RegisterButton() {
|
||||
const dispatch = useDispatch();
|
||||
const broadcastState = useSelector((state: RootState) => state.broadcast);
|
||||
const [connectButtonAnimating, setConnectButtonAnimating] = useState(false);
|
||||
|
||||
const prevRegistrationStage = useRef(broadcastState.stage);
|
||||
useEffect(() => {
|
||||
if (broadcastState.stage !== prevRegistrationStage.current) {
|
||||
setConnectButtonAnimating(false);
|
||||
}
|
||||
prevRegistrationStage.current = broadcastState.stage;
|
||||
}, [broadcastState.stage]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<li className="nav-item" style={{ color: "white" }}>
|
||||
<div className="nav-link">
|
||||
<b>{nicifyConnectionState(broadcastState.connectionState)}</b>
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
className="btn btn-outline-light rounded-0 pt-2 pb-1 nav-item nav-link connect"
|
||||
onClick={() => {
|
||||
setConnectButtonAnimating(true);
|
||||
switch (broadcastState.stage) {
|
||||
case "NOT_REGISTERED":
|
||||
dispatch(BroadcastState.goOnAir());
|
||||
break;
|
||||
case "REGISTERED":
|
||||
dispatch(BroadcastState.cancelTimeslot());
|
||||
break;
|
||||
}
|
||||
}}
|
||||
>
|
||||
{connectButtonAnimating ? (
|
||||
<>
|
||||
<FaBroadcastTower size={17} className="mr-2" />
|
||||
<FaSpinner size={17} className="nav-spin mr-2" />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<FaBroadcastTower size={17} className="mr-2" />
|
||||
{broadcastState.stage === "NOT_REGISTERED" && "Register"}
|
||||
{broadcastState.stage === "REGISTERED" && "Stop"}
|
||||
</>
|
||||
)}
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
function RecordingButton() {
|
||||
const recordingState = useSelector(
|
||||
(state: RootState) => state.broadcast.recordingState
|
||||
);
|
||||
const enableRecording = useSelector(
|
||||
(state: RootState) => state.settings.enableRecording
|
||||
);
|
||||
const dispatch = useDispatch();
|
||||
return (
|
||||
<>
|
||||
{enableRecording && (
|
||||
<li
|
||||
className="btn btn-outline-light rounded-0 pt-2 pb-1 nav-item nav-link connect"
|
||||
onClick={() => {
|
||||
setConnectButtonAnimating(true);
|
||||
switch (broadcastState.stage) {
|
||||
case "NOT_REGISTERED":
|
||||
dispatch(BroadcastState.goOnAir());
|
||||
break;
|
||||
case "REGISTERED":
|
||||
dispatch(BroadcastState.cancelTimeslot());
|
||||
break;
|
||||
}
|
||||
}}
|
||||
className={
|
||||
"btn rounded-0 pt-2 pb-1 nav-item nav-link " +
|
||||
(recordingState === "CONNECTED"
|
||||
? "btn-outline-danger active"
|
||||
: "btn-outline-light")
|
||||
}
|
||||
onClick={() =>
|
||||
dispatch(
|
||||
recordingState === "NOT_CONNECTED"
|
||||
? BroadcastState.startRecording()
|
||||
: BroadcastState.stopRecording()
|
||||
)
|
||||
}
|
||||
>
|
||||
{connectButtonAnimating ? (
|
||||
<>
|
||||
<FaBroadcastTower size={17} className="mr-2" />
|
||||
<FaSpinner size={17} className="nav-spin mr-2" />
|
||||
</>
|
||||
<FaCircle
|
||||
size={17}
|
||||
className={
|
||||
recordingState === "CONNECTED" ? "rec-blink" : "rec-stop"
|
||||
}
|
||||
/>{" "}
|
||||
{recordingState === "CONNECTED" ? (
|
||||
<Stopwatch
|
||||
seconds={0}
|
||||
minutes={0}
|
||||
hours={0}
|
||||
render={({ formatted }) => {
|
||||
return <span>{formatted}</span>;
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<FaBroadcastTower size={17} className="mr-2" />
|
||||
{broadcastState.stage === "NOT_REGISTERED" && "Register"}
|
||||
{broadcastState.stage === "REGISTERED" && "Stop"}
|
||||
</>
|
||||
"Record"
|
||||
)}
|
||||
</li>
|
||||
{settings.enableRecording && (
|
||||
<li
|
||||
className={
|
||||
"btn rounded-0 pt-2 pb-1 nav-item nav-link " +
|
||||
(broadcastState.recordingState === "CONNECTED"
|
||||
? "btn-outline-danger active"
|
||||
: "btn-outline-light")
|
||||
}
|
||||
onClick={() =>
|
||||
dispatch(
|
||||
broadcastState.recordingState === "NOT_CONNECTED"
|
||||
? BroadcastState.startRecording()
|
||||
: BroadcastState.stopRecording()
|
||||
)
|
||||
}
|
||||
>
|
||||
<FaCircle
|
||||
size={17}
|
||||
className={
|
||||
broadcastState.recordingState === "CONNECTED"
|
||||
? "rec-blink"
|
||||
: "rec-stop"
|
||||
}
|
||||
/>{" "}
|
||||
{broadcastState.recordingState === "CONNECTED" ? (
|
||||
<Stopwatch
|
||||
seconds={0}
|
||||
minutes={0}
|
||||
hours={0}
|
||||
render={({ formatted }) => {
|
||||
return <span>{formatted}</span>;
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
"Record"
|
||||
)}
|
||||
</li>
|
||||
)}
|
||||
<li
|
||||
className="btn btn-outline-light rounded-0 pt-2 pb-1 nav-item nav-link"
|
||||
onClick={() => dispatch(OptionsMenuState.open())}
|
||||
>
|
||||
<FaCog size={17} /> Options
|
||||
</li>
|
||||
{settings.proMode && isPFL && (
|
||||
<li
|
||||
className="btn btn-danger rounded-0 pt-2 pb-1 nav-item nav-link clear-pfl"
|
||||
onClick={() => dispatch(setChannelPFL(-1, false))}
|
||||
>
|
||||
<FaHeadphonesAlt size={17} /> Clear PFL
|
||||
</li>
|
||||
)}
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
function OptionsButton() {
|
||||
const dispatch = useDispatch();
|
||||
return (
|
||||
<li
|
||||
className="btn btn-outline-light rounded-0 pt-2 pb-1 nav-item nav-link"
|
||||
onClick={() => dispatch(OptionsMenuState.open())}
|
||||
>
|
||||
<FaCog size={17} /> Options
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
<li className={"nav-item px-2 nav-vu" + (isPFL ? " pfl-live" : "")}>
|
||||
function MeterBridge() {
|
||||
const dispatch = useDispatch();
|
||||
const proMode = useSelector((state: RootState) => state.settings.proMode);
|
||||
const playerPFLs = useSelector(
|
||||
(state: RootState) => state.mixer.players.map((x) => x.pfl),
|
||||
shallowEqual
|
||||
);
|
||||
const isPFL = useSelector((state) => playerPFLs).some((x) => x === true);
|
||||
|
||||
return (
|
||||
<>
|
||||
{proMode && isPFL && (
|
||||
<li
|
||||
className="btn btn-danger rounded-0 pt-2 pb-1 nav-item nav-link clear-pfl"
|
||||
onClick={() => dispatch(setChannelPFL(-1, false))}
|
||||
>
|
||||
<FaHeadphonesAlt size={17} /> Clear PFL
|
||||
</li>
|
||||
)}
|
||||
|
||||
<li className={"nav-item px-2 nav-vu" + (isPFL ? " pfl-live" : "")}>
|
||||
{isPFL && (
|
||||
<VUMeter
|
||||
width={235}
|
||||
height={isPFL ? 34 : 40}
|
||||
source={isPFL ? "pfl" : "master"}
|
||||
height={34}
|
||||
source="pfl"
|
||||
range={[-40, 3]}
|
||||
stereo={true}
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
)}
|
||||
{!isPFL && (
|
||||
<VUMeter
|
||||
width={235}
|
||||
height={40}
|
||||
source="master"
|
||||
range={[-40, 3]}
|
||||
stereo={true}
|
||||
/>
|
||||
)}
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue