Compare commits
3 Commits
enhancemen
...
bugfix/min
| Author | SHA1 | Date | |
|---|---|---|---|
| ae0a6f9249 | |||
| e46460f41d | |||
| 6c441a0a4b |
@@ -32,7 +32,8 @@
|
|||||||
"react-tabs": "^6.1.0",
|
"react-tabs": "^6.1.0",
|
||||||
"react-use": "^17.6.0",
|
"react-use": "^17.6.0",
|
||||||
"sonner": "^2.0.7",
|
"sonner": "^2.0.7",
|
||||||
"tailwindcss": "^4.1.11"
|
"tailwindcss": "^4.1.11",
|
||||||
|
"use-debounce": "^10.0.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.32.0",
|
"@eslint/js": "^9.32.0",
|
||||||
|
|||||||
BIN
src/assets/sounds/ui/Attention.wav
Normal file
BIN
src/assets/sounds/ui/Attention.wav
Normal file
Binary file not shown.
Binary file not shown.
@@ -181,8 +181,8 @@ export default function SightingHistoryWidget({ className, title }: SightingHist
|
|||||||
if (!isSightingModalOpen && modalQueue.length > 0) {
|
if (!isSightingModalOpen && modalQueue.length > 0) {
|
||||||
const next = modalQueue[0];
|
const next = modalQueue[0];
|
||||||
|
|
||||||
if (next.kind === "NPED") npedSound();
|
// if (next.kind === "NPED") npedSound();
|
||||||
else hotlistsound();
|
// else hotlistsound();
|
||||||
|
|
||||||
setSelectedSighting(next.sighting);
|
setSelectedSighting(next.sighting);
|
||||||
setSightingModalOpen(true);
|
setSightingModalOpen(true);
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
import { useEffect, useMemo, useRef, useState } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
import { Query, useQuery } from "@tanstack/react-query";
|
import { Query, useQuery } from "@tanstack/react-query";
|
||||||
import type { SightingType } from "../types/types";
|
import type { SightingType } from "../types/types";
|
||||||
import { useSoundOnChange } from "react-sounds";
|
import { useSound } from "react-sounds";
|
||||||
import { useSoundContext } from "../context/SoundContext";
|
import { useSoundContext } from "../context/SoundContext";
|
||||||
import { getSoundFileURL } from "../utils/utils";
|
import { checkIsHotListHit, getNPEDCategory, getSoundFileURL } from "../utils/utils";
|
||||||
import switchSound from "../assets/sounds/ui/switch.mp3";
|
import switchSound from "../assets/sounds/ui/switch.mp3";
|
||||||
|
import notification from "../assets/sounds/ui/notification.mp3";
|
||||||
|
import popup from "../assets/sounds/ui/popup_open.mp3";
|
||||||
|
|
||||||
async function fetchSighting(url: string | undefined, ref: number): Promise<SightingType> {
|
async function fetchSighting(url: string | undefined, ref: number): Promise<SightingType> {
|
||||||
const res = await fetch(`${url}${ref}`, {
|
const res = await fetch(`${url}${ref}`, {
|
||||||
@@ -21,26 +24,21 @@ export function useSightingFeed(url: string | undefined) {
|
|||||||
const [sessionStarted, setSessionStarted] = useState(false);
|
const [sessionStarted, setSessionStarted] = useState(false);
|
||||||
const [selectedSighting, setSelectedSighting] = useState<SightingType | null>(null);
|
const [selectedSighting, setSelectedSighting] = useState<SightingType | null>(null);
|
||||||
|
|
||||||
const mostRecent = sightings[0] ?? null;
|
const soundSrcHotlist = useMemo(() => {
|
||||||
const latestRef = mostRecent?.ref ?? null;
|
if (state?.hotlistSound?.includes(".mp3") || state.hotlistSound?.includes(".wav")) {
|
||||||
|
const file = state.soundOptions?.find((item) => item.name === state.hotlistSound);
|
||||||
const first = useRef(true);
|
return file?.soundUrl ?? notification;
|
||||||
const lastSoundAt = useRef(0);
|
|
||||||
const COOLDOWN_MS = 1500;
|
|
||||||
const currentRef = useRef<number>(-1);
|
|
||||||
const lastValidTimestamp = useRef<number>(Date.now());
|
|
||||||
|
|
||||||
const trigger = useMemo(() => {
|
|
||||||
if (latestRef == null || !audioArmed) return null;
|
|
||||||
if (first.current) {
|
|
||||||
first.current = false;
|
|
||||||
return Symbol("skip");
|
|
||||||
}
|
}
|
||||||
const now = Date.now();
|
return getSoundFileURL(state?.hotlistSound) ?? notification;
|
||||||
if (now - lastSoundAt.current < COOLDOWN_MS) return Symbol("skip");
|
}, [state.hotlistSound, state.soundOptions]);
|
||||||
lastSoundAt.current = now;
|
|
||||||
return latestRef;
|
const soundSrcNped = useMemo(() => {
|
||||||
}, [audioArmed, latestRef]);
|
if (state?.NPEDsound?.includes(".mp3") || state.NPEDsound?.includes(".wav")) {
|
||||||
|
const file = state.soundOptions?.find((item) => item.name === state.NPEDsound);
|
||||||
|
return file?.soundUrl ?? popup;
|
||||||
|
}
|
||||||
|
return getSoundFileURL(state.NPEDsound) ?? popup;
|
||||||
|
}, [state.NPEDsound, state.soundOptions]);
|
||||||
|
|
||||||
const soundSrc = useMemo(() => {
|
const soundSrc = useMemo(() => {
|
||||||
if (state?.sightingSound?.includes(".mp3") || state.sightingSound?.includes(".wav")) {
|
if (state?.sightingSound?.includes(".mp3") || state.sightingSound?.includes(".wav")) {
|
||||||
@@ -50,6 +48,15 @@ export function useSightingFeed(url: string | undefined) {
|
|||||||
return getSoundFileURL(state?.sightingSound) ?? switchSound;
|
return getSoundFileURL(state?.sightingSound) ?? switchSound;
|
||||||
}, [state.sightingSound, state.soundOptions]);
|
}, [state.sightingSound, state.soundOptions]);
|
||||||
|
|
||||||
|
const { play: hotlistsound } = useSound(soundSrcHotlist, { volume: state.hotlistSoundVolume });
|
||||||
|
const { play: npedSound } = useSound(soundSrcNped, { volume: state.NPEDsoundVolume });
|
||||||
|
const { play: sightingSound } = useSound(soundSrc, { volume: state.sightingVolume });
|
||||||
|
|
||||||
|
const mostRecent = sightings[0] ?? null;
|
||||||
|
|
||||||
|
const currentRef = useRef<number>(-1);
|
||||||
|
const lastValidTimestamp = useRef<number>(Date.now());
|
||||||
|
|
||||||
function refetchInterval(query: Query<SightingType, Error, SightingType, (string | undefined)[]>) {
|
function refetchInterval(query: Query<SightingType, Error, SightingType, (string | undefined)[]>) {
|
||||||
if (!query) return;
|
if (!query) return;
|
||||||
const data = query.state.data as SightingType | undefined;
|
const data = query.state.data as SightingType | undefined;
|
||||||
@@ -78,16 +85,36 @@ export function useSightingFeed(url: string | undefined) {
|
|||||||
staleTime: 0,
|
staleTime: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
//use latestref instead of trigger to revert back
|
const playHotlistsound = useDebouncedCallback(() => {
|
||||||
|
hotlistsound();
|
||||||
|
}, 500);
|
||||||
|
|
||||||
useSoundOnChange(soundSrc, trigger, {
|
const playNPEDHitSound = useDebouncedCallback(() => {
|
||||||
volume: state.sightingVolume,
|
npedSound();
|
||||||
initial: false,
|
}, 500);
|
||||||
});
|
|
||||||
|
const playSightingHitSound = useDebouncedCallback(() => {
|
||||||
|
sightingSound();
|
||||||
|
}, 500);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const data = query.data;
|
const data = query.data;
|
||||||
|
|
||||||
if (!data || data.ref === -1) return;
|
if (!data || data.ref === -1) return;
|
||||||
|
const isHotListHit = checkIsHotListHit(data);
|
||||||
|
const cat = getNPEDCategory(data);
|
||||||
|
|
||||||
|
const isNPEDHitA = cat === "A";
|
||||||
|
const isNPEDHitB = cat === "B";
|
||||||
|
const isNPEDHitC = cat === "C";
|
||||||
|
|
||||||
|
if ((isNPEDHitA && audioArmed) || (isNPEDHitB && audioArmed) || (isNPEDHitC && audioArmed)) {
|
||||||
|
playNPEDHitSound();
|
||||||
|
} else if (isHotListHit && audioArmed) {
|
||||||
|
playHotlistsound();
|
||||||
|
} else if (audioArmed) {
|
||||||
|
playSightingHitSound();
|
||||||
|
}
|
||||||
|
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import beep from "../assets/sounds/ui/Beep.wav";
|
|||||||
import warning from "../assets/sounds/ui/Warning.wav";
|
import warning from "../assets/sounds/ui/Warning.wav";
|
||||||
import ding from "../assets/sounds/ui/Ding.wav";
|
import ding from "../assets/sounds/ui/Ding.wav";
|
||||||
import shutter from "../assets/sounds/ui/shutter.mp3";
|
import shutter from "../assets/sounds/ui/shutter.mp3";
|
||||||
|
import attention from "../assets/sounds/ui/Attention.wav";
|
||||||
import type { HotlistMatches, SightingType } from "../types/types";
|
import type { HotlistMatches, SightingType } from "../types/types";
|
||||||
|
|
||||||
export function getSoundFileURL(name: string) {
|
export function getSoundFileURL(name: string) {
|
||||||
@@ -17,6 +17,7 @@ export function getSoundFileURL(name: string) {
|
|||||||
warning: warning,
|
warning: warning,
|
||||||
ding: ding,
|
ding: ding,
|
||||||
shutter: shutter,
|
shutter: shutter,
|
||||||
|
attention: attention,
|
||||||
};
|
};
|
||||||
return sounds[name] ?? null;
|
return sounds[name] ?? null;
|
||||||
}
|
}
|
||||||
@@ -156,4 +157,4 @@ export function getHotlistName(obj: HotlistMatches | undefined) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const getNPEDCategory = (r?: SightingType | null) =>
|
export const getNPEDCategory = (r?: SightingType | null) =>
|
||||||
r?.metadata?.npedJSON?.["NPED CATEGORY"] as "A" | "B" | "C" | undefined;
|
r?.metadata?.npedJSON?.["NPED CATEGORY"] as "A" | "B" | "C" | "D" | undefined;
|
||||||
|
|||||||
@@ -2267,6 +2267,11 @@ uri-js@^4.2.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
punycode "^2.1.0"
|
punycode "^2.1.0"
|
||||||
|
|
||||||
|
use-debounce@^10.0.6:
|
||||||
|
version "10.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/use-debounce/-/use-debounce-10.0.6.tgz#e05060a5e561432ec740c653698f3eb162bd28ec"
|
||||||
|
integrity sha512-C5OtPyhAZgVoteO9heXMTdW7v/IbFI+8bSVKYCJrSmiWWCLsbUxiBSp4t9v0hNBTGY97bT72ydDIDyGSFWfwXg==
|
||||||
|
|
||||||
vite@^7.1.0:
|
vite@^7.1.0:
|
||||||
version "7.1.2"
|
version "7.1.2"
|
||||||
resolved "https://registry.npmjs.org/vite/-/vite-7.1.2.tgz"
|
resolved "https://registry.npmjs.org/vite/-/vite-7.1.2.tgz"
|
||||||
|
|||||||
Reference in New Issue
Block a user