Added Pilot Filter functionality
This commit is contained in:
@@ -2,10 +2,12 @@
|
||||
import { useLeftMenuStore } from "_store/leftMenuStore";
|
||||
import { cn } from "@repo/shared-components";
|
||||
import { SettingsIcon } from "lucide-react";
|
||||
import { usePilotConnectionStore } from "_store/pilot/connectionStore";
|
||||
|
||||
export const SettingsBoard = () => {
|
||||
const { setSituationTabOpen, situationTabOpen } = useLeftMenuStore();
|
||||
|
||||
const { followOwnAircraft, showOtherAircrafts, showOtherMissions, setMapOptions } =
|
||||
usePilotConnectionStore();
|
||||
const cross = (
|
||||
<svg
|
||||
aria-label="disabled"
|
||||
@@ -59,7 +61,11 @@ export const SettingsBoard = () => {
|
||||
</h2>
|
||||
<div className="flex items-center gap-2">
|
||||
<label className="toggle text-base-content">
|
||||
<input type="checkbox" />
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={followOwnAircraft}
|
||||
onChange={(e) => setMapOptions({ followOwnAircraft: e.target.checked })}
|
||||
/>
|
||||
{cross}
|
||||
{check}
|
||||
</label>
|
||||
@@ -67,7 +73,11 @@ export const SettingsBoard = () => {
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<label className="toggle text-base-content">
|
||||
<input type="checkbox" />
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={showOtherAircrafts}
|
||||
onChange={(e) => setMapOptions({ showOtherAircrafts: e.target.checked })}
|
||||
/>
|
||||
{cross}
|
||||
{check}
|
||||
</label>
|
||||
@@ -75,7 +85,11 @@ export const SettingsBoard = () => {
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<label className="toggle text-base-content">
|
||||
<input type="checkbox" />
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={showOtherMissions}
|
||||
onChange={(e) => setMapOptions({ showOtherMissions: e.target.checked })}
|
||||
/>
|
||||
{cross}
|
||||
{check}
|
||||
</label>
|
||||
|
||||
@@ -16,6 +16,7 @@ import { useQuery } from "@tanstack/react-query";
|
||||
import { getConnectedAircraftPositionLogAPI, getConnectedAircraftsAPI } from "_querys/aircrafts";
|
||||
import { getMissionsAPI } from "_querys/missions";
|
||||
import { FMS_STATUS_COLORS, FMS_STATUS_TEXT_COLORS } from "_helpers/fmsStatusColors";
|
||||
import { usePilotConnectionStore } from "_store/pilot/connectionStore";
|
||||
|
||||
const AircraftPopupContent = ({
|
||||
aircraft,
|
||||
@@ -396,10 +397,42 @@ export const AircraftLayer = () => {
|
||||
queryFn: () => getConnectedAircraftsAPI(),
|
||||
refetchInterval: 10_000,
|
||||
});
|
||||
const { setMap } = useMapStore((state) => state);
|
||||
const map = useMap();
|
||||
const {
|
||||
connectedAircraft,
|
||||
status: pilotConnectionStatus,
|
||||
showOtherAircrafts,
|
||||
followOwnAircraft,
|
||||
} = usePilotConnectionStore((state) => state);
|
||||
|
||||
const filteredAircrafts = useMemo(() => {
|
||||
if (!aircrafts) return [];
|
||||
return aircrafts.filter((aircraft) => {
|
||||
if (pilotConnectionStatus === "connected" && !showOtherAircrafts) {
|
||||
return connectedAircraft?.stationId === aircraft.stationId;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}, [aircrafts, pilotConnectionStatus, connectedAircraft, showOtherAircrafts]);
|
||||
|
||||
const ownAircraft = useMemo(() => {
|
||||
return aircrafts?.find((aircraft) => aircraft.id === connectedAircraft?.id);
|
||||
}, [aircrafts, connectedAircraft]);
|
||||
|
||||
useEffect(() => {
|
||||
if (pilotConnectionStatus === "connected" && followOwnAircraft && ownAircraft) {
|
||||
if (!ownAircraft.posLat || !ownAircraft.posLng) return;
|
||||
setMap({
|
||||
center: [ownAircraft.posLat, ownAircraft.posLng],
|
||||
zoom: map.getZoom(),
|
||||
});
|
||||
}
|
||||
}, [pilotConnectionStatus, followOwnAircraft, ownAircraft, setMap, map]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{aircrafts?.map((aircraft) => {
|
||||
{filteredAircrafts?.map((aircraft) => {
|
||||
return <AircraftMarker key={aircraft.id} aircraft={aircraft} />;
|
||||
})}
|
||||
</>
|
||||
|
||||
@@ -17,6 +17,7 @@ import { getMissionsAPI } from "_querys/missions";
|
||||
import { useDispatchConnectionStore } from "_store/dispatch/connectionStore";
|
||||
import { HPGValidationRequired } from "_helpers/hpgValidationRequired";
|
||||
import { getConnectedAircraftsAPI } from "_querys/aircrafts";
|
||||
import { usePilotConnectionStore } from "_store/pilot/connectionStore";
|
||||
|
||||
export const MISSION_STATUS_COLORS: Record<MissionState | "attention", string> = {
|
||||
draft: "#0092b8",
|
||||
@@ -396,6 +397,11 @@ const MissionMarker = ({ mission }: { mission: Mission }) => {
|
||||
export const MissionLayer = () => {
|
||||
const dispatchState = useDispatchConnectionStore((s) => s);
|
||||
const dispatcherConnected = dispatchState.status === "connected";
|
||||
const {
|
||||
status: pilotConnectionStatus,
|
||||
showOtherMissions,
|
||||
selectedStation,
|
||||
} = usePilotConnectionStore((state) => state);
|
||||
|
||||
const { data: missions = [] } = useQuery({
|
||||
queryKey: ["missions"],
|
||||
@@ -410,9 +416,18 @@ export const MissionLayer = () => {
|
||||
return missions.filter((m: Mission) => {
|
||||
if (m.state === "draft" && !dispatcherConnected) return false;
|
||||
if (dispatchState.hideDraftMissions && m.state === "draft") return false;
|
||||
if (pilotConnectionStatus === "connected" && !showOtherMissions)
|
||||
return m.missionStationIds.includes(selectedStation!.id);
|
||||
return true;
|
||||
});
|
||||
}, [missions, dispatcherConnected, dispatchState.hideDraftMissions]);
|
||||
}, [
|
||||
missions,
|
||||
dispatcherConnected,
|
||||
dispatchState.hideDraftMissions,
|
||||
pilotConnectionStatus,
|
||||
showOtherMissions,
|
||||
selectedStation,
|
||||
]);
|
||||
|
||||
// IDEA: Add Marker to Map Layer / LayerGroup
|
||||
return (
|
||||
|
||||
@@ -11,6 +11,7 @@ import { getMissionsAPI } from "_querys/missions";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useMap } from "react-leaflet";
|
||||
import { HPGValidationRequired } from "_helpers/hpgValidationRequired";
|
||||
import { usePilotConnectionStore } from "_store/pilot/connectionStore";
|
||||
|
||||
const PopupContent = ({
|
||||
aircrafts,
|
||||
@@ -136,6 +137,7 @@ const PopupContent = ({
|
||||
export const MarkerCluster = () => {
|
||||
const map = useMap();
|
||||
const dispatchState = useDispatchConnectionStore((s) => s);
|
||||
const pilotState = usePilotConnectionStore((s) => s);
|
||||
const dispatcherConnected = dispatchState.status === "connected";
|
||||
const { data: aircrafts } = useQuery({
|
||||
queryKey: ["aircrafts"],
|
||||
@@ -155,9 +157,36 @@ export const MarkerCluster = () => {
|
||||
return missions.filter((m: Mission) => {
|
||||
if (m.state === "draft" && !dispatcherConnected) return false;
|
||||
if (dispatchState.hideDraftMissions && m.state === "draft") return false;
|
||||
if (
|
||||
pilotState.status === "connected" &&
|
||||
!pilotState.showOtherMissions &&
|
||||
pilotState.selectedStation
|
||||
)
|
||||
return m.missionStationIds.includes(pilotState.selectedStation.id);
|
||||
return true;
|
||||
});
|
||||
}, [missions, dispatcherConnected, dispatchState.hideDraftMissions]);
|
||||
}, [
|
||||
missions,
|
||||
dispatcherConnected,
|
||||
dispatchState.hideDraftMissions,
|
||||
pilotState.selectedStation,
|
||||
pilotState.showOtherMissions,
|
||||
pilotState.status,
|
||||
]);
|
||||
|
||||
const filteredAircrafts = useMemo(() => {
|
||||
return aircrafts?.filter((a: ConnectedAircraft) => {
|
||||
if (pilotState.status === "connected" && !pilotState.showOtherAircrafts) {
|
||||
return a.stationId === pilotState.connectedAircraft?.stationId;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}, [
|
||||
aircrafts,
|
||||
pilotState.status,
|
||||
pilotState.showOtherAircrafts,
|
||||
pilotState.connectedAircraft?.stationId,
|
||||
]);
|
||||
|
||||
// Track zoom level in state
|
||||
const [zoom, setZoom] = useState(() => map.getZoom());
|
||||
@@ -178,7 +207,7 @@ export const MarkerCluster = () => {
|
||||
lat: number;
|
||||
lng: number;
|
||||
}[] = [];
|
||||
aircrafts?.forEach((aircraft) => {
|
||||
filteredAircrafts?.forEach((aircraft) => {
|
||||
const lat = aircraft.posLat!;
|
||||
const lng = aircraft.posLng!;
|
||||
|
||||
@@ -255,7 +284,7 @@ export const MarkerCluster = () => {
|
||||
});
|
||||
|
||||
return clusterWithAvgPos;
|
||||
}, [aircrafts, filteredMissions, zoom]);
|
||||
}, [filteredAircrafts, filteredMissions, zoom]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { AudioTrack, RemoteAudioTrack, RemoteTrack } from "livekit-client";
|
||||
|
||||
// Helper function for distortion curve generation
|
||||
function createDistortionCurve(amount: number): Float32Array {
|
||||
const k = typeof amount === "number" ? amount : 50;
|
||||
@@ -12,10 +14,12 @@ function createDistortionCurve(amount: number): Float32Array {
|
||||
return curve;
|
||||
}
|
||||
|
||||
export const getRadioStream = (stream: MediaStream, volume: number): MediaStream | null => {
|
||||
export const getRadioStream = (track: RemoteAudioTrack, volume: number): MediaStream | null => {
|
||||
try {
|
||||
const audioContext = new window.AudioContext();
|
||||
const sourceNode = audioContext.createMediaStreamSource(stream);
|
||||
const sourceNode = audioContext.createMediaStreamSource(
|
||||
new MediaStream([track.mediaStreamTrack]),
|
||||
);
|
||||
const destinationNode = audioContext.createMediaStreamDestination();
|
||||
const gainNode = audioContext.createGain();
|
||||
|
||||
@@ -6,6 +6,7 @@ export interface MapStore {
|
||||
lat: number;
|
||||
lng: number;
|
||||
} | null;
|
||||
|
||||
map: {
|
||||
center: L.LatLngExpression;
|
||||
zoom: number;
|
||||
|
||||
@@ -27,6 +27,14 @@ interface ConnectionStore {
|
||||
debug?: boolean,
|
||||
) => Promise<void>;
|
||||
disconnect: () => void;
|
||||
followOwnAircraft: boolean;
|
||||
showOtherAircrafts: boolean;
|
||||
showOtherMissions: boolean;
|
||||
setMapOptions: (options: {
|
||||
followOwnAircraft?: boolean;
|
||||
showOtherAircrafts?: boolean;
|
||||
showOtherMissions?: boolean;
|
||||
}) => void;
|
||||
}
|
||||
|
||||
export const usePilotConnectionStore = create<ConnectionStore>((set) => ({
|
||||
@@ -37,7 +45,15 @@ export const usePilotConnectionStore = create<ConnectionStore>((set) => ({
|
||||
connectedAircraft: null,
|
||||
activeMission: null,
|
||||
debug: false,
|
||||
|
||||
followOwnAircraft: false,
|
||||
showOtherAircrafts: false,
|
||||
showOtherMissions: false,
|
||||
setMapOptions(options) {
|
||||
set((state) => ({
|
||||
...state,
|
||||
...options,
|
||||
}));
|
||||
},
|
||||
connect: async (uid, stationId, logoffTime, station, user, debug) =>
|
||||
new Promise((resolve) => {
|
||||
set({
|
||||
|
||||
Reference in New Issue
Block a user