Change menu text from gray to white

This commit is contained in:
NeilClack
2026-08-13 14:34:49 -05:00
parent c35f928c85
commit 4abcfa473f
2 changed files with 249 additions and 151 deletions
+123 -71
View File
@@ -16,7 +16,7 @@
#include <algorithm>
#ifndef APP_VERSION
#define APP_VERSION "unknown"
#define APP_VERSION "dev"
#endif
static TextLine renderText(SDL_Renderer *renderer, TTF_Font *font, const char *text, SDL_Color color)
@@ -47,12 +47,10 @@ void Home::onPush(AppState &state)
refreshStatus();
state.licenseTracker.refresh();
state.keybinds.bind(SDLK_UP, "menu_up", [this]() {
state_->currentMenuItem = (state_->currentMenuItem + 1) % 2;
});
state.keybinds.bind(SDLK_DOWN, "menu_down", [this]() {
state_->currentMenuItem = (state_->currentMenuItem + 1) % 2;
});
state.keybinds.bind(SDLK_UP, "menu_up", [this]()
{ state_->currentMenuItem = (state_->currentMenuItem + 1) % 2; });
state.keybinds.bind(SDLK_DOWN, "menu_down", [this]()
{ state_->currentMenuItem = (state_->currentMenuItem + 1) % 2; });
}
void Home::onResume(AppState &state)
@@ -63,12 +61,10 @@ void Home::onResume(AppState &state)
refreshStatus();
state.licenseTracker.refresh();
state.keybinds.bind(SDLK_UP, "menu_up", [this]() {
state_->currentMenuItem = (state_->currentMenuItem + 1) % 2;
});
state.keybinds.bind(SDLK_DOWN, "menu_down", [this]() {
state_->currentMenuItem = (state_->currentMenuItem + 1) % 2;
});
state.keybinds.bind(SDLK_UP, "menu_up", [this]()
{ state_->currentMenuItem = (state_->currentMenuItem + 1) % 2; });
state.keybinds.bind(SDLK_DOWN, "menu_down", [this]()
{ state_->currentMenuItem = (state_->currentMenuItem + 1) % 2; });
}
void Home::onPause(AppState &state)
@@ -85,15 +81,22 @@ void Home::onPop(AppState &state)
void Home::handleEvent(const SDL_Event &event)
{
if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_RETURN) {
if (state_->currentMenuItem == 0) {
if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_RETURN)
{
if (state_->currentMenuItem == 0)
{
// Only a confirmed-valid license unlocks the scroller.
if (state_->licenseTracker.isValid()) {
if (state_->licenseTracker.isValid())
{
state_->pages.push(*state_, std::make_unique<ScrollerPage>());
} else {
}
else
{
state_->pages.push(*state_, std::make_unique<LicenseBlockedPage>());
}
} else if (state_->currentMenuItem == 1) {
}
else if (state_->currentMenuItem == 1)
{
state_->pages.replace(*state_, std::make_unique<Settings>());
}
}
@@ -102,7 +105,8 @@ void Home::handleEvent(const SDL_Event &event)
void Home::update(float dt)
{
internetRefreshTimer_ -= dt;
if (internetRefreshTimer_ <= 0.0f) {
if (internetRefreshTimer_ <= 0.0f)
{
internetRefreshTimer_ = 5.0f;
refreshStatus();
}
@@ -133,7 +137,8 @@ void Home::render(SDL_Renderer *renderer)
SDL_FRect overlay{0, 0, fw, fh};
SDL_RenderFillRect(renderer, &overlay);
if (!title_.texture) return;
if (!title_.texture)
return;
float titleX = (fw - title_.width) / 2.0f;
float titleY = fh / 3.0f - 60.0f;
@@ -194,30 +199,31 @@ void Home::render(SDL_Renderer *renderer)
std::string licenseValue;
SDL_Color licenseColor = footerColor;
bool licenseBold = false;
switch (licenseStatus) {
case radiantwave::license::Status::Valid:
licenseValue = "OK";
licenseColor = okGreen;
break;
case radiantwave::license::Status::Invalid:
licenseValue = "Invalid";
licenseColor = badRed;
licenseBold = true;
break;
case radiantwave::license::Status::Checking:
licenseValue = "Checking...";
break;
case radiantwave::license::Status::Unknown:
licenseValue = "Unknown";
break;
switch (licenseStatus)
{
case radiantwave::license::Status::Valid:
licenseValue = "OK";
licenseColor = okGreen;
break;
case radiantwave::license::Status::Invalid:
licenseValue = "Invalid";
licenseColor = badRed;
licenseBold = true;
break;
case radiantwave::license::Status::Checking:
licenseValue = "Checking...";
break;
case radiantwave::license::Status::Unknown:
licenseValue = "Unknown";
break;
}
int subscriptionLevelId = state_
? radiantwave::license::getStoredSubscriptionLevelId(state_->db)
: 0;
? radiantwave::license::getStoredSubscriptionLevelId(state_->db)
: 0;
std::string subscriptionValue = subscriptionLevelId > 0
? radiantwave::license::subscriptionLevelName(subscriptionLevelId)
: std::string("Not set");
? radiantwave::license::subscriptionLevelName(subscriptionLevelId)
: std::string("Not set");
time_t now = std::time(nullptr);
std::vector<std::string> names = {
@@ -250,23 +256,32 @@ void Home::render(SDL_Renderer *renderer)
valueColors[1] = licenseColor;
valueBold[1] = licenseBold;
if (footerNames_.size() != names.size()) footerNames_.resize(names.size());
if (footerValues_.size() != values.size()) footerValues_.resize(values.size());
for (size_t i = 0; i < names.size(); ++i) {
if (footerNames_.size() != names.size())
footerNames_.resize(names.size());
if (footerValues_.size() != values.size())
footerValues_.resize(values.size());
for (size_t i = 0; i < names.size(); ++i)
{
footerNames_[i].ensure(renderer, footerFont_, names[i], footerColor);
}
for (size_t i = 0; i < values.size(); ++i) {
if (valueBold[i]) TTF_SetFontStyle(footerFont_, TTF_STYLE_BOLD);
for (size_t i = 0; i < values.size(); ++i)
{
if (valueBold[i])
TTF_SetFontStyle(footerFont_, TTF_STYLE_BOLD);
footerValues_[i].ensure(renderer, footerFont_, values[i], valueColors[i],
valueBold[i] ? TTF_STYLE_BOLD : TTF_STYLE_NORMAL);
if (valueBold[i]) TTF_SetFontStyle(footerFont_, TTF_STYLE_NORMAL);
valueBold[i] ? TTF_STYLE_BOLD : TTF_STYLE_NORMAL);
if (valueBold[i])
TTF_SetFontStyle(footerFont_, TTF_STYLE_NORMAL);
}
float maxNameW = 0.0f;
float maxValueW = 0.0f;
for (size_t i = 0; i < footerNames_.size(); ++i) {
if (footerNames_[i].width > maxNameW) maxNameW = footerNames_[i].width;
if (footerValues_[i].width > maxValueW) maxValueW = footerValues_[i].width;
for (size_t i = 0; i < footerNames_.size(); ++i)
{
if (footerNames_[i].width > maxNameW)
maxNameW = footerNames_[i].width;
if (footerValues_[i].width > maxValueW)
maxValueW = footerValues_[i].width;
}
CachedText fourSpaces;
@@ -280,14 +295,16 @@ void Home::render(SDL_Renderer *renderer)
float lineY = fh - margin;
const float lineGap = 6.0f;
for (size_t i = footerNames_.size(); i-- > 0; )
for (size_t i = footerNames_.size(); i-- > 0;)
{
float h = std::max(footerNames_[i].height, footerValues_[i].height);
if (footerNames_[i].texture) {
if (footerNames_[i].texture)
{
SDL_FRect dst{rectLeft, lineY - h, footerNames_[i].width, footerNames_[i].height};
SDL_RenderTexture(renderer, footerNames_[i].texture, nullptr, &dst);
}
if (footerValues_[i].texture) {
if (footerValues_[i].texture)
{
SDL_FRect dst{rectRight - footerValues_[i].width, lineY - h, footerValues_[i].width, footerValues_[i].height};
SDL_RenderTexture(renderer, footerValues_[i].texture, nullptr, &dst);
}
@@ -309,7 +326,8 @@ void Home::createTextures(AppState &state)
TextLine textWidthRef = renderText(state.renderer, font, "Radiant Wave", white);
float targetWidth = textWidthRef.width * 1.5f;
if (textWidthRef.texture) SDL_DestroyTexture(textWidthRef.texture);
if (textWidthRef.texture)
SDL_DestroyTexture(textWidthRef.texture);
TTF_CloseFont(font);
@@ -338,9 +356,8 @@ void Home::createTextures(AppState &state)
return;
}
SDL_Color gray = {180, 180, 180, 255};
play_ = renderText(state.renderer, font, "Play", gray);
settings_ = renderText(state.renderer, font, "Settings", gray);
play_ = renderText(state.renderer, font, "Play", white);
settings_ = renderText(state.renderer, font, "Settings", white);
TTF_CloseFont(font);
@@ -356,16 +373,26 @@ void Home::createTextures(AppState &state)
footerFont_ = TTF_OpenFont("assets/fonts/Roboto-Regular.ttf", 20);
const std::vector<std::string> footerNames = {
"Version:", "License:", "Key:", "Email:", "Subscription:", "WiFi:",
"Internet:", "Audio:", "Date:", "Time:",
"Version:",
"License:",
"Key:",
"Email:",
"Subscription:",
"WiFi:",
"Internet:",
"Audio:",
"Date:",
"Time:",
};
footerNames_.clear();
footerValues_.clear();
footerNames_.resize(footerNames.size());
footerValues_.resize(footerNames.size());
SDL_Color footerColor = {200, 200, 200, 255};
if (footerFont_) {
for (size_t i = 0; i < footerNames.size(); ++i) {
if (footerFont_)
{
for (size_t i = 0; i < footerNames.size(); ++i)
{
footerNames_[i].ensure(state.renderer, footerFont_, footerNames[i], footerColor);
}
}
@@ -373,20 +400,43 @@ void Home::createTextures(AppState &state)
void Home::destroyTextures()
{
if (bg_.texture) { SDL_DestroyTexture(bg_.texture); bg_.texture = nullptr; }
if (title_.texture) { SDL_DestroyTexture(title_.texture); title_.texture = nullptr; }
if (play_.texture) { SDL_DestroyTexture(play_.texture); play_.texture = nullptr; }
if (settings_.texture) { SDL_DestroyTexture(settings_.texture); settings_.texture = nullptr; }
for (auto& t : footerNames_) t.destroy();
for (auto& t : footerValues_) t.destroy();
if (bg_.texture)
{
SDL_DestroyTexture(bg_.texture);
bg_.texture = nullptr;
}
if (title_.texture)
{
SDL_DestroyTexture(title_.texture);
title_.texture = nullptr;
}
if (play_.texture)
{
SDL_DestroyTexture(play_.texture);
play_.texture = nullptr;
}
if (settings_.texture)
{
SDL_DestroyTexture(settings_.texture);
settings_.texture = nullptr;
}
for (auto &t : footerNames_)
t.destroy();
for (auto &t : footerValues_)
t.destroy();
footerNames_.clear();
footerValues_.clear();
if (footerFont_) { TTF_CloseFont(footerFont_); footerFont_ = nullptr; }
if (footerFont_)
{
TTF_CloseFont(footerFont_);
footerFont_ = nullptr;
}
}
void Home::refreshStatus()
{
if (!state_) return;
if (!state_)
return;
email_ = state_->db.getKV(radiantwave::db::KV_EMAIL_ADDRESS);
license_ = state_->db.getKV(radiantwave::db::KV_LICENSE_KEY);
dateFormat_ = state_->db.getKV("date_format", radiantwave::datetime::DEFAULT_DATE_FORMAT);
@@ -401,7 +451,8 @@ void Home::syncProclamationsIfEmpty(AppState &state)
// Proclamation options. Skipped once the database has content so a
// blocking sync never runs on every Home push. The API call is also
// skipped when the database is closed (fallback path in provisioning).
if (state.db.isOpen() && state.db.getActiveProclamations().empty()) {
if (state.db.isOpen() && state.db.getActiveProclamations().empty())
{
// TODO(portal #4/#5): once the portal exposes color palettes, sync them
// alongside proclamations here (sync::syncColorPalettesFromApi) so Play's
// scroller has portal colors from the very first run.
@@ -411,7 +462,8 @@ void Home::syncProclamationsIfEmpty(AppState &state)
std::string Home::audioStatus() const
{
if (!state_) return "Idle";
if (!state_)
return "Idle";
std::string status = state_->audioDownloader.statusString();
return status.empty() ? "Idle" : status;
}