import isElectron from 'is-electron'; import { debounce } from 'lodash'; import { useCallback, useEffect, useRef, useState } from 'react'; import { api } from '/@/renderer/api'; import { useAuthStoreActions, useCurrentServer } from '/@/renderer/store'; import { toast } from '/@/shared/components/toast/toast'; import { ServerListItem, ServerType } from '/@/shared/types/domain/server-domain-types'; import { ListSortOrder } from '/@/shared/types/domain/shared-domain-types'; import { SongListSort } from '/@/shared/types/domain/song-domain-types'; import { AuthState } from '/@/shared/types/types'; const localSettings = isElectron() ? window.api.localSettings : null; export const useServerAuthenticated = () => { const priorServerId = useRef(undefined); const server = useCurrentServer(); const [ready, setReady] = useState( server?.type === ServerType.NAVIDROME ? AuthState.VALID : AuthState.VALID, ); const { updateServer } = useAuthStoreActions(); const authenticateNavidrome = useCallback( async (server: ServerListItem) => { // This trick works because navidrome-api.ts will internally check for authentication // failures and try to log in again (where available). So, all that's necessary is // making one request first try { await api.controller.getSongList({ apiClientProps: { server }, query: { limit: 1, sortBy: SongListSort.NAME, sortOrder: ListSortOrder.ASC, offset: 0, }, }); setReady(AuthState.VALID); } catch (error) { // Clear server credentials (and saved password). if (server.savePassword && localSettings) { localSettings.passwordRemove(server.id); } server.credential = ''; updateServer(server.id, server); toast.error({ message: (error as Error).message }); setReady(AuthState.INVALID); } }, [updateServer], ); const debouncedAuth = debounce((server: ServerListItem) => { authenticateNavidrome(server).catch(console.error); }, 300); useEffect(() => { if (priorServerId.current !== server?.id) { priorServerId.current = server?.id || ''; if (server?.type === ServerType.NAVIDROME) { setReady(AuthState.LOADING); debouncedAuth(server); } else { setReady(AuthState.VALID); } } }, [debouncedAuth, server]); return ready; };