Gate READY on download completion; move audio to ~/.radiantwave/audio

State machine now uses DOWNLOADING_ASSETS before READY. Downloads closing
the DownloadDone channel signals checkState() to proceed. Download failure
sets downloadFailed flag which prevents READY. Audio files moved from
~/.local/share/rhemawave/audio to ~/.radiantwave/audio/.

Regression tests in application_test.go (linux build-tagged due to
network package D-Bus init). Version 0.6.
This commit is contained in:
NeilClack
2026-07-11 13:43:05 -05:00
parent 2cc5071731
commit 3f8144a708
7 changed files with 252 additions and 26 deletions
+34 -17
View File
@@ -45,14 +45,16 @@ const (
)
type Application struct {
Window *sdl.Window
License *license.Response
pageStack []page.Page
pendingAction func()
running bool
DB *gorm.DB
PageRouter *page.Router
state State
Window *sdl.Window
License *license.Response
pageStack []page.Page
pendingAction func()
running bool
DB *gorm.DB
PageRouter *page.Router
state State
downloadsComplete bool
downloadFailed bool
}
var lastNetworkCheckTime time.Time
@@ -153,12 +155,14 @@ func Run() {
app.initializeAudio()
// Create a buffered channel so log writes don't slow down downloads.
downloadProgressChan := make(chan download.DownloadStatus, 1000)
downloadDone := make(chan struct{})
app.PageRouter = page.NewRouter(page.PageCtx{
DbPtr: app.DB,
W: w,
H: h,
MessageChannel: downloadProgressChan,
DownloadDone: downloadDone,
})
// Sync the proclamations from the API to the Database
@@ -183,16 +187,11 @@ func Run() {
// "PinealGland.wav",
// }
config, err := db.GetConfig(app.DB)
if err != nil {
panic(err)
}
audioDir := filepath.Join(config.AssetsDir, "audio")
audioDir := filepath.Join(homeDir, ".radiantwave", "audio")
_, err = os.Stat(audioDir)
if os.IsNotExist(err) {
if err = os.MkdirAll(audioDir, 0740); err != nil {
if err = os.MkdirAll(audioDir, 0755); err != nil {
logger.Error("unable to create audio directory: %v", err)
}
}
@@ -203,13 +202,22 @@ func Run() {
}
// checkState keeps watch of the application state and sets pages
// accordingly. This function runs once per
// accordingly. This function runs once per frame.
func (app *Application) checkState() {
// app.state is READY so do nothing.
if app.state == READY {
return
}
// Check if downloads have finished (non-blocking)
if !app.downloadsComplete {
select {
case <-app.PageRouter.Context.DownloadDone:
app.downloadsComplete = true
default:
}
}
// Check if there is an internet connection, and if not, force the WiFi page
if !networkIsUp {
if lastNetworkCheckTime.IsZero() || time.Since(lastNetworkCheckTime) >= time.Second {
@@ -264,6 +272,15 @@ func (app *Application) checkState() {
return
}
// All config prerequisites met — now wait for downloads to finish
if !app.downloadsComplete {
if app.state != DOWNLOADING_ASSETS {
app.state = DOWNLOADING_ASSETS
app.PageRouter.NavigateTo(page.HOME)
}
return
}
app.state = READY
app.PageRouter.NavigateTo(page.HOME)
}
@@ -494,7 +511,7 @@ func (app *Application) initKeybinds() {
})
keybinds.Register(sdl.K_F1, sdl.KMOD_NONE, func() {
if app.state != READY {
if app.state != READY && app.state != DOWNLOADING_ASSETS {
return
}
app.PageRouter.NavigateTo(page.HOME)