refactor: remove cached AppConfig pointer and read configuration directly from DB
Replace in-memory atomic AppConfig caching with direct DB queries via db.GetConfig across application and page layers. This simplifies state management and ensures all components always operate on the latest persisted configuration. Key changes: - Remove Application.Config atomic cache and refreshCache mechanism - Eliminate PageCtx.CfgPtr and pass DB handle instead - Replace all cfg reads with db.GetConfig(app.DB) - Update mixer, audio, UI pages, and initialization paths accordingly - Explicitly set AppConfig table name to avoid GORM pluralization issues - Reduce DB connection pooling (SetMaxIdleConns(1)) - Standardize application font to SpaceMonoNerdFont-Regular - Lower default audio volume (1.0 → 0.2) - Add Unicode checkmark glyph to font map Behavioral impact: - Configuration is no longer cached in memory - Every config access now hits the DB (more consistent, slightly more overhead)
This commit is contained in:
@@ -1,28 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- Added proclamation sync when entering "proclamations" settings page
|
||||
|
||||
### Changed
|
||||
|
||||
- Changed audio devices page to be strictly an audio on/off toggle
|
||||
- Changed settings menu items to be left-aligned with eachother
|
||||
- Changed settings entry organization
|
||||
|
||||
### Deprecated
|
||||
|
||||
### Removed
|
||||
|
||||
- Removed list of audio devices from audio device page
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed audio device not being initialized on first entry to F2 screen
|
||||
|
||||
### Security
|
||||
|
||||
---
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/go-gl/gl/v3.3-core/gl"
|
||||
@@ -51,7 +50,6 @@ type Application struct {
|
||||
pendingAction func()
|
||||
running bool
|
||||
DB *gorm.DB
|
||||
Config atomic.Pointer[db.AppConfig]
|
||||
PageRouter *page.Router
|
||||
state State
|
||||
}
|
||||
@@ -112,7 +110,7 @@ func Run() {
|
||||
|
||||
// Populate the initial Config cache OR create defaults
|
||||
firstRun := false
|
||||
result = DB.First(&initialConfig)
|
||||
result = DB.Unscoped().First(&initialConfig)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
logger.Info("First run detected: Creating default configuration...")
|
||||
@@ -148,8 +146,6 @@ func Run() {
|
||||
app.state = FIRST_RUN
|
||||
}
|
||||
|
||||
app.refreshCache()
|
||||
|
||||
w, h := app.initializeSDLAndOpenGL()
|
||||
defer app.cleanup()
|
||||
|
||||
@@ -159,12 +155,10 @@ func Run() {
|
||||
downloadProgressChan := make(chan download.DownloadStatus, 1000)
|
||||
|
||||
app.PageRouter = page.NewRouter(page.PageCtx{
|
||||
CfgPtr: app.Config.Load(),
|
||||
DbPtr: app.DB,
|
||||
W: w,
|
||||
H: h,
|
||||
MessageChannel: downloadProgressChan,
|
||||
RefreshConfig: app.refreshCache,
|
||||
})
|
||||
|
||||
// Sync the proclamations from the API to the Database
|
||||
@@ -188,7 +182,12 @@ func Run() {
|
||||
"PinealGland.wav",
|
||||
}
|
||||
|
||||
go download.DownloadAudioFiles(app.PageRouter.Context.MessageChannel, audioFileNames, filepath.Join(app.PageRouter.Context.CfgPtr.AssetsDir, "audio"))
|
||||
config, err := db.GetConfig(app.DB)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go download.DownloadAudioFiles(app.PageRouter.Context.MessageChannel, audioFileNames, filepath.Join(config.AssetsDir, "audio"))
|
||||
|
||||
app.runEventLoop()
|
||||
}
|
||||
@@ -221,7 +220,12 @@ func (app *Application) checkState() {
|
||||
}
|
||||
|
||||
// Then check for an email address
|
||||
if app.Config.Load().EmailAddress == "" {
|
||||
config, err := db.GetConfig(app.DB)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if config.EmailAddress == "" {
|
||||
if app.state != NEEDS_EMAIL_ADDRESS {
|
||||
app.PageRouter.NavigateTo(page.EMAIL_ADDRESS)
|
||||
app.state = NEEDS_EMAIL_ADDRESS
|
||||
@@ -230,7 +234,11 @@ func (app *Application) checkState() {
|
||||
}
|
||||
|
||||
// Then check for a license key
|
||||
if app.Config.Load().LicenseKey == "" {
|
||||
config, err = db.GetConfig(app.DB)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if config.LicenseKey == "" {
|
||||
if app.state != NEEDS_LICENSE_KEY {
|
||||
app.PageRouter.NavigateTo(page.LICENSE_KEY)
|
||||
app.state = NEEDS_LICENSE_KEY
|
||||
@@ -242,14 +250,6 @@ func (app *Application) checkState() {
|
||||
app.PageRouter.NavigateTo(page.HOME)
|
||||
}
|
||||
|
||||
func (app *Application) refreshCache() {
|
||||
var freshConfig db.AppConfig
|
||||
if result := app.DB.First(&freshConfig); result.Error != nil {
|
||||
logger.Error("failed to fetch configuration from the database: %v", result.Error)
|
||||
}
|
||||
app.Config.Store(&freshConfig)
|
||||
}
|
||||
|
||||
func (app *Application) initializeSDLAndOpenGL() (W, H int32) {
|
||||
logger.Info("Initializing SDL")
|
||||
if err := sdl.Init(sdl.INIT_VIDEO | sdl.INIT_AUDIO); err != nil {
|
||||
@@ -324,29 +324,38 @@ func (app *Application) initializeSDLAndOpenGL() (W, H int32) {
|
||||
|
||||
func (app *Application) initializeManagers() {
|
||||
logger.Info("Initializing ShaderManager")
|
||||
shaderDir := filepath.Join(app.Config.Load().AssetsDir, "shaders")
|
||||
config, err := db.GetConfig(app.DB)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
shaderDir := filepath.Join(config.AssetsDir, "shaders")
|
||||
logger.Info("Loading shaders from %s", shaderDir)
|
||||
if err := shaderManager.InitShaderManager(shaderDir); err != nil {
|
||||
logger.Fatal("ShaderManager initialization failed: %v", err)
|
||||
}
|
||||
|
||||
logger.Info("Initializing FontManager")
|
||||
if err := fontManager.InitFontManager(app.Config.Load()); err != nil {
|
||||
if err := fontManager.InitFontManager(config); err != nil {
|
||||
logger.Fatal("FontManager initialization failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (app *Application) initializeAudio() {
|
||||
logger.Info("Initializing audio")
|
||||
|
||||
if err := mixer.Init(app.Config.Load(), app.refreshCache); err != nil {
|
||||
logger.Error("Unable to initialize audio device '%s': %v", app.Config.Load().SelectedAudioDevice, err)
|
||||
config, err := db.GetConfig(app.DB)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := mixer.Init(config, app.refreshCache); err != nil {
|
||||
logger.Error("Unable to initialize audio device '%s': %v", config.SelectedAudioDevice, err)
|
||||
logger.Error("Audio will be unavailable until a device is configured")
|
||||
} else {
|
||||
logger.Info("Audio initialized with device: '%s'", app.Config.Load().SelectedAudioDevice)
|
||||
logger.Info("Audio initialized with device: '%s'", config.SelectedAudioDevice)
|
||||
}
|
||||
}
|
||||
|
||||
func (app *Application) refreshCache() {}
|
||||
|
||||
func (app *Application) cleanup() {
|
||||
logger.Info("Cleaning up")
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ func InitFontManager(cfg *db.AppConfig) error {
|
||||
// --- NEW: Create the scrambled font after loading normal fonts ---
|
||||
// We will use "DejaVuSans" as the base. If you use a different default font,
|
||||
// change this string.
|
||||
baseFontForScramble := "Roboto-Regular"
|
||||
baseFontForScramble := "SpaceMonoNerdFont-Regular"
|
||||
if _, ok := fm.Fonts[baseFontForScramble]; ok {
|
||||
if err := fm.CreateScrambledFont(baseFontForScramble, "Scrambled"); err != nil {
|
||||
// This is not a fatal error for the whole application, so we just log it.
|
||||
@@ -526,6 +526,7 @@ func (fm *FontManager) createFontMap(font *FontEntry, scramble bool, baseFont *F
|
||||
8482, // ™
|
||||
232, // è
|
||||
233, // é
|
||||
10003, // checkmark
|
||||
}
|
||||
tempGlyphs := make([]TempGlyph, 0, len(chars))
|
||||
var totalWidth, maxHeight int32
|
||||
|
||||
@@ -70,7 +70,7 @@ func Init(cfg *db.AppConfig, onUpdate func()) error {
|
||||
return err
|
||||
}
|
||||
|
||||
SetAllSinkVolumes(1.0)
|
||||
SetAllSinkVolumes(0.20)
|
||||
|
||||
inited = true
|
||||
return nil
|
||||
|
||||
@@ -100,7 +100,7 @@ func (p *AudioOptions) Init(ctx *PageCtx) error {
|
||||
|
||||
// Font
|
||||
fm := fontManager.Get()
|
||||
font, ok := fm.GetFont("Roboto-Regular")
|
||||
font, ok := fm.GetFont("SpaceMonoNerdFont-Regular")
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to get font: %w", sdl.GetError())
|
||||
}
|
||||
@@ -121,7 +121,12 @@ func (p *AudioOptions) Init(ctx *PageCtx) error {
|
||||
return fmt.Errorf("base init failed: %w", err)
|
||||
}
|
||||
|
||||
baseFontSize := p.Context.CfgPtr.StandardFontSize
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
baseFontSize := config.StandardFontSize
|
||||
titleScale := float32(64) / float32(baseFontSize)
|
||||
p.ItemScale = float32(32) / float32(baseFontSize)
|
||||
|
||||
@@ -211,7 +216,11 @@ func (p *AudioOptions) seedAudioFiles() error {
|
||||
// ── Audio status toggle ───────────────────────────────────────────────────────
|
||||
|
||||
func (p *AudioOptions) CreateAudioStatusItem() error {
|
||||
on := p.Context.CfgPtr.AudioEnabled
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
on := config.AudioEnabled
|
||||
statusString := "Turn Audio On"
|
||||
color := colors.Green
|
||||
if on {
|
||||
@@ -277,7 +286,11 @@ func (p *AudioOptions) CreateVolumePercentItem() error {
|
||||
if p.volumePercent.ID != 0 {
|
||||
gl.DeleteTextures(1, &p.volumePercent.ID)
|
||||
}
|
||||
pct := int(p.Context.CfgPtr.SavedVolume * 100)
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pct := int(config.SavedVolume * 100)
|
||||
item, err := NewStringItem(fmt.Sprintf("%d%%", pct), p.font, colors.White)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create volume percent item: %v", err)
|
||||
@@ -288,15 +301,19 @@ func (p *AudioOptions) CreateVolumePercentItem() error {
|
||||
}
|
||||
|
||||
func (p *AudioOptions) UpdateVolume(level int) {
|
||||
newVol := mixer.ConvertVolume(level) + p.Context.CfgPtr.SavedVolume
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
newVol := mixer.ConvertVolume(level) + config.SavedVolume
|
||||
if newVol < 0.0 || newVol > 1.0 {
|
||||
return
|
||||
}
|
||||
if newVol > .99 {
|
||||
newVol = 1.0
|
||||
}
|
||||
p.Context.CfgPtr.SavedVolume = newVol
|
||||
p.Context.DbPtr.Save(&p.Context.CfgPtr)
|
||||
config.SavedVolume = newVol
|
||||
p.Context.DbPtr.Save(&config)
|
||||
if err := mixer.SetAllSinkVolumes(newVol); err != nil {
|
||||
logger.Error("Error setting allSinkVolumes: %v", err)
|
||||
}
|
||||
@@ -311,6 +328,11 @@ func (p *AudioOptions) UpdateVolume(level int) {
|
||||
// ── Layout ────────────────────────────────────────────────────────────────────
|
||||
|
||||
func (p *AudioOptions) layout() {
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Title
|
||||
p.title.X = p.ScreenCenterX - p.title.W/2
|
||||
p.title.Y = p.ScreenHeight - p.title.H - p.verticalMargin*2
|
||||
@@ -320,7 +342,7 @@ func (p *AudioOptions) layout() {
|
||||
p.prompt.Y = p.title.Y - p.verticalMargin - p.prompt.H
|
||||
|
||||
// Volume row
|
||||
barH := int32(float32(p.Context.CfgPtr.StandardFontSize) * p.ItemScale)
|
||||
barH := int32(float32(config.StandardFontSize) * p.ItemScale)
|
||||
barW := int32(float32(p.ScreenWidth) * 0.30)
|
||||
barX := p.ScreenCenterX - barW/2
|
||||
barY := p.prompt.Y - p.verticalMargin*2 - barH
|
||||
@@ -376,8 +398,12 @@ func (p *AudioOptions) updateCursorPosition() {
|
||||
// ── Toggle ────────────────────────────────────────────────────────────────────
|
||||
|
||||
func (p *AudioOptions) ToggleAudio() {
|
||||
p.Context.CfgPtr.AudioEnabled = !p.Context.CfgPtr.AudioEnabled
|
||||
p.Context.DbPtr.Save(p.Context.CfgPtr)
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
config.AudioEnabled = !config.AudioEnabled
|
||||
p.Context.DbPtr.Save(config)
|
||||
p.Context.RefreshConfig()
|
||||
p.CreateAudioStatusItem()
|
||||
p.layout()
|
||||
@@ -447,7 +473,11 @@ func (p *AudioOptions) Update(dt float32) error {
|
||||
// ── Render helpers ────────────────────────────────────────────────────────────
|
||||
|
||||
func (p *AudioOptions) renderVolumeBar() error {
|
||||
vol := p.Context.CfgPtr.SavedVolume
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
vol := config.SavedVolume
|
||||
|
||||
fillW := float32(p.volumeBarW) * float32(vol)
|
||||
if fillW > 0 {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/go-gl/mathgl/mgl32"
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
"rhemawavetech.com/rhemawave/internal/colors"
|
||||
"rhemawavetech.com/rhemawave/internal/db"
|
||||
"rhemawavetech.com/rhemawave/internal/fontManager"
|
||||
"rhemawavetech.com/rhemawave/internal/shaderManager"
|
||||
)
|
||||
@@ -59,7 +60,7 @@ func (p *EmailAddressPage) Init(ctx *PageCtx) error {
|
||||
|
||||
p.title = "Your Email Address"
|
||||
|
||||
applicationFont := "Roboto-Regular"
|
||||
applicationFont := "SpaceMonoNerdFont-Regular"
|
||||
|
||||
fm := fontManager.Get()
|
||||
textShader, ok := shaderManager.Get().Get("text")
|
||||
@@ -81,7 +82,11 @@ func (p *EmailAddressPage) Init(ctx *PageCtx) error {
|
||||
p.titleTextureHeight = titleHeight
|
||||
|
||||
// Load existing email address from database
|
||||
emailAddress := ctx.CfgPtr.EmailAddress
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
emailAddress := config.EmailAddress
|
||||
|
||||
if emailAddress != "" {
|
||||
p.inputText = emailAddress
|
||||
@@ -154,9 +159,12 @@ func (p *EmailAddressPage) HandleEvent(event *sdl.Event) error {
|
||||
sdl.StopTextInput()
|
||||
|
||||
// Save email address to database
|
||||
p.Context.CfgPtr.EmailAddress = p.inputText
|
||||
p.Context.DbPtr.Save(p.Context.CfgPtr)
|
||||
p.Context.RefreshConfig()
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
config.EmailAddress = p.inputText
|
||||
p.Context.DbPtr.Save(config)
|
||||
|
||||
if p.isFirstTimeSetup {
|
||||
// First-time setup: navigate to License Key page
|
||||
@@ -189,7 +197,7 @@ func (p *EmailAddressPage) 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 *EmailAddressPage) Update(dt float32) error {
|
||||
// Get application font from database
|
||||
applicationFont := "Roboto-Regular"
|
||||
applicationFont := "SpaceMonoNerdFont-Regular"
|
||||
|
||||
fm := fontManager.Get()
|
||||
sm := shaderManager.Get()
|
||||
@@ -252,8 +260,12 @@ func (p *EmailAddressPage) Update(dt float32) error {
|
||||
|
||||
// Render performs page drawing logic.
|
||||
func (p *EmailAddressPage) Render() error {
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// Get base font size from database
|
||||
baseFontSize := p.Context.CfgPtr.StandardFontSize
|
||||
baseFontSize := config.StandardFontSize
|
||||
|
||||
sm := shaderManager.Get()
|
||||
|
||||
|
||||
+13
-7
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/go-gl/mathgl/mgl32"
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
"rhemawavetech.com/rhemawave/internal/colors"
|
||||
"rhemawavetech.com/rhemawave/internal/db"
|
||||
"rhemawavetech.com/rhemawave/internal/download"
|
||||
"rhemawavetech.com/rhemawave/internal/fontManager"
|
||||
"rhemawavetech.com/rhemawave/internal/shaderManager"
|
||||
@@ -45,7 +46,7 @@ func (p *Home) Init(ctx *PageCtx) error {
|
||||
|
||||
// Get font
|
||||
p.fm = fontManager.Get()
|
||||
font, ok := p.fm.GetFont("Roboto-Regular")
|
||||
font, ok := p.fm.GetFont("SpaceMonoNerdFont-Regular")
|
||||
if !ok {
|
||||
return fmt.Errorf("unable to fetch font")
|
||||
}
|
||||
@@ -86,8 +87,13 @@ func (p *Home) Init(ctx *PageCtx) error {
|
||||
return fmt.Errorf("unable to create initial message texture: %w", err)
|
||||
}
|
||||
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Create license info textures if data exists
|
||||
if p.Context.CfgPtr.EmailAddress != "" || p.Context.CfgPtr.LicenseKey != "" {
|
||||
if config.EmailAddress != "" || config.LicenseKey != "" {
|
||||
p.hasLicenseInfo = true
|
||||
|
||||
// Create heading
|
||||
@@ -97,8 +103,8 @@ func (p *Home) Init(ctx *PageCtx) error {
|
||||
}
|
||||
|
||||
// Create email display if exists
|
||||
if p.Context.CfgPtr.EmailAddress != "" {
|
||||
emailText := fmt.Sprintf("Email: %s", p.Context.CfgPtr.EmailAddress)
|
||||
if config.EmailAddress != "" {
|
||||
emailText := fmt.Sprintf("Email: %s", config.EmailAddress)
|
||||
p.emailDisplay, err = NewStringItem(emailText, font, colors.White)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create email display texture: %w", err)
|
||||
@@ -106,8 +112,8 @@ func (p *Home) Init(ctx *PageCtx) error {
|
||||
}
|
||||
|
||||
// Create license key display if exists
|
||||
if p.Context.CfgPtr.LicenseKey != "" {
|
||||
licenseKeyText := fmt.Sprintf("License Key: %s", p.Context.CfgPtr.LicenseKey)
|
||||
if config.LicenseKey != "" {
|
||||
licenseKeyText := fmt.Sprintf("License Key: %s", config.LicenseKey)
|
||||
p.licenseKeyDisplay, err = NewStringItem(licenseKeyText, font, colors.White)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create license key display texture: %w", err)
|
||||
@@ -116,7 +122,7 @@ func (p *Home) Init(ctx *PageCtx) error {
|
||||
}
|
||||
|
||||
// Get base font size from database
|
||||
baseFontSize := p.Context.CfgPtr.StandardFontSize
|
||||
baseFontSize := config.StandardFontSize
|
||||
p.baseFontSize = baseFontSize
|
||||
|
||||
// Scale the note text
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/go-gl/mathgl/mgl32"
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
"rhemawavetech.com/rhemawave/internal/colors"
|
||||
"rhemawavetech.com/rhemawave/internal/db"
|
||||
"rhemawavetech.com/rhemawave/internal/fontManager"
|
||||
"rhemawavetech.com/rhemawave/internal/logger"
|
||||
"rhemawavetech.com/rhemawave/internal/shaderManager"
|
||||
@@ -55,7 +56,7 @@ func (p *LicenseKeyPage) Init(ctx *PageCtx) error {
|
||||
p.title = "License Key"
|
||||
|
||||
// Get application font from database
|
||||
applicationFont := "Roboto-Regular"
|
||||
applicationFont := "SpaceMonoNerdFont-Regular"
|
||||
|
||||
fm := fontManager.Get()
|
||||
textShader, ok := shaderManager.Get().Get("text")
|
||||
@@ -77,7 +78,11 @@ func (p *LicenseKeyPage) Init(ctx *PageCtx) error {
|
||||
p.titleTextureHeight = titleHeight
|
||||
|
||||
// Load existing license key from database
|
||||
licenseKey := p.Context.CfgPtr.LicenseKey
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
licenseKey := config.LicenseKey
|
||||
|
||||
if licenseKey != "" {
|
||||
p.inputText = licenseKey
|
||||
@@ -188,9 +193,12 @@ func (p *LicenseKeyPage) HandleEvent(event *sdl.Event) error {
|
||||
sdl.StopTextInput()
|
||||
|
||||
// Save license key to database
|
||||
p.Context.CfgPtr.LicenseKey = p.inputText
|
||||
p.Context.DbPtr.Save(p.Context.CfgPtr)
|
||||
p.Context.RefreshConfig()
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
config.LicenseKey = p.inputText
|
||||
p.Context.DbPtr.Save(config)
|
||||
|
||||
// Write license key to plain text file for the updater
|
||||
if homeDir, err := os.UserHomeDir(); err == nil {
|
||||
@@ -239,7 +247,7 @@ func (p *LicenseKeyPage) 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 *LicenseKeyPage) Update(dt float32) error {
|
||||
// Get application font from database
|
||||
applicationFont := "Roboto-Regular"
|
||||
applicationFont := "SpaceMonoNerdFont-Regular"
|
||||
|
||||
fm := fontManager.Get()
|
||||
sm := shaderManager.Get()
|
||||
@@ -302,8 +310,12 @@ func (p *LicenseKeyPage) Update(dt float32) error {
|
||||
|
||||
// Render performs page drawing logic.
|
||||
func (p *LicenseKeyPage) Render() error {
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// Get base font size from database
|
||||
baseFontSize := p.Context.CfgPtr.StandardFontSize
|
||||
baseFontSize := config.StandardFontSize
|
||||
|
||||
sm := shaderManager.Get()
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ func (p *LogViewerPage) Init(ctx *PageCtx) error {
|
||||
p.lineColors = append(p.lineColors, color)
|
||||
}
|
||||
|
||||
applicationFont := "Roboto-Regular"
|
||||
applicationFont := "SpaceMonoNerdFont-Regular"
|
||||
|
||||
fm := fontManager.Get()
|
||||
textShader, ok := shaderManager.Get().Get("text")
|
||||
@@ -177,7 +177,11 @@ func (p *LogViewerPage) Update(dt float32) error {
|
||||
}
|
||||
|
||||
func (p *LogViewerPage) Render() error {
|
||||
baseFontSize := p.Context.CfgPtr.StandardFontSize
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
baseFontSize := config.StandardFontSize
|
||||
|
||||
sm := shaderManager.Get()
|
||||
textShader, _ := sm.Get("text")
|
||||
|
||||
@@ -105,7 +105,7 @@ func (p *ProclamationOptions) Init(ctx *PageCtx) error {
|
||||
sync.SyncFrequencies(ctx.DbPtr)
|
||||
|
||||
fm := fontManager.Get()
|
||||
font, _ := fm.GetFont("Roboto-Regular")
|
||||
font, _ := fm.GetFont("SpaceMonoNerdFont-Regular")
|
||||
p.font = font
|
||||
|
||||
sm := shaderManager.Get()
|
||||
@@ -114,9 +114,14 @@ func (p *ProclamationOptions) Init(ctx *PageCtx) error {
|
||||
|
||||
p.Base.Init(ctx)
|
||||
|
||||
itemScale := float32(32) / float32(ctx.CfgPtr.StandardFontSize)
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
itemScale := float32(32) / float32(config.StandardFontSize)
|
||||
p.title, _ = NewStringItem("Proclamation Browser", p.font, colors.White)
|
||||
p.title.Scale(float32(64) / float32(ctx.CfgPtr.StandardFontSize))
|
||||
p.title.Scale(float32(64) / float32(config.StandardFontSize))
|
||||
|
||||
p.prompt, _ = NewStringItem("Type to Search Space to Select Enter to Save Escape to Exit", p.font, colors.White)
|
||||
p.prompt.Scale(itemScale * 0.8)
|
||||
@@ -183,7 +188,11 @@ func (p *ProclamationOptions) createFlatItem(name, id string, isCat bool, depth
|
||||
if isCat && depth == 0 {
|
||||
text = "[+] " + name
|
||||
}
|
||||
itemScale := float32(32) / float32(p.Context.CfgPtr.StandardFontSize)
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
itemScale := float32(32) / float32(config.StandardFontSize)
|
||||
lbl, _ := NewStringItem(text, p.font, colors.White)
|
||||
lbl.Scale(itemScale)
|
||||
return &FlatItem{
|
||||
@@ -277,7 +286,12 @@ func (p *ProclamationOptions) toggleExpansion(index int) {
|
||||
pureName := item.Label.content[4:]
|
||||
gl.DeleteTextures(1, &item.Label.ID)
|
||||
|
||||
itemScale := float32(32) / float32(p.Context.CfgPtr.StandardFontSize)
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
itemScale := float32(32) / float32(config.StandardFontSize)
|
||||
if item.Expanded {
|
||||
p.collapse(index)
|
||||
item.Label, _ = NewStringItem("[+] "+pureName, p.font, colors.White)
|
||||
@@ -401,7 +415,11 @@ func (p *ProclamationOptions) rebuildSearchLabel() {
|
||||
if p.searchQuery == "" {
|
||||
return
|
||||
}
|
||||
itemScale := float32(32) / float32(p.Context.CfgPtr.StandardFontSize)
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
itemScale := float32(32) / float32(config.StandardFontSize)
|
||||
p.searchInput, _ = NewStringItem("Search: "+p.searchQuery, p.font, colors.Yellow)
|
||||
p.searchInput.Scale(itemScale * 1.1)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package page
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
"rhemawavetech.com/rhemawave/internal/db"
|
||||
"rhemawavetech.com/rhemawave/internal/download"
|
||||
)
|
||||
|
||||
@@ -23,7 +22,6 @@ const (
|
||||
)
|
||||
|
||||
type PageCtx struct {
|
||||
CfgPtr *db.AppConfig
|
||||
DbPtr *gorm.DB
|
||||
W, H int32
|
||||
MessageChannel chan download.DownloadStatus
|
||||
|
||||
@@ -220,8 +220,11 @@ func (p *ScrollerPage) Init(ctx *PageCtx) error {
|
||||
}
|
||||
|
||||
// Get line pattern from database
|
||||
var err error
|
||||
linePatternName := p.Context.CfgPtr.LinePattern
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
linePatternName := config.LinePattern
|
||||
|
||||
p.activePattern, err = linePattern.Get(linePatternName)
|
||||
if err != nil {
|
||||
@@ -241,7 +244,7 @@ func (p *ScrollerPage) Init(ctx *PageCtx) error {
|
||||
p.colorPattern = colorPattern.NewColorPattern(baseColors)
|
||||
|
||||
// Font setup
|
||||
p.fontScale = float32(32) / float32(p.Context.CfgPtr.StandardFontSize)
|
||||
p.fontScale = float32(32) / float32(config.StandardFontSize)
|
||||
nLines := int(float32(p.ScreenHeight) / 32.0)
|
||||
p.lines = NewLineDeque(nLines * 2)
|
||||
|
||||
@@ -288,14 +291,14 @@ func (p *ScrollerPage) Init(ctx *PageCtx) error {
|
||||
if err := p.Context.DbPtr.Where("Selected = ?", true).First(&selectedAudio).Error; err != nil {
|
||||
selectedAudio = db.AudioFile{
|
||||
Name: "OriginalAudio",
|
||||
Path: filepath.Join(p.Context.CfgPtr.AssetsDir, "audio", "OriginalAudio.wav"),
|
||||
Path: filepath.Join(config.AssetsDir, "audio", "OriginalAudio.wav"),
|
||||
Selected: true,
|
||||
Order: 0,
|
||||
}
|
||||
}
|
||||
|
||||
logger.Info("Playing %s", selectedAudio.Path)
|
||||
if err := mixer.Play(selectedAudio.Path, true, p.Context.CfgPtr); err != nil {
|
||||
if err := mixer.Play(selectedAudio.Path, true, config); err != nil {
|
||||
logger.Error("Mixer returned an error: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -420,7 +423,11 @@ func (p *ScrollerPage) loadProclamations() error {
|
||||
// audioPathForFrequency builds the on-disk path for a solfeggio frequency's
|
||||
// audio file, e.g. 396 -> "<AssetsDir>/audio/396Hz.wav".
|
||||
func (p *ScrollerPage) audioPathForFrequency(freq int) string {
|
||||
return filepath.Join(p.Context.CfgPtr.AssetsDir, "audio", fmt.Sprintf("%dHz.wav", freq))
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return filepath.Join(config.AssetsDir, "audio", fmt.Sprintf("%dHz.wav", freq))
|
||||
}
|
||||
|
||||
// switchAudioForFrequency swaps the currently playing track to match freq.
|
||||
@@ -449,9 +456,12 @@ func (p *ScrollerPage) switchAudioForFrequency(freq int) bool {
|
||||
logger.Warning("No audio file for %dHz (%s), keeping current track", freq, path)
|
||||
return false
|
||||
}
|
||||
|
||||
mixer.Stop(3000, p.Context.CfgPtr)
|
||||
if err := mixer.Play(path, true, p.Context.CfgPtr); err != nil {
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
mixer.Stop(3000, config)
|
||||
if err := mixer.Play(path, true, config); err != nil {
|
||||
logger.Error("Mixer returned an error: %v", err)
|
||||
return false
|
||||
}
|
||||
@@ -722,7 +732,12 @@ func (p *ScrollerPage) Destroy() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
mixer.Stop(3000, p.Context.CfgPtr)
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mixer.Stop(3000, config)
|
||||
|
||||
// Delete each cached word texture exactly once.
|
||||
for k, item := range p.wordTextureCache {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"github.com/go-gl/gl/v3.3-core/gl"
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
"rhemawavetech.com/rhemawave/internal/colors"
|
||||
"rhemawavetech.com/rhemawave/internal/db"
|
||||
"rhemawavetech.com/rhemawave/internal/fontManager"
|
||||
"rhemawavetech.com/rhemawave/internal/shaderManager"
|
||||
)
|
||||
@@ -34,7 +35,7 @@ func (p *Settings) Init(ctx *PageCtx) error {
|
||||
|
||||
// Get font
|
||||
fm := fontManager.Get()
|
||||
font, ok := fm.GetFont("Roboto-Regular")
|
||||
font, ok := fm.GetFont("SpaceMonoNerdFont-Regular")
|
||||
if !ok {
|
||||
return fmt.Errorf("failed to get font: %w", sdl.GetError())
|
||||
}
|
||||
@@ -127,7 +128,11 @@ func (p *Settings) Init(ctx *PageCtx) error {
|
||||
// TODO: Add entry for "About"
|
||||
|
||||
// Get base font size from database
|
||||
baseFontSize := p.Context.CfgPtr.StandardFontSize
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
baseFontSize := config.StandardFontSize
|
||||
|
||||
// Calculate scales
|
||||
titleScale := float32(64) / float32(baseFontSize)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/go-gl/mathgl/mgl32"
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
"rhemawavetech.com/rhemawave/internal/colors"
|
||||
"rhemawavetech.com/rhemawave/internal/db"
|
||||
"rhemawavetech.com/rhemawave/internal/fontManager"
|
||||
"rhemawavetech.com/rhemawave/internal/keybinds"
|
||||
"rhemawavetech.com/rhemawave/internal/logger"
|
||||
@@ -39,6 +40,7 @@ type WiFiSetupPage struct {
|
||||
applicationFont *fontManager.FontEntry
|
||||
|
||||
// UI elements
|
||||
BaseFontSize int
|
||||
titleItem StringItem
|
||||
scanningStatusItem StringItem
|
||||
connectionStatusItem StringItem
|
||||
@@ -75,9 +77,9 @@ func (p *WiFiSetupPage) Init(ctx *PageCtx) error {
|
||||
}
|
||||
|
||||
fm := fontManager.Get()
|
||||
font, ok := fm.GetFont("Roboto-Regular")
|
||||
font, ok := fm.GetFont("SpaceMonoNerdFont-Regular")
|
||||
if !ok {
|
||||
return fmt.Errorf("could not find application font: Roboto-Regular")
|
||||
return fmt.Errorf("could not find application font: SpaceMonoNerdFont-Regular")
|
||||
}
|
||||
p.applicationFont = font
|
||||
|
||||
@@ -92,6 +94,12 @@ func (p *WiFiSetupPage) Init(ctx *PageCtx) error {
|
||||
return fmt.Errorf("failed to create scanning status item: %w", err)
|
||||
}
|
||||
|
||||
config, err := db.GetConfig(p.Context.DbPtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
p.BaseFontSize = config.StandardFontSize
|
||||
|
||||
p.connectResultCh = make(chan error, 1)
|
||||
p.ctx, p.cancel = context.WithCancel(context.Background())
|
||||
|
||||
@@ -310,7 +318,20 @@ func (p *WiFiSetupPage) rebuildNetworkList(nets []network.Network) {
|
||||
label += " ★"
|
||||
}
|
||||
if n.Security != network.SecurityOpen {
|
||||
label += " [" + string(n.Security) + "]"
|
||||
var secStr string
|
||||
switch n.Security {
|
||||
case network.SecurityWEP:
|
||||
secStr = "WEP"
|
||||
case network.SecurityWPA:
|
||||
secStr = "WPA"
|
||||
case network.SecurityWPA2:
|
||||
secStr = "WPA2"
|
||||
case network.SecurityWPA3:
|
||||
secStr = "WPA3"
|
||||
default:
|
||||
secStr = "Secured"
|
||||
}
|
||||
label += " [" + secStr + "]"
|
||||
}
|
||||
|
||||
c := colors.White
|
||||
@@ -417,8 +438,6 @@ func (p *WiFiSetupPage) rebuildPasswordErrorTexture() {
|
||||
// ─── Render ───────────────────────────────────────────────────────────────────
|
||||
|
||||
func (p *WiFiSetupPage) Render() error {
|
||||
baseFontSize := p.Context.CfgPtr.StandardFontSize
|
||||
|
||||
solidShader, _ := shaderManager.Get().Get("solid_color")
|
||||
textShader, _ := shaderManager.Get().Get("text")
|
||||
|
||||
@@ -435,7 +454,7 @@ func (p *WiFiSetupPage) Render() error {
|
||||
)
|
||||
|
||||
// Title — 48pt
|
||||
titleScale := float32(48) / float32(baseFontSize)
|
||||
titleScale := float32(48) / float32(p.BaseFontSize)
|
||||
titleW := float32(p.titleItem.W) * titleScale
|
||||
titleH := float32(p.titleItem.H) * titleScale
|
||||
titleX := float32(p.ScreenCenterX) - titleW/2
|
||||
@@ -449,7 +468,7 @@ func (p *WiFiSetupPage) Render() error {
|
||||
// Status message — 30pt (was 24pt, now 1.25x)
|
||||
statusY := titleY - titleH - vertMargin
|
||||
if p.status == wifiStatusScanning {
|
||||
scale := float32(30) / float32(baseFontSize)
|
||||
scale := float32(30) / float32(p.BaseFontSize)
|
||||
w := float32(p.scanningStatusItem.W) * scale
|
||||
h := float32(p.scanningStatusItem.H) * scale
|
||||
x := float32(p.ScreenCenterX) - w/2
|
||||
@@ -459,7 +478,7 @@ func (p *WiFiSetupPage) Render() error {
|
||||
white,
|
||||
)
|
||||
} else if p.connectionStatusItem.ID != 0 {
|
||||
scale := float32(30) / float32(baseFontSize)
|
||||
scale := float32(30) / float32(p.BaseFontSize)
|
||||
w := float32(p.connectionStatusItem.W) * scale
|
||||
h := float32(p.connectionStatusItem.H) * scale
|
||||
x := float32(p.ScreenCenterX) - w/2
|
||||
@@ -488,7 +507,7 @@ func (p *WiFiSetupPage) Render() error {
|
||||
)
|
||||
}
|
||||
|
||||
scale := float32(24) / float32(baseFontSize)
|
||||
scale := float32(24) / float32(p.BaseFontSize)
|
||||
tw := float32(item.Item.W) * scale
|
||||
th := float32(item.Item.H) * scale
|
||||
tx := listX + float32(listPad)
|
||||
@@ -502,7 +521,7 @@ func (p *WiFiSetupPage) Render() error {
|
||||
|
||||
// Password dialog
|
||||
if p.isEnteringPassword {
|
||||
if err := p.renderPasswordDialog(solidShader, textShader, float32(baseFontSize)); err != nil {
|
||||
if err := p.renderPasswordDialog(solidShader, textShader, float32(p.BaseFontSize)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user