import React, {Fragment, useCallback, useMemo} from 'react';
import StatusCardSkeleton, {type StatusCardSkeletonData} from "./StatusCardSkeleton";
import SkeletonParagraph from "../skeleton/SkeletonParagraph";
import {Link} from "react-router-dom";
import {sourceAdapter} from "../../status/ducks";
import type {RootState} from "../../store";
import {connect, type ConnectedProps} from "react-redux";
import Player from "../player/Player";
import {useStartSourceMutation, useListenSourceMutation} from "./sourceDucks";
import './statusCard.scss';
import Tooltip from '../Tooltip';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import {faQuestionCircle} from '@fortawesome/free-solid-svg-icons'
const ambiguousTypes = ['lastfm','listenbrainz','koito','librefm','maloja','rocksky'];
export interface SourceStatusCardData extends StatusCardSkeletonData, PropsFromRedux {
loading?: boolean
}
const statusToStatusType = (status: string) => {
const lower = status.toLowerCase();
if(lower.includes('running') || lower.includes('polling') || lower.includes('received data')) {
return 'active';
}
if(lower.includes('idle') || lower.includes('awaiting data')) {
return 'warn';
}
return 'error';
}
const SourceStatusCard = (props: SourceStatusCardData) => {
const {
loading = false,
data,
data: {
display,
name,
type,
status,
} = {}
} = props;
let header: string | undefined = display;
let body = ;
const [startPut, startResult] = useStartSourceMutation();
const [listenPut, listenResult] = useListenSourceMutation();
const tryStart = useCallback((name: string, type: string, force?: boolean) => startPut({name, type, force}), [startPut]);
const tryListen = useCallback((name: string, type: string, currentListening?: boolean) => {
// cycle through states
let nextListen: boolean | undefined;
switch(currentListening) {
case true:
nextListen = false;
break;
case false:
nextListen = undefined;
break;
case undefined:
nextListen = true;
break;
}
listenPut({name, type, listening: nextListen});
}, [listenPut]);
let subtitleElement = null;
if(data !== undefined)
{
const {
display,
name,
canPoll,
hasAuth,
authed,
status,
tracksDiscovered,
hasAuthInteraction,
type,
players = {},
sot,
supportsUpstreamRecentlyPlayed,
manualListening,
systemListeningBehavior
} = data;
if(ambiguousTypes.includes(type)) {
header = `${display} (Source)`;
}
let startText = '';
if(canPoll) {
startText = status === 'Polling' ? 'Restart' : 'Start'
} else {
startText = status === 'Running' ? 'Reinit' : 'Init'
}
const ml = useMemo(() => {
if(listenResult.status !== 'fulfilled' || listenResult.data === undefined) {
return manualListening;
}
return (listenResult.data as any).listening;
}, [manualListening, listenResult]);
const manualListenElement = type !== 'azuracast' && type !== 'icecast' ? null : (
Monitoring
:
tryListen(name, type, ml)}
className="capitalize underline cursor-pointer inline mr-1 ml-1">
{ml !== undefined ? (ml ? 'Yes' : 'No') : null}
{ml === undefined ? System {systemListeningBehavior ? '(Yes)' : '(No)'} : null}
{/* {ml !== undefined ? tryListen(name, type, undefined)}
className="capitalize underline cursor-pointer inline">Clear
: null} */}
);
const startSourceElement = (
tryStart(name, type)}
className="capitalize underline cursor-pointer inline mr-1">{startText}
( tryStart(name, type, true)}
className="capitalize underline cursor-pointer inline">Force
)
);
if(manualListenElement !== null) {
subtitleElement = {manualListenElement} | {startSourceElement}
} else {
subtitleElement = startSourceElement;
}
const platformIds = Object.keys(players);
const discovered = (!hasAuth || authed) ? Tracks Discovered : Tracks Discovered;
let upstreamRecent = null;
if(supportsUpstreamRecentlyPlayed && (!hasAuth || authed)) {
upstreamRecent =
See Recent from Source API
;
}
// TODO links
body = (
{platformIds.map(x =>
)}
{discovered}: {tracksDiscovered}
{upstreamRecent}
{canPoll && hasAuthInteraction ? (Re)authenticate : null}
{type === 'ytmusic' && 'userCode' in data ? Code: {data.userCode as string}
: null}
);
}
return (
{body}
);
}
const simpleSelectors = sourceAdapter.getSelectors();
const mapStateToProps = (state: RootState, props) => ({
data: simpleSelectors.selectById(state.sources, props.id)
});
const connector = connect(mapStateToProps);
type PropsFromRedux = ConnectedProps
export default connector(SourceStatusCard);