mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-21 22:15:40 +00:00
4de577eede
Parse type and serverVersion from Subsonic ping; persist per-server identity and run a background Instant Mix probe (random songs + getSimilarSongs) for Navidrome 0.60+. Hide the AudioMuse server toggle when the probe returns no similar tracks; clear prefs when the server is no longer eligible. Artist pages fall back to Last.fm similar artists when AudioMuse is enabled but the server returns none. Instant Mix failures set a per-server issue flag with a settings warning and toast. Settings description links the official plugin repo via i18n Trans.
89 lines
2.6 KiB
TypeScript
89 lines
2.6 KiB
TypeScript
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
import { useAuthStore } from '../store/authStore';
|
|
import { pingWithCredentials, scheduleInstantMixProbeForServer } from '../api/subsonic';
|
|
|
|
export type ConnectionStatus = 'connected' | 'disconnected' | 'checking';
|
|
|
|
export function isLanUrl(url: string): boolean {
|
|
try {
|
|
const hostname = new URL(url.startsWith('http') ? url : `http://${url}`).hostname;
|
|
return (
|
|
hostname === 'localhost' ||
|
|
hostname.endsWith('.local') ||
|
|
/^127\./.test(hostname) ||
|
|
/^10\./.test(hostname) ||
|
|
/^192\.168\./.test(hostname) ||
|
|
/^172\.(1[6-9]|2\d|3[01])\./.test(hostname)
|
|
);
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export function useConnectionStatus() {
|
|
const [status, setStatus] = useState<ConnectionStatus>('checking');
|
|
const [isRetrying, setIsRetrying] = useState(false);
|
|
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
|
|
|
const check = useCallback(async () => {
|
|
const server = useAuthStore.getState().getActiveServer();
|
|
if (!server) {
|
|
setStatus('disconnected');
|
|
return;
|
|
}
|
|
|
|
if (!navigator.onLine) {
|
|
setStatus('disconnected');
|
|
return;
|
|
}
|
|
|
|
const ping = await pingWithCredentials(server.url, server.username, server.password);
|
|
if (ping.ok) {
|
|
const sid = useAuthStore.getState().activeServerId;
|
|
if (sid) {
|
|
const identity = {
|
|
type: ping.type,
|
|
serverVersion: ping.serverVersion,
|
|
openSubsonic: ping.openSubsonic,
|
|
};
|
|
useAuthStore.getState().setSubsonicServerIdentity(sid, identity);
|
|
scheduleInstantMixProbeForServer(sid, server.url, server.username, server.password, identity);
|
|
}
|
|
}
|
|
setStatus(ping.ok ? 'connected' : 'disconnected');
|
|
}, []);
|
|
|
|
const retry = useCallback(async () => {
|
|
setIsRetrying(true);
|
|
await check();
|
|
setIsRetrying(false);
|
|
}, [check]);
|
|
|
|
useEffect(() => {
|
|
check();
|
|
intervalRef.current = setInterval(check, 120_000);
|
|
|
|
const handleOnline = () => check();
|
|
const handleOffline = () => setStatus('disconnected');
|
|
|
|
window.addEventListener('online', handleOnline);
|
|
window.addEventListener('offline', handleOffline);
|
|
|
|
return () => {
|
|
if (intervalRef.current) clearInterval(intervalRef.current);
|
|
window.removeEventListener('online', handleOnline);
|
|
window.removeEventListener('offline', handleOffline);
|
|
};
|
|
}, [check]);
|
|
|
|
const server = useAuthStore(s => s.getActiveServer());
|
|
|
|
return {
|
|
status,
|
|
isRetrying,
|
|
retry,
|
|
isLan: server ? isLanUrl(server.url) : false,
|
|
serverName: server?.name ?? '',
|
|
};
|
|
}
|