diff --git a/api/Server.ts b/api/Server.ts index 7b6f3065..5ff370c1 100755 --- a/api/Server.ts +++ b/api/Server.ts @@ -149,6 +149,12 @@ const checkS3Connection = async (): Promise => { "Access-Control-Allow-Headers", "where, offset, limit, Authorization, Origin, X-Requested-With, Content-Type, Accept, Viewport, if-none-match, cache-control" ); + + // NOTE: We've seen an instance where the HOST request header is rewritten by the client, which would otherwise break + // some things. If the host is unknown, default to browse-next. + if (!request.headers.host.includes("cacophony.org.nz")) { + request.headers.host = "https://browse-next.cacophony.org.nz"; + } next(); }); await initialiseApi(app); diff --git a/api/api/V1/recordingUtil.ts b/api/api/V1/recordingUtil.ts index ad4c51da..1d9b0ea1 100755 --- a/api/api/V1/recordingUtil.ts +++ b/api/api/V1/recordingUtil.ts @@ -1356,6 +1356,9 @@ export function signedToken( export const guessMimeType = (type, filename): string => { const mimeType = mime.getType(filename); if (mimeType) { + if (mimeType === "audio/x-aac") { + return "audio/mp4"; + } return mimeType; } switch (type) { diff --git a/browse-next/src/api/Device.ts b/browse-next/src/api/Device.ts index 691c257a..5ccf122c 100644 --- a/browse-next/src/api/Device.ts +++ b/browse-next/src/api/Device.ts @@ -341,6 +341,7 @@ export const getLatestStatusRecordingForDevice = ( params.append("max-results", "1"); params.append("types", "thermal"); params.append("include-false-positives", true.toString()); + params.append("devices", deviceId.toString()); if (use2SecondRecordings) { params.append("status-recordings", true.toString()); } diff --git a/browse-next/src/components/CptvSingleFrame.vue b/browse-next/src/components/CptvSingleFrame.vue index 6895223c..4914e3d0 100644 --- a/browse-next/src/components/CptvSingleFrame.vue +++ b/browse-next/src/components/CptvSingleFrame.vue @@ -120,6 +120,8 @@ const loadRecording = async () => { ); frameData.value = new ImageData(buffer, 160, 120); renderFrame(); + } else { + break; } } } diff --git a/browse-next/src/components/DeviceRecordingSetup.vue b/browse-next/src/components/DeviceRecordingSetup.vue index 6006131e..3f14cab6 100644 --- a/browse-next/src/components/DeviceRecordingSetup.vue +++ b/browse-next/src/components/DeviceRecordingSetup.vue @@ -4,11 +4,13 @@ import { selectedProjectDevices } from "@models/provides.ts"; import type { ApiDeviceHistorySettings, ApiDeviceResponse, + AudioModes, } from "@typedefs/api/device"; import { useRoute } from "vue-router"; import type { DeviceId } from "@typedefs/api/common"; import type { LoadedResource } from "@api/types.ts"; import { + getDeviceModel, getDeviceNodeGroup, getSettingsForDevice, updateDeviceSettings, @@ -16,13 +18,12 @@ import { import Datepicker from "@vuepic/vue-datepicker"; import { projectDevicesLoaded } from "@models/LoggedInUser.ts"; import { resourceIsLoading } from "@/helpers/utils.ts"; -import { DeviceType } from "@typedefs/api/consts.ts"; type Time = { hours: number; minutes: number; seconds: number }; const devices = inject(selectedProjectDevices) as Ref< ApiDeviceResponse[] | null >; const route = useRoute(); -const saltNodeGroup = ref>(null); +const deviceModel = ref>(null); // Device Settings const settings = ref>(null); const syncedSettings = ref>(null); @@ -53,9 +54,9 @@ const device = computed(() => { const settingsLoading = resourceIsLoading(settings); const lastSyncedSettingsLoading = resourceIsLoading(lastSyncedSettings); -const nodeGroupInfoLoading = resourceIsLoading(saltNodeGroup); +const nodeGroupInfoLoading = resourceIsLoading(deviceModel); const isTc2Device = computed(() => { - return (saltNodeGroup.value || "").includes("tc2"); + return deviceModel.value === "tc2"; }); const defaultWindows = { powerOn: "-30m", @@ -152,8 +153,8 @@ const loadResource = async ( const initialised = ref(false); onBeforeMount(async () => { await projectDevicesLoaded(); - await loadResource(saltNodeGroup, () => getDeviceNodeGroup(deviceId.value)); await loadResource(settings, fetchSettings); + await loadResource(deviceModel, () => getDeviceModel(deviceId.value)); initialised.value = true; if (settings.value && !settings.value.synced) { // Load last synced settings @@ -283,6 +284,233 @@ const customRecordingWindowStop = computed