Skip to content

Commit

Permalink
chore: clean up production-line component
Browse files Browse the repository at this point in the history
  • Loading branch information
martinstark committed Apr 17, 2024
1 parent 21701d9 commit d7a9271
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 71 deletions.
106 changes: 35 additions & 71 deletions src/components/production-line/production-line.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,19 @@ import { useRtcConnection } from "./use-rtc-connection.ts";
import { useEstablishSession } from "./use-establish-session.ts";
import { ActionButton } from "../landing-page/form-elements.tsx";
import { UserList } from "./user-list.tsx";
import { API } from "../../api/api.ts";
import { noop } from "../../helpers.ts";
import { MicMuted, MicUnmuted } from "../../assets/icons/icon.tsx";
import { Spinner } from "../loader/loader.tsx";
import { TLine, TProduction } from "./types.ts";
import { DisplayContainerHeader } from "../landing-page/display-container-header.tsx";
import { DisplayContainer, FlexContainer } from "../generic-components.ts";
import { useHeartbeat } from "./use-heartbeat.ts";
import { JoinProduction } from "../landing-page/join-production.tsx";
import { useDeviceLabels } from "./use-device-labels.ts";
import { useLineHotkeys } from "./use-line-hotkeys.ts";
import { isMobile } from "../../bowser.ts";
import { useLinePolling } from "./use-line-polling.ts";
import { useFetchProduction } from "../landing-page/use-fetch-production.ts";
import { useIsLoading } from "./use-is-loading.ts";
import { useCheckBadLineData } from "./use-check-bad-line-data.ts";

const TempDiv = styled.div`
padding: 1rem 0;
Expand Down Expand Up @@ -56,10 +57,6 @@ export const ProductionLine: FC = () => {
const [{ joinProductionOptions }, dispatch] = useGlobalState();
const navigate = useNavigate();
const [isInputMuted, setIsInputMuted] = useState(true);
const [line, setLine] = useState<TLine | null>(null);

const [loading, setLoading] = useState<boolean>(true);
const [production, setProduction] = useState<TProduction | null>(null);

const inputAudioStream = useAudioInput({
inputId: joinProductionOptions?.audioinput ?? null,
Expand All @@ -72,12 +69,21 @@ export const ProductionLine: FC = () => {
// eslint-disable-next-line no-param-reassign
t.enabled = !mute;
setIsInputMuted(mute);
console.log("input audio enabled", t.enabled);
});
}
},
[inputAudioStream]
);

const exit = useCallback(() => {
dispatch({
type: "UPDATE_JOIN_PRODUCTION_OPTIONS",
payload: null,
});
navigate("/");
}, [dispatch, navigate]);

useLineHotkeys({
muteInput,
isInputMuted,
Expand All @@ -95,80 +101,38 @@ export const ProductionLine: FC = () => {
sessionId,
});

// Participant list, TODO extract hook to separate file
useEffect(() => {
if (!joinProductionOptions) return noop;
const line = useLinePolling({ joinProductionOptions });

const productionId = parseInt(joinProductionOptions.productionId, 10);
const lineId = parseInt(joinProductionOptions.lineId, 10);

const interval = window.setInterval(() => {
API.fetchProductionLine(productionId, lineId)
.then((l) => setLine(l))
.catch(console.error);
}, 1000);

return () => {
window.clearInterval(interval);
};
}, [joinProductionOptions]);

useEffect(() => {
if (!joinProductionOptions) return;

const productionId = parseInt(joinProductionOptions.productionId, 10);

API.fetchProduction(productionId)
.then((p) => {
setProduction(p);
})
.catch((e) => {
dispatch({
type: "ERROR",
payload:
e instanceof Error ? e : new Error("Error fetching production."),
});
});
}, [dispatch, joinProductionOptions]);
const { production, error: fetchProductionError } = useFetchProduction(
joinProductionOptions
? parseInt(joinProductionOptions.productionId, 10)
: null
);

useEffect(() => {
if (connectionState === "connected") {
setLoading(false);
}
// TODO add handling for `connectionState === "failed"`
}, [connectionState]);

useHeartbeat({ sessionId });
if (!fetchProductionError) return;

const exit = () => {
dispatch({
type: "UPDATE_JOIN_PRODUCTION_OPTIONS",
payload: null,
type: "ERROR",
payload:
fetchProductionError instanceof Error
? fetchProductionError
: new Error("Error fetching production."),
});
navigate("/");
};

const deviceLabels = useDeviceLabels({ joinProductionOptions });

// Check if we have what's needed to join a production line
if (!joinProductionOptions) {
const pidIsNan = Number.isNaN(
paramProductionId && parseInt(paramProductionId, 10)
);
}, [dispatch, fetchProductionError]);

const lidIsNan = Number.isNaN(paramLineId && parseInt(paramLineId, 10));
const loading = useIsLoading({ connectionState });

if (pidIsNan || lidIsNan) {
// Someone entered a production id in the URL that's not a number
useHeartbeat({ sessionId });

const errorString = `Bad URL. ${pidIsNan ? "Production ID is not a number." : ""} ${lidIsNan ? "Line ID is not a number." : ""}`;
const deviceLabels = useDeviceLabels({ joinProductionOptions });

dispatch({
type: "ERROR",
payload: new Error(errorString),
});
}
}
useCheckBadLineData({
joinProductionOptions,
paramLineId,
paramProductionId,
dispatch,
});

// TODO detect if browser back button is pressed and run exit();
return (
Expand Down
38 changes: 38 additions & 0 deletions src/components/production-line/use-check-bad-line-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Dispatch, useEffect } from "react";
import { TJoinProductionOptions } from "./types.ts";
import { TGlobalStateAction } from "../../global-state/global-state-actions.ts";

type TProps = {
joinProductionOptions: TJoinProductionOptions | null;
paramProductionId: string | undefined;
paramLineId: string | undefined;
dispatch: Dispatch<TGlobalStateAction>;
};

export const useCheckBadLineData = ({
joinProductionOptions,
paramProductionId,
paramLineId,
dispatch,
}: TProps) => {
useEffect(() => {
if (!joinProductionOptions) {
const pidIsNan = Number.isNaN(
paramProductionId && parseInt(paramProductionId, 10)
);

const lidIsNan = Number.isNaN(paramLineId && parseInt(paramLineId, 10));

if (pidIsNan || lidIsNan) {
// Someone entered a production id in the URL that's not a number

const errorString = `Bad URL. ${pidIsNan ? "Production ID is not a number." : ""} ${lidIsNan ? "Line ID is not a number." : ""}`;

dispatch({
type: "ERROR",
payload: new Error(errorString),
});
}
}
}, [paramProductionId, paramLineId, joinProductionOptions, dispatch]);
};
18 changes: 18 additions & 0 deletions src/components/production-line/use-is-loading.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useEffect, useState } from "react";

type TProps = {
connectionState: string | null;
};

export const useIsLoading = ({ connectionState }: TProps) => {
const [loading, setLoading] = useState<boolean>(true);

useEffect(() => {
if (connectionState === "connected") {
setLoading(false);
}
// TODO add handling for `connectionState === "failed"`
}, [connectionState]);

return loading;
};
30 changes: 30 additions & 0 deletions src/components/production-line/use-line-polling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useEffect, useState } from "react";
import { noop } from "../../helpers.ts";
import { API } from "../../api/api.ts";
import { TJoinProductionOptions, TLine } from "./types.ts";

type TProps = {
joinProductionOptions: TJoinProductionOptions | null;
};

export const useLinePolling = ({ joinProductionOptions }: TProps) => {
const [line, setLine] = useState<TLine | null>(null);
useEffect(() => {
if (!joinProductionOptions) return noop;

const productionId = parseInt(joinProductionOptions.productionId, 10);
const lineId = parseInt(joinProductionOptions.lineId, 10);

const interval = window.setInterval(() => {
API.fetchProductionLine(productionId, lineId)
.then((l) => setLine(l))
.catch(console.error);
}, 1000);

return () => {
window.clearInterval(interval);
};
}, [joinProductionOptions]);

return line;
};

0 comments on commit d7a9271

Please sign in to comment.