113 lines
3.1 KiB
TypeScript
113 lines
3.1 KiB
TypeScript
import { useEffect, useState } from 'react'
|
|
import {
|
|
hydrateLocalSaveFromServer,
|
|
loadSession,
|
|
localCloudSave,
|
|
logoutAccount,
|
|
pushCloudSave,
|
|
type AuthSession,
|
|
} from './actionApi'
|
|
import type { ActionMechanicConfig } from './actionBoss/actionEncounterConfig'
|
|
import { ActionModeScreen } from './components/ActionModeScreen'
|
|
import { AuthScreen } from './components/AuthScreen'
|
|
|
|
export function App() {
|
|
const [session, setSession] = useState<AuthSession | null>(null)
|
|
const [loading, setLoading] = useState(true)
|
|
const [message, setMessage] = useState('')
|
|
const [screenKey, setScreenKey] = useState(0)
|
|
|
|
useEffect(() => {
|
|
let cancelled = false
|
|
async function start() {
|
|
try {
|
|
const nextSession = await loadSession()
|
|
if (!nextSession.account) {
|
|
if (!cancelled) setSession(nextSession)
|
|
return
|
|
}
|
|
const syncStatus = await hydrateLocalSaveFromServer()
|
|
if (!cancelled) {
|
|
setSession(nextSession)
|
|
setScreenKey((current) => current + 1)
|
|
setMessage(syncStatus === 'loaded' ? 'Server save loaded.' : '')
|
|
}
|
|
} catch {
|
|
if (!cancelled) setMessage('Server unavailable. Sign in when it comes back online.')
|
|
} finally {
|
|
if (!cancelled) setLoading(false)
|
|
}
|
|
}
|
|
start()
|
|
return () => {
|
|
cancelled = true
|
|
}
|
|
}, [])
|
|
|
|
async function handleAuthenticated(nextSession: AuthSession) {
|
|
if (nextSession.account) {
|
|
const syncStatus = await hydrateLocalSaveFromServer()
|
|
setMessage(syncStatus === 'loaded' ? 'Server save loaded.' : 'Local save uploaded.')
|
|
setScreenKey((current) => current + 1)
|
|
}
|
|
setSession(nextSession)
|
|
}
|
|
|
|
function handlePlayOffline() {
|
|
setSession({ account: null, offline: true })
|
|
setMessage('')
|
|
setScreenKey((current) => current + 1)
|
|
}
|
|
|
|
async function handleLogout() {
|
|
if (!session?.offline) await logoutAccount()
|
|
setSession({ account: null })
|
|
setMessage(session?.offline ? 'Offline mode ended.' : 'Signed out.')
|
|
}
|
|
|
|
function syncCharacter() {
|
|
if (!session?.account) return
|
|
pushCloudSave(localCloudSave()).catch(() => null)
|
|
}
|
|
|
|
function syncMechanics(mechanics: ActionMechanicConfig) {
|
|
if (!session?.account) return
|
|
pushCloudSave({ ...localCloudSave(), mechanics }).catch(() => null)
|
|
}
|
|
|
|
if (loading) {
|
|
return (
|
|
<main className="auth-shell">
|
|
<section className="auth-panel single">
|
|
<div className="auth-card">
|
|
<p className="eyebrow">Loading</p>
|
|
<h1>Connecting</h1>
|
|
<p className="auth-message">Checking server session.</p>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
)
|
|
}
|
|
|
|
if (!session?.account && !session?.offline) {
|
|
return (
|
|
<AuthScreen
|
|
onAuthenticated={handleAuthenticated}
|
|
onPlayOffline={handlePlayOffline}
|
|
serverMessage={message}
|
|
/>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<ActionModeScreen
|
|
key={screenKey}
|
|
account={session.account ?? undefined}
|
|
authActionLabel={session.offline ? 'Sign In' : 'Logout'}
|
|
onCharacterSaved={syncCharacter}
|
|
onLogout={handleLogout}
|
|
onMechanicsSaved={syncMechanics}
|
|
/>
|
|
)
|
|
}
|