2026-02-17 15:03:34 +00:00
|
|
|
/**
|
|
|
|
|
* Onboarding state - prefers backend, falls back to localStorage for mock/offline.
|
2026-03-01 17:53:18 +00:00
|
|
|
* Hardened: retries on 502/503, never blocks completion.
|
2026-02-17 15:03:34 +00:00
|
|
|
*/
|
|
|
|
|
import { rpcClient } from '@/api/rpc-client'
|
|
|
|
|
|
2026-03-01 17:53:18 +00:00
|
|
|
async function callWithRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T | null> {
|
|
|
|
|
for (let i = 0; i < maxRetries; i++) {
|
|
|
|
|
try {
|
|
|
|
|
return await fn()
|
|
|
|
|
} catch (e) {
|
|
|
|
|
const msg = e instanceof Error ? e.message : ''
|
|
|
|
|
const isRetryable = /502|503|timeout|fetch|network/i.test(msg)
|
|
|
|
|
if (!isRetryable || i === maxRetries - 1) return null
|
|
|
|
|
await new Promise((r) => setTimeout(r, 800 * (i + 1)))
|
|
|
|
|
}
|
2026-02-17 15:03:34 +00:00
|
|
|
}
|
2026-03-01 17:53:18 +00:00
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function isOnboardingComplete(): Promise<boolean> {
|
fix: container DNS, nginx chown, onboarding guard, seed UX, install flow
Backend:
- Add --add-host host.containers.internal:host-gateway to LND and Bitcoin
Knots containers (fixes DNS resolution failure in rootless podman)
- Add --user 0:0 and DAC_OVERRIDE to nginx UI sidecar containers
(fixes chown crash in rootless podman for bitcoin-ui, electrs-ui, lnd-ui)
- Add hostadd to Rust Podman API client for web UI container installs
- Add Chromium privacy flags to kiosk launcher (disable telemetry)
Frontend:
- Fix onboarding reset on raw IP visits (trust localStorage as first-class
signal, skip boot screen when server is up but not onboarded)
- Fix seed regression: persist challenge indices in sessionStorage so going
back from Verify doesn't change which words are asked
- Remove glass container from seed Generate/Verify/Restore screens
- Add Back button to Restore from Seed screen
- Replace Network card: Tor (purple), VPN status (orange), Bitcoin sync (orange)
- Add ElectrumX to curated app list with correct .webp icon
- Install flow: navigate to My Apps immediately with toast, hide
installed/installing apps from marketplace and discover views
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 13:06:57 +01:00
|
|
|
// localStorage is set on completion and survives backend restarts/resets
|
|
|
|
|
if (localStorage.getItem('neode_onboarding_complete') === '1') return true
|
2026-03-01 17:53:18 +00:00
|
|
|
const result = await callWithRetry(() => rpcClient.isOnboardingComplete(), 2)
|
|
|
|
|
if (result !== null) return result
|
fix: container DNS, nginx chown, onboarding guard, seed UX, install flow
Backend:
- Add --add-host host.containers.internal:host-gateway to LND and Bitcoin
Knots containers (fixes DNS resolution failure in rootless podman)
- Add --user 0:0 and DAC_OVERRIDE to nginx UI sidecar containers
(fixes chown crash in rootless podman for bitcoin-ui, electrs-ui, lnd-ui)
- Add hostadd to Rust Podman API client for web UI container installs
- Add Chromium privacy flags to kiosk launcher (disable telemetry)
Frontend:
- Fix onboarding reset on raw IP visits (trust localStorage as first-class
signal, skip boot screen when server is up but not onboarded)
- Fix seed regression: persist challenge indices in sessionStorage so going
back from Verify doesn't change which words are asked
- Remove glass container from seed Generate/Verify/Restore screens
- Add Back button to Restore from Seed screen
- Replace Network card: Tor (purple), VPN status (orange), Bitcoin sync (orange)
- Add ElectrumX to curated app list with correct .webp icon
- Install flow: navigate to My Apps immediately with toast, hide
installed/installing apps from marketplace and discover views
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 13:06:57 +01:00
|
|
|
return false
|
2026-02-17 15:03:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function completeOnboarding(): Promise<void> {
|
2026-03-01 17:53:18 +00:00
|
|
|
await callWithRetry(() => rpcClient.completeOnboarding(), 3)
|
|
|
|
|
localStorage.setItem('neode_onboarding_complete', '1')
|
2026-04-02 18:20:52 +01:00
|
|
|
localStorage.removeItem('neode_onboarding_step')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Save current onboarding step so refresh resumes where user left off */
|
|
|
|
|
export function saveOnboardingStep(step: string): void {
|
|
|
|
|
localStorage.setItem('neode_onboarding_step', step)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Get the last saved onboarding step, or 'intro' if none */
|
|
|
|
|
export function getSavedOnboardingStep(): string {
|
|
|
|
|
return localStorage.getItem('neode_onboarding_step') || 'intro'
|
2026-02-17 15:03:34 +00:00
|
|
|
}
|