205 lines
5.5 KiB
JavaScript
205 lines
5.5 KiB
JavaScript
import { useContext, useEffect, useRef, useState } from 'react'
|
|
import { useLocation } from 'react-router-dom'
|
|
import { Flex, Card, Alert, Button } from 'antd'
|
|
import { LoadingOutlined } from '@ant-design/icons'
|
|
import { customAlphabet } from 'nanoid'
|
|
import AuthParticles from './AppParticles'
|
|
import FarmControlLogo from '../Logos/FarmControlLogo'
|
|
import ExclamationOctagonIcon from '../Icons/ExclamationOctagonIcon'
|
|
import CheckIcon from '../Icons/CheckIcon'
|
|
import ReloadIcon from '../Icons/ReloadIcon'
|
|
import { ApiServerContext } from '../Dashboard/context/ApiServerContext'
|
|
|
|
const createLaunchSession = customAlphabet(
|
|
'01abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
|
32
|
|
)
|
|
|
|
const AuthLaunch = () => {
|
|
const location = useLocation()
|
|
const hasRedirected = useRef(false)
|
|
const startTimeoutRef = useRef(null)
|
|
const pollTimeoutRef = useRef(null)
|
|
const { getAppLaunchSession } = useContext(ApiServerContext)
|
|
const [launchError, setLaunchError] = useState(false)
|
|
const [launchErrorMessage, setLaunchErrorMessage] = useState('')
|
|
const [launchSuccess, setLaunchSuccess] = useState(false)
|
|
|
|
const handleRefresh = () => {
|
|
window.location.reload()
|
|
}
|
|
|
|
useEffect(() => {
|
|
let cancelled = false
|
|
const redirect = new URLSearchParams(location.search).get('redirect')
|
|
const redirectType = new URLSearchParams(location.search).get(
|
|
'redirectType'
|
|
)
|
|
|
|
if (!redirect) {
|
|
setLaunchError(true)
|
|
setLaunchErrorMessage('No redirect provided!')
|
|
return
|
|
}
|
|
|
|
if (!redirect || hasRedirected.current) {
|
|
return
|
|
}
|
|
|
|
startTimeoutRef.current = setTimeout(() => {
|
|
if (cancelled) {
|
|
return
|
|
}
|
|
|
|
hasRedirected.current = true
|
|
const launchSession = createLaunchSession()
|
|
let launchCheckCount = 0
|
|
|
|
setLaunchError(false)
|
|
setLaunchErrorMessage('')
|
|
setLaunchSuccess(false)
|
|
|
|
let redirectWithLaunchSession = redirect
|
|
try {
|
|
const redirectUrl = new URL(redirect, window.location.origin)
|
|
redirectUrl.searchParams.set('launchSession', launchSession)
|
|
redirectWithLaunchSession = redirectUrl.toString()
|
|
} catch {
|
|
const hasQuery = redirect.includes('?')
|
|
const separator = hasQuery ? '&' : '?'
|
|
redirectWithLaunchSession = `${redirect}${separator}launchSession=${encodeURIComponent(
|
|
launchSession
|
|
)}`
|
|
}
|
|
|
|
const link = document.createElement('a')
|
|
link.href = redirectWithLaunchSession
|
|
link.style.display = 'none'
|
|
|
|
if (redirectType === 'app-localhost') {
|
|
link.addEventListener('click', (event) => {
|
|
event.preventDefault()
|
|
window.open(
|
|
redirectWithLaunchSession,
|
|
'farmcontrol-launch',
|
|
'width=480,height=640,menubar=no,toolbar=no,location=yes,status=no,resizable=yes,scrollbars=yes'
|
|
)
|
|
})
|
|
}
|
|
|
|
document.body.appendChild(link)
|
|
link.click()
|
|
document.body.removeChild(link)
|
|
|
|
const checkLaunchSession = async () => {
|
|
launchCheckCount += 1
|
|
|
|
let launchComplete = false
|
|
|
|
try {
|
|
const launchStatus = await getAppLaunchSession(launchSession)
|
|
launchComplete = launchStatus?.complete === true
|
|
} catch {
|
|
launchComplete = false
|
|
}
|
|
|
|
if (cancelled) {
|
|
return
|
|
}
|
|
|
|
if (launchComplete) {
|
|
setLaunchSuccess(true)
|
|
return
|
|
}
|
|
|
|
if (launchCheckCount >= 10) {
|
|
setLaunchError(true)
|
|
setLaunchErrorMessage('Failed to open Farm Control.')
|
|
return
|
|
}
|
|
|
|
pollTimeoutRef.current = setTimeout(() => {
|
|
checkLaunchSession()
|
|
}, 1000)
|
|
}
|
|
|
|
checkLaunchSession()
|
|
}, 0)
|
|
|
|
return () => {
|
|
cancelled = true
|
|
hasRedirected.current = false
|
|
if (startTimeoutRef.current) {
|
|
clearTimeout(startTimeoutRef.current)
|
|
}
|
|
if (pollTimeoutRef.current) {
|
|
clearTimeout(pollTimeoutRef.current)
|
|
}
|
|
}
|
|
}, [getAppLaunchSession, location.search])
|
|
|
|
return (
|
|
<div
|
|
style={{
|
|
backgroundColor: 'black'
|
|
}}
|
|
>
|
|
<div
|
|
style={{
|
|
backgroundColor: 'black',
|
|
minHeight: '100vh',
|
|
transition: 'opacity 0.5s ease-in-out',
|
|
opacity: 1
|
|
}}
|
|
>
|
|
<AuthParticles />
|
|
<Flex
|
|
align='center'
|
|
justify='center'
|
|
vertical
|
|
style={{ height: '100vh' }}
|
|
gap={'large'}
|
|
>
|
|
<Card style={{ borderRadius: 20 }}>
|
|
<Flex vertical align='center'>
|
|
<FarmControlLogo style={{ fontSize: '500px', height: '40px' }} />
|
|
</Flex>
|
|
</Card>
|
|
{!launchError && !launchSuccess && (
|
|
<Alert
|
|
message='Launching Farm Control please wait...'
|
|
icon={<LoadingOutlined />}
|
|
showIcon
|
|
/>
|
|
)}
|
|
{launchError && (
|
|
<>
|
|
<Alert
|
|
message={launchErrorMessage}
|
|
icon={<ExclamationOctagonIcon />}
|
|
type='error'
|
|
showIcon
|
|
/>
|
|
<Button
|
|
icon={<ReloadIcon />}
|
|
onClick={handleRefresh}
|
|
size='large'
|
|
/>
|
|
</>
|
|
)}
|
|
{launchSuccess && (
|
|
<Alert
|
|
message='Launch successful! You may now close this window.'
|
|
icon={<CheckIcon />}
|
|
type='success'
|
|
showIcon
|
|
/>
|
|
)}
|
|
</Flex>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default AuthLaunch
|