Skip to content

Commit

Permalink
Camera Feed: Persist last accessed position or preset
Browse files Browse the repository at this point in the history
  • Loading branch information
rithviknishad committed Aug 14, 2024
1 parent 596cbba commit 351c479
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 14 deletions.
5 changes: 3 additions & 2 deletions src/Components/CameraFeed/CameraFeed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import FeedControls from "./FeedControls";
import FeedWatermark from "./FeedWatermark";
import useFullscreen from "../../Common/hooks/useFullscreen";
import useBreakpoints from "../../Common/hooks/useBreakpoints";
import { GetPresetsResponse } from "./routes";

interface Props {
children?: React.ReactNode;
Expand Down Expand Up @@ -66,7 +67,7 @@ export default function CameraFeed(props: Props) {
async function getPresets(cb: (presets: Record<string, number>) => void) {
const { res, data } = await props.operate({ type: "get_presets" });
if (res?.ok && data) {
cb((data as { result: Record<string, number> }).result);
cb((data as GetPresetsResponse).result);
}
}
getPresets(props.onCameraPresetsObtained);
Expand Down Expand Up @@ -125,9 +126,9 @@ export default function CameraFeed(props: Props) {
}}
onReset={resetStream}
onMove={async (data) => {
props.onMove?.();
setState("moving");
const { res } = await props.operate({ type: "relative_move", data });
props.onMove?.();
setTimeout(() => {
setState((state) => (state === "moving" ? undefined : state));
}, 4000);
Expand Down
20 changes: 18 additions & 2 deletions src/Components/CameraFeed/routes.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
import { Type } from "../../Redux/api";
import { OperationAction } from "./useOperateCamera";
import { OperationAction, PTZPayload } from "./useOperateCamera";

export type GetStatusResponse = {
result: {
position: PTZPayload;
moveStatus: {
panTilt: "IDLE" | "MOVING";
zoom: "IDLE" | "MOVING";
};
error: string;
utcTime: string;
};
};

export type GetPresetsResponse = {
result: Record<string, number>;
};

export const FeedRoutes = {
operateAsset: {
path: "/api/v1/asset/{id}/operate_assets/",
method: "POST",
TRes: Type<object>(),
TRes: Type<GetStatusResponse | GetPresetsResponse>(),
TBody: Type<{ action: OperationAction }>(),
},
} as const;
66 changes: 56 additions & 10 deletions src/Components/Facility/ConsultationDetails/ConsultationFeedTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ import ConfirmDialog from "../../Common/ConfirmDialog";
import useBreakpoints from "../../../Common/hooks/useBreakpoints";
import { Warn } from "../../../Utils/Notifications";
import { useTranslation } from "react-i18next";
import { GetStatusResponse } from "../../CameraFeed/routes";

export const ConsultationFeedTab = (props: ConsultationTabProps) => {
const { t } = useTranslation();
const authUser = useAuthUser();
const facility = useSlug("facility");
const bed = props.consultationData.current_bed?.bed_object;
const feedStateSessionKey = getFeedStateKey(props.consultationId);

const [asset, setAsset] = useState<AssetData>();
const [preset, setPreset] = useState<AssetBedModel>();
Expand Down Expand Up @@ -65,11 +67,23 @@ export const ConsultationFeedTab = (props: ConsultationTabProps) => {
obj.meta.type !== "boundary",
);

const lastPresetId = sessionStorage.getItem(
getFeedPresetKey(props.consultationId),
);
const lastStateJSON = sessionStorage.getItem(feedStateSessionKey);
const preset =
presets.find((obj) => obj.id === lastPresetId) ?? presets[0];
(() => {
if (lastStateJSON) {
const lastState = JSON.parse(lastStateJSON) as LastFeedState;
if (lastState.type === "preset") {
return presets.find((obj) => obj.id === lastState.value);
}
if (lastState.type === "position") {
return {
...presets[0],
id: "",
meta: { ...presets[0].meta, position: lastState.value },
};
}
}
})() ?? presets[0];

if (preset) {
setPreset(preset);
Expand Down Expand Up @@ -112,9 +126,15 @@ export const ConsultationFeedTab = (props: ConsultationTabProps) => {
}, [!!bed, loading, !!asset, divRef.current]);

useEffect(() => {
const feedPresetKey = getFeedPresetKey(props.consultationId);
if (preset) {
sessionStorage.setItem(feedPresetKey, preset.id);
const feedPresetKey = getFeedStateKey(props.consultationId);
if (preset?.id) {
sessionStorage.setItem(
feedPresetKey,
JSON.stringify({
type: "preset",
value: preset.id,
} satisfies LastAccessedPreset),
);
}
}, [preset, props.consultationId]);

Expand Down Expand Up @@ -148,7 +168,21 @@ export const ConsultationFeedTab = (props: ConsultationTabProps) => {
key={key}
asset={asset}
preset={preset?.meta.position}
onMove={() => setHasMoved(true)}
onMove={() => {
setHasMoved(true);
setTimeout(async () => {
const { data } = await operate({ type: "get_status" });
if (data) {
sessionStorage.setItem(
feedStateSessionKey,
JSON.stringify({
type: "position",
value: (data as GetStatusResponse).result.position,
} satisfies LastAccessedPosition),
);
}
}, 3000);
}}
operate={operate}
onStreamError={() => {
triggerGoal("Camera Feed Viewed", {
Expand Down Expand Up @@ -226,6 +260,18 @@ export const ConsultationFeedTab = (props: ConsultationTabProps) => {
);
};

const getFeedPresetKey = (consultationId: string) => {
return `encounterFeedPreset[${consultationId}]`;
type LastAccessedPreset = {
type: "preset";
value: string;
};

type LastAccessedPosition = {
type: "position";
value: PTZPayload;
};

type LastFeedState = LastAccessedPosition | LastAccessedPreset;

const getFeedStateKey = (consultationId: string) => {
return `encounterFeedState[${consultationId}]`;
};

0 comments on commit 351c479

Please sign in to comment.