Files
yt-dlp-webui/frontend/src/components/SocketSubscriber.tsx
2023-10-29 15:07:42 +01:00

72 lines
2.0 KiB
TypeScript

import * as O from 'fp-ts/Option'
import { useMemo } from 'react'
import { useRecoilState, useRecoilValue } from 'recoil'
import { share, take, timer } from 'rxjs'
import { downloadsState } from '../atoms/downloads'
import { serverAddressAndPortState } from '../atoms/settings'
import { connectedState } from '../atoms/status'
import { useSubscription } from '../hooks/observable'
import { useToast } from '../hooks/toast'
import { useI18n } from '../hooks/useI18n'
import { useRPC } from '../hooks/useRPC'
import { datetimeCompareFunc, isRPCResponse } from '../utils'
interface Props extends React.HTMLAttributes<HTMLBaseElement> { }
const SocketSubscriber: React.FC<Props> = ({ children }) => {
const [, setIsConnected] = useRecoilState(connectedState)
const [, setDownloads] = useRecoilState(downloadsState)
const serverAddressAndPort = useRecoilValue(serverAddressAndPortState)
const { i18n } = useI18n()
const { client } = useRPC()
const { pushMessage } = useToast()
const sharedSocket$ = useMemo(() => client.socket$.pipe(share()), [])
const socketOnce$ = useMemo(() => sharedSocket$.pipe(take(1)), [])
useSubscription(socketOnce$, () => {
setIsConnected(true)
pushMessage(
`${i18n.t('toastConnected')} (${serverAddressAndPort})`,
"success"
)
})
useSubscription(
sharedSocket$,
event => {
if (!isRPCResponse(event)) { return }
if (!Array.isArray(event.result)) { return }
if (event.result) {
return setDownloads(
O.of(event.result
.filter(f => !!f.info.url).sort((a, b) => datetimeCompareFunc(
b.info.created_at,
a.info.created_at,
))
)
)
}
setDownloads(O.none)
},
err => {
console.error(err)
pushMessage(
`${i18n.t('rpcConnErr')} (${serverAddressAndPort})`,
"error"
)
}
)
useSubscription(timer(0, 1000), () => client.running())
return (
<>{children}</>
)
}
export default SocketSubscriber