Downloads are working and the goroutine is reporting updates appropriately.

This commit is contained in:
NeilClack
2026-06-18 21:28:16 -05:00
parent 397d4c9f19
commit 7ecb90b63b
6 changed files with 126 additions and 337 deletions
+29
View File
@@ -0,0 +1,29 @@
package page
import (
"github.com/veandco/go-sdl2/sdl"
)
type MessagePage struct {
Msg string
}
func (p *MessagePage) Init(ctx *PageCtx) error {
return nil
}
func (p *MessagePage) HandleEvent(event *sdl.Event) error {
return nil
}
func (p *MessagePage) Update(dt float32) error {
return nil
}
func (p *MessagePage) Render() error {
return nil
}
func (p *MessagePage) Destroy() error {
return nil
}
+56 -12
View File
@@ -2,12 +2,14 @@ package page
import (
"fmt"
"path/filepath"
"time"
"github.com/go-gl/gl/v3.3-core/gl"
"github.com/go-gl/mathgl/mgl32"
"github.com/veandco/go-sdl2/sdl"
"rhemawavetech.com/rhemawave/internal/colors"
"rhemawavetech.com/rhemawave/internal/download"
"rhemawavetech.com/rhemawave/internal/fontManager"
"rhemawavetech.com/rhemawave/internal/shaderManager"
)
@@ -16,16 +18,20 @@ var GitVersion = "1.0"
type Home struct {
Base
title StringItem
version StringItem
prompt StringItem
note StringItem
licenseInfoHeading StringItem
emailDisplay StringItem
licenseKeyDisplay StringItem
hasLicenseInfo bool
lastDisplayUpdate time.Time
baseFontSize int // cached from db at init
fm *fontManager.FontManager
font *fontManager.FontEntry
title StringItem
version StringItem
prompt StringItem
note StringItem
message StringItem
downloadProgressChan chan download.DownloadStatus
licenseInfoHeading StringItem
emailDisplay StringItem
licenseKeyDisplay StringItem
hasLicenseInfo bool
lastDisplayUpdate time.Time
baseFontSize int // cached from db at init
}
// Init performs basic page initialization and creation of static assets.
@@ -40,11 +46,12 @@ func (p *Home) Init(ctx *PageCtx) error {
}
// Get font
fm := fontManager.Get()
font, ok := fm.GetFont("Roboto-Regular")
p.fm = fontManager.Get()
font, ok := p.fm.GetFont("Roboto-Regular")
if !ok {
return fmt.Errorf("unable to fetch font")
}
p.font = font
// Create title texture
var err error
@@ -72,6 +79,9 @@ func (p *Home) Init(ctx *PageCtx) error {
return fmt.Errorf("unable to create note string texture: %w", err)
}
// Create download channel and message
p.downloadProgressChan = make(chan download.DownloadStatus)
// Create license info textures if data exists
if p.Context.CfgPtr.EmailAddress != "" || p.Context.CfgPtr.LicenseKey != "" {
p.hasLicenseInfo = true
@@ -123,6 +133,25 @@ func (p *Home) Init(ctx *PageCtx) error {
}
}
audioFileNames := []string{
"OriginalAudio.wav",
"174Hz.wav",
"396Hz.wav",
"417Hz.wav",
"432Hz.wav",
"639Hz.wav",
"741Hz.wav",
"852Hz.wav",
"963Hz.wav",
"1111Hz.wav",
"14Hz_Binaural.wav",
"40Hz_Binaural.wav",
"AlphaWaves.wav",
"PinealGland.wav",
}
go download.DownloadAudioFiles(p.downloadProgressChan, audioFileNames, filepath.Join(ctx.CfgPtr.AssetsDir, "audio"))
return nil
}
@@ -133,6 +162,21 @@ func (p *Home) HandleEvent(event *sdl.Event) error {
// 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 {
var err error
select {
case progressUpdate := <-p.downloadProgressChan:
if progressUpdate.Err != nil {
p.message, err = NewStringItem(progressUpdate.Msg, p.font, colors.White)
if err != nil {
return err
}
} else {
p.message, err = NewStringItem(progressUpdate.Err.Error(), p.font, colors.Red)
}
default:
return nil
}
return nil
}
-111
View File
@@ -1,111 +0,0 @@
package page
import (
"fmt"
"github.com/go-gl/gl/v3.3-core/gl"
"github.com/go-gl/mathgl/mgl32"
"github.com/veandco/go-sdl2/sdl"
"rhemawavetech.com/rhemawave/internal/colors"
"rhemawavetech.com/rhemawave/internal/fontManager"
"rhemawavetech.com/rhemawave/internal/shaderManager"
)
type MessagePage struct {
Base
message StringItem
instructions StringItem
msgDim mgl32.Vec2
instDim mgl32.Vec2
textShader *shaderManager.Shader
msgPos mgl32.Vec2
instPos mgl32.Vec2
}
func (p *MessagePage) Init(ctx *PageCtx) error {
var err error
var ok bool
if ctx.Msg == "" {
ctx.Msg = "This is an example message because no message was passed"
}
if ctx.Inst == "" {
ctx.Inst = "Press F1 to exit"
}
if err = p.Base.Init(ctx); err != nil {
return fmt.Errorf("failed to init Base page: %w", err)
}
// Fetch and cache shader
sm := shaderManager.Get()
p.textShader, ok = sm.Get("text")
if !ok {
return fmt.Errorf("failed to fetch text shader")
}
fm := fontManager.Get()
font, ok := fm.GetFont("Roboto-Regular")
if !ok {
return fmt.Errorf("unable to fetch font")
}
p.message, err = NewStringItem(ctx.Msg, font, colors.Orange)
if err != nil {
return fmt.Errorf("unable to create message string texture: %w", err)
}
p.instructions, err = NewStringItem(ctx.Inst, font, colors.White)
if err != nil {
return fmt.Errorf("unable to create instructions string texture: %w", err)
}
baseFontSize := float32(p.Context.CfgPtr.StandardFontSize)
p.message.Scale(float32(48) / baseFontSize)
p.instructions.Scale(float32(28) / baseFontSize)
// Cache scaled dimensions — never recomputed unless textures are replaced
p.msgDim = p.message.RawDimensions()
p.instDim = p.instructions.RawDimensions()
p.msgPos = mgl32.Vec2{
float32(p.Base.ScreenCenterX) - p.msgDim[0]/2,
float32(p.Base.ScreenCenterY) - p.msgDim[1]/2,
}
p.instPos = mgl32.Vec2{
float32(p.Base.ScreenCenterX) - p.instDim[0]/2,
float32(20),
}
return nil
}
func (p *MessagePage) HandleEvent(event *sdl.Event) error {
return nil
}
func (p *MessagePage) Update(dt float32) error {
return nil
}
func (p *MessagePage) Render() error {
p.Base.RenderTexture(p.textShader, p.message.ID, p.msgPos, p.msgDim, colors.Orange)
p.Base.RenderTexture(p.textShader, p.instructions.ID, p.instPos, p.instDim, colors.White)
return nil
}
func (p *MessagePage) Destroy() error {
gl.DeleteTextures(1, &p.message.ID)
gl.DeleteTextures(1, &p.instructions.ID)
return p.Base.Destroy()
}
func (p *MessagePage) SetMessage(msg string) error {
return nil
}
func (p *MessagePage) SetInstructions(inst string) error {
return nil
}
+3 -3
View File
@@ -17,8 +17,8 @@ const (
LICENSE_KEY
EMAIL_ADDRESS
LOGS
CHECK_UPDATES
MESSAGE
DOWNLOADING_ASSETS
)
type PageCtx struct {
@@ -69,10 +69,10 @@ func (r *Router) NavigateTo(p pageType) {
r.ActivePage = &EmailAddressPage{}
case LOGS:
r.ActivePage = &LogViewerPage{}
case CHECK_UPDATES:
r.ActivePage = &UpdateCheckPage{}
case MESSAGE:
r.ActivePage = &MessagePage{}
case DOWNLOADING_ASSETS:
r.ActivePage = &DownloadingAssets{}
}
r.ActivePage.Init(&r.Context)
-188
View File
@@ -1,188 +0,0 @@
package page
import (
"fmt"
"os/exec"
"strings"
"github.com/go-gl/gl/v3.3-core/gl"
"github.com/veandco/go-sdl2/sdl"
"rhemawavetech.com/rhemawave/internal/colors"
"rhemawavetech.com/rhemawave/internal/fontManager"
"rhemawavetech.com/rhemawave/internal/shaderManager"
)
type updateCheckState int
const (
updateCheckStateChecking updateCheckState = iota
updateCheckStateDone
)
type UpdateCheckPage struct {
Base
textShader *shaderManager.Shader
state updateCheckState
// "Checking for Updates." / ".." / "..."
checkingTextures [3]StringItem
// "No updates available" and "Press F3 to return"
doneMessage StringItem
doneHint StringItem
// Error message if service failed to start
errorMessage StringItem
hasError bool
pollTimer float32
dotIndex int
dotTimer float32
}
func (p *UpdateCheckPage) Init(ctx *PageCtx) error {
var err error
if err := p.Base.Init(ctx); err != nil {
return fmt.Errorf("failed base page initialization: %w", err)
}
fm := fontManager.Get()
sm := shaderManager.Get()
font, ok := fm.GetFont("Roboto-Regular")
if !ok {
return fmt.Errorf("failed to get font")
}
p.textShader, ok = sm.Get("text")
if !ok {
return fmt.Errorf("failed to get text shader")
}
// Get scale
baseFontSize := ctx.CfgPtr.StandardFontSize
scale := float32(48) / float32(baseFontSize)
// Create checking textures with animated dots
dots := []string{"Checking for Updates.", "Checking for Updates..", "Checking for Updates..."}
for i, text := range dots {
item, err := NewStringItem(text, font, colors.White)
if err != nil {
return fmt.Errorf("creating checking texture %d: %w", i, err)
}
item.Scale(scale)
p.checkingTextures[i] = item
}
// Create done textures
hintScale := float32(32) / float32(baseFontSize)
p.doneMessage, err = NewStringItem("No updates available", font, colors.White)
if err != nil {
return fmt.Errorf("creating done message: %w", err)
}
p.doneMessage.Scale(scale)
p.doneHint, err = NewStringItem("Press F3 to return", font, colors.White)
if err != nil {
return fmt.Errorf("creating done hint: %w", err)
}
p.doneHint.Scale(hintScale)
// Start the update service
p.state = updateCheckStateChecking
if err := exec.Command("systemctl", "start", "nixos-upgrade.service").Run(); err != nil {
p.errorMessage, _ = NewStringItem("Update service unavailable", font, colors.White)
p.errorMessage.Scale(scale)
p.hasError = true
p.state = updateCheckStateDone
}
return nil
}
func (p *UpdateCheckPage) Update(dt float32) error {
if p.state != updateCheckStateChecking {
return nil
}
// Animate dots
p.dotTimer += dt
if p.dotTimer >= 0.5 {
p.dotTimer -= 0.5
p.dotIndex = (p.dotIndex + 1) % 3
}
// Poll service status every 2 seconds
p.pollTimer += dt
if p.pollTimer >= 2.0 {
p.pollTimer -= 2.0
output, _ := exec.Command("systemctl", "is-active", "rhemawave-update.service").Output()
status := strings.TrimSpace(string(output))
if status != "active" && status != "activating" {
p.state = updateCheckStateDone
}
}
return nil
}
func (p *UpdateCheckPage) HandleEvent(event *sdl.Event) error {
if p.state != updateCheckStateDone {
return nil
}
switch e := (*event).(type) {
case *sdl.KeyboardEvent:
if e.Type != sdl.KEYDOWN {
return nil
}
switch e.Keysym.Sym {
case sdl.K_F3, sdl.K_BACKSPACE:
p.Context.NavigateTo(SETTINGS)
}
}
return nil
}
func (p *UpdateCheckPage) Render() error {
switch p.state {
case updateCheckStateChecking:
item := p.checkingTextures[p.dotIndex]
item.X = p.ScreenCenterX - item.W/2
item.Y = p.ScreenCenterY - item.H/2
p.RenderTexture(p.textShader, item.ID, item.Position(), item.RawDimensions(), item.Color)
case updateCheckStateDone:
var msg *StringItem
if p.hasError {
msg = &p.errorMessage
} else {
msg = &p.doneMessage
}
msg.X = p.ScreenCenterX - msg.W/2
msg.Y = p.ScreenCenterY + msg.H/2
p.RenderTexture(p.textShader, msg.ID, msg.Position(), msg.RawDimensions(), msg.Color)
p.doneHint.X = p.ScreenCenterX - p.doneHint.W/2
p.doneHint.Y = msg.Y - p.doneHint.H - 20
p.RenderTexture(p.textShader, p.doneHint.ID, p.doneHint.Position(), p.doneHint.RawDimensions(), p.doneHint.Color)
}
return nil
}
func (p *UpdateCheckPage) Destroy() error {
for i := range p.checkingTextures {
gl.DeleteTextures(1, &p.checkingTextures[i].ID)
}
gl.DeleteTextures(1, &p.doneMessage.ID)
gl.DeleteTextures(1, &p.doneHint.ID)
if p.hasError {
gl.DeleteTextures(1, &p.errorMessage.ID)
}
return nil
}