diff --git a/backend/http_headers.go b/backend/http_headers.go index 94f95f3..4d6a042 100644 --- a/backend/http_headers.go +++ b/backend/http_headers.go @@ -18,4 +18,3 @@ func NewRequestWithDefaultHeaders(method string, rawURL string, body io.Reader) return req, nil } - diff --git a/frontend/src/components/ApiStatusTab.tsx b/frontend/src/components/ApiStatusTab.tsx index 730a55e..3314b28 100644 --- a/frontend/src/components/ApiStatusTab.tsx +++ b/frontend/src/components/ApiStatusTab.tsx @@ -3,7 +3,6 @@ import { SearchCheck, CheckCircle2, XCircle, Loader2 } from "lucide-react"; import { TidalIcon, QobuzIcon, AmazonIcon, MusicBrainzIcon, AppleMusicIcon, DeezerIcon } from "./PlatformIcons"; import { useApiStatus } from "@/hooks/useApiStatus"; import { SPOTIFLAC_NEXT_SOURCES } from "@/lib/api-status"; - function renderStatusIcon(status: "checking" | "online" | "offline" | "idle") { if (status === "online") { return ; @@ -13,7 +12,6 @@ function renderStatusIcon(status: "checking" | "online" | "offline" | "idle") { } return null; } - function renderPlatformIcon(type: string) { if (type === "tidal") { return ; @@ -32,7 +30,6 @@ function renderPlatformIcon(type: string) { } return ; } - export function ApiStatusTab() { const { sources, statuses, nextStatuses, checkingSources, checkOne } = useApiStatus(); return (
diff --git a/frontend/src/lib/api-status.ts b/frontend/src/lib/api-status.ts index c89b4a4..ad6b915 100644 --- a/frontend/src/lib/api-status.ts +++ b/frontend/src/lib/api-status.ts @@ -1,20 +1,16 @@ import { CheckAPIStatus } from "../../wailsjs/go/main/App"; import { CHECK_TIMEOUT_MS, withTimeout } from "@/lib/async-timeout"; - export type ApiCheckStatus = "checking" | "online" | "offline" | "idle"; - export interface ApiSource { id: string; type: string; name: string; url: string; } - interface SpotiFLACNextSource { id: string; name: string; } - type SpotiFLACNextStatusResponse = { tidal?: string; qobuz_a?: string; @@ -27,14 +23,12 @@ type SpotiFLACNextStatusResponse = { amazon_c?: string; apple?: string; }; - export const API_SOURCES: ApiSource[] = [ { id: "tidal", type: "tidal", name: "Tidal", url: "" }, { id: "qobuz", type: "qobuz", name: "Qobuz", url: "" }, { id: "amazon", type: "amazon", name: "Amazon Music", url: "" }, { id: "musicbrainz", type: "musicbrainz", name: "MusicBrainz", url: "https://musicbrainz.org" }, ]; - export const SPOTIFLAC_NEXT_SOURCES: SpotiFLACNextSource[] = [ { id: "tidal", name: "Tidal" }, { id: "qobuz", name: "Qobuz" }, @@ -42,38 +36,31 @@ export const SPOTIFLAC_NEXT_SOURCES: SpotiFLACNextSource[] = [ { id: "deezer", name: "Deezer" }, { id: "apple", name: "Apple Music" }, ]; - const SPOTIFLAC_NEXT_STATUS_URL = "https://status.spotbye.qzz.io/status"; const SPOTIFLAC_NEXT_MAX_ATTEMPTS = 3; const SPOTIFLAC_NEXT_RETRY_DELAY_MS = 1200; - type ApiStatusState = { checkingSources: Record; statuses: Record; nextStatuses: Record; }; - let apiStatusState: ApiStatusState = { checkingSources: {}, statuses: {}, nextStatuses: {}, }; - let activeCheckNextOnly: Promise | null = null; const activeSourceChecks = new Map>(); const listeners = new Set<() => void>(); - function emitApiStatusChange() { for (const listener of listeners) { listener(); } } - function setApiStatusState(updater: (current: ApiStatusState) => ApiStatusState) { apiStatusState = updater(apiStatusState); emitApiStatusChange(); } - async function checkSourceStatus(source: ApiSource): Promise { try { const isOnline = await withTimeout(CheckAPIStatus(source.type, source.url), CHECK_TIMEOUT_MS, `API status check timed out after 10 seconds for ${source.name}`); @@ -83,19 +70,15 @@ async function checkSourceStatus(source: ApiSource): Promise { return "offline"; } } - function statusFromNextValue(value: string | undefined): ApiCheckStatus { return value === "up" ? "online" : "offline"; } - function anyNextVariantUp(values: Array): ApiCheckStatus { return values.some((value) => value === "up") ? "online" : "offline"; } - function delay(ms: number): Promise { return new Promise((resolve) => window.setTimeout(resolve, ms)); } - function getSafeNextStatusesFallback(currentStatuses: Record): Record { return SPOTIFLAC_NEXT_SOURCES.reduce>((acc, source) => { const current = currentStatuses[source.id]; @@ -103,7 +86,6 @@ function getSafeNextStatusesFallback(currentStatuses: Record> { const response = await withTimeout(fetch(SPOTIFLAC_NEXT_STATUS_URL, { method: "GET", @@ -112,11 +94,9 @@ async function fetchSpotiFLACNextStatusesOnce(): Promise> { let lastError: unknown = null; - for (let attempt = 1; attempt <= SPOTIFLAC_NEXT_MAX_ATTEMPTS; attempt++) { try { return await fetchSpotiFLACNextStatusesOnce(); @@ -141,33 +119,27 @@ async function checkSpotiFLACNextStatuses(): Promise void): () => void { listeners.add(listener); return () => { listeners.delete(listener); }; } - function hasSpotiFLACNextResults(): boolean { return SPOTIFLAC_NEXT_SOURCES.some((source) => { const status = apiStatusState.nextStatuses[source.id]; return status === "online" || status === "offline"; }); } - export async function checkSpotiFLACNextStatusesOnly(): Promise { if (activeCheckNextOnly) { return activeCheckNextOnly; } - activeCheckNextOnly = (async () => { const checkingNextStatuses = Object.fromEntries(SPOTIFLAC_NEXT_SOURCES.map((source) => [source.id, "checking" as ApiCheckStatus])); setApiStatusState((current) => ({ @@ -177,15 +149,12 @@ export async function checkSpotiFLACNextStatusesOnly(): Promise { ...checkingNextStatuses, }, })); - try { setApiStatusState((current) => ({ ...current, nextStatuses: { ...current.nextStatuses }, })); - const nextStatuses = await checkSpotiFLACNextStatuses(); - setApiStatusState((current) => ({ ...current, nextStatuses: { @@ -204,27 +173,22 @@ export async function checkSpotiFLACNextStatusesOnly(): Promise { activeCheckNextOnly = null; } })(); - return activeCheckNextOnly; } - export function ensureSpotiFLACNextStatusCheckStarted(): void { if (!activeCheckNextOnly && !hasSpotiFLACNextResults()) { void checkSpotiFLACNextStatusesOnly(); } } - export async function checkApiStatus(sourceId: string): Promise { const source = API_SOURCES.find((item) => item.id === sourceId); if (!source) { return; } - const activeCheck = activeSourceChecks.get(sourceId); if (activeCheck) { return activeCheck; } - const task = (async () => { setApiStatusState((current) => ({ ...current, @@ -237,10 +201,8 @@ export async function checkApiStatus(sourceId: string): Promise { [sourceId]: "checking", }, })); - try { const status = await checkSourceStatus(source); - setApiStatusState((current) => ({ ...current, statuses: { @@ -260,7 +222,6 @@ export async function checkApiStatus(sourceId: string): Promise { activeSourceChecks.delete(sourceId); } })(); - activeSourceChecks.set(sourceId, task); return task; }