Add downloading message to home screen.

Download files in the background and keep track of progress.
This commit is contained in:
NeilClack
2026-06-18 22:43:47 -05:00
parent 2af1aae885
commit ac86864c72
3 changed files with 78 additions and 42 deletions
+2 -1
View File
@@ -154,7 +154,8 @@ func Run() {
app.initializeManagers() app.initializeManagers()
app.initializeAudio() app.initializeAudio()
downloadProgressChan := make(chan download.DownloadStatus) // Create a buffered channel so log writes don't slow down downloads.
downloadProgressChan := make(chan download.DownloadStatus, 1000)
app.PageRouter = page.NewRouter(page.PageCtx{ app.PageRouter = page.NewRouter(page.PageCtx{
CfgPtr: app.Config.Load(), CfgPtr: app.Config.Load(),
+5 -4
View File
@@ -30,6 +30,7 @@ func DownloadAudioFiles(progressChan chan<- DownloadStatus, filenames []string,
// First, calculate the total size of files that need to be downloaded // First, calculate the total size of files that need to be downloaded
totalSize := int64(0) totalSize := int64(0)
filesToDownload := []string{} filesToDownload := []string{}
totalDownloaded := int64(0)
for _, filename := range filenames { for _, filename := range filenames {
destPath := filepath.Join(destDir, filename) destPath := filepath.Join(destDir, filename)
@@ -62,13 +63,15 @@ func DownloadAudioFiles(progressChan chan<- DownloadStatus, filenames []string,
// Append it to the list to download // Append it to the list to download
filesToDownload = append(filesToDownload, filename) filesToDownload = append(filesToDownload, filename)
// And increase the total bytes to download
totalSize += resp.ContentLength
} else if err != nil { } else if err != nil {
logger.Error("unknown error: %v", err) logger.Error("unknown error: %v", err)
} else { } else {
logger.Error("File %s exists, skipping...", filename) logger.Error("File %s exists, skipping...", filename)
totalDownloaded += fileStat.Size()
} }
// Calculate the total of ALL files to give the illusion of
// "picking up where you left off" to the user
totalSize += resp.ContentLength
resp.Body.Close() resp.Body.Close()
} }
@@ -79,8 +82,6 @@ func DownloadAudioFiles(progressChan chan<- DownloadStatus, filenames []string,
Msg: "Starting download...", Msg: "Starting download...",
} }
totalDownloaded := int64(0)
// Download each file that doesn't exist // Download each file that doesn't exist
for _, filename := range filesToDownload { for _, filename := range filesToDownload {
url := urlBase + filename url := urlBase + filename
+71 -37
View File
@@ -153,47 +153,81 @@ func (p *Home) HandleEvent(event *sdl.Event) error {
return nil return nil
} }
// Update updates animations and changing textures and other changes using `dt` which represents a time delta in float32.
func (p *Home) Update(dt float32) error { func (p *Home) Update(dt float32) error {
select { var (
case progressUpdate, ok := <-p.Context.MessageChannel: progressUpdate download.DownloadStatus
if !ok { ok bool
// Channel is closed, set message to READY gotUpdate bool
newMsg, err := NewStringItem("Status: READY", p.font, colors.Green) )
if err != nil {
return err // Drain the channel, keeping only the newest update.
for {
select {
case progressUpdate, ok = <-p.Context.MessageChannel:
gotUpdate = true
if !ok {
// Channel was closed while draining.
newMsg, err := NewStringItem("Status: READY", p.font, colors.Green)
if err != nil {
return err
}
messageScale := float32(28) / float32(p.baseFontSize)
newMsg.W = int32(float32(newMsg.W) * messageScale)
newMsg.H = int32(float32(newMsg.H) * messageScale)
p.message = newMsg
p.isDownloadComplete = true
return nil
} }
messageScale := float32(28) / float32(p.baseFontSize)
newMsg.W = int32(float32(newMsg.W) * messageScale) default:
newMsg.H = int32(float32(newMsg.H) * messageScale) goto drained
p.message = newMsg
p.isDownloadComplete = true
} else if progressUpdate.Err != nil {
// Handle error
newMsg, err := NewStringItem(fmt.Sprintf("Status: %s", progressUpdate.Err.Error), p.font, colors.Red)
if err != nil {
return err
}
messageScale := float32(28) / float32(p.baseFontSize)
newMsg.W = int32(float32(newMsg.W) * messageScale)
newMsg.H = int32(float32(newMsg.H) * messageScale)
p.message = newMsg
} else {
// Update progress message
percentComplete := float64(progressUpdate.Cur) / float64(progressUpdate.Max) * 100
msg := fmt.Sprintf("Status: Downloading assets %.1f%% Complete", percentComplete)
newMsg, err := NewStringItem(msg, p.font, colors.White)
if err != nil {
return err
}
messageScale := float32(28) / float32(p.baseFontSize)
newMsg.W = int32(float32(newMsg.W) * messageScale)
newMsg.H = int32(float32(newMsg.H) * messageScale)
p.message = newMsg
} }
default:
// No update, do nothing
} }
drained:
if !gotUpdate {
return nil
}
if progressUpdate.Err != nil {
// Handle error
newMsg, err := NewStringItem(
fmt.Sprintf("Status: %s", progressUpdate.Err.Error()),
p.font,
colors.Red,
)
if err != nil {
return err
}
messageScale := float32(28) / float32(p.baseFontSize)
newMsg.W = int32(float32(newMsg.W) * messageScale)
newMsg.H = int32(float32(newMsg.H) * messageScale)
p.message = newMsg
} else {
// Update progress message using ONLY the latest update.
percentComplete := float64(progressUpdate.Cur) / float64(progressUpdate.Max) * 100
msg := fmt.Sprintf(
"Status: Downloading assets %.1f%% Complete",
percentComplete,
)
newMsg, err := NewStringItem(msg, p.font, colors.White)
if err != nil {
return err
}
messageScale := float32(28) / float32(p.baseFontSize)
newMsg.W = int32(float32(newMsg.W) * messageScale)
newMsg.H = int32(float32(newMsg.H) * messageScale)
p.message = newMsg
}
return nil return nil
} }