Merge branch 'feat-sdcard-info' of https://github.com/jpirnay/crosspoint-reader into mybuild

This commit is contained in:
jpirnay
2026-03-17 21:27:10 +01:00
11 changed files with 228 additions and 9 deletions
@@ -6,6 +6,7 @@
#include "ButtonRemapActivity.h"
#include "CalibreSettingsActivity.h"
#include "ClearCacheActivity.h"
#include "SystemInformationActivity.h"
#include "CrossPointSettings.h"
#include "KOReaderSettingsActivity.h"
#include "LanguageSelectActivity.h"
@@ -52,6 +53,7 @@ void SettingsActivity::onEnter() {
systemSettings.push_back(SettingInfo::Action(StrId::STR_CLEAR_READING_CACHE, SettingAction::ClearCache));
systemSettings.push_back(SettingInfo::Action(StrId::STR_CHECK_UPDATES, SettingAction::CheckForUpdates));
systemSettings.push_back(SettingInfo::Action(StrId::STR_LANGUAGE, SettingAction::Language));
systemSettings.push_back(SettingInfo::Action(StrId::STR_SYSTEM_INFO, SettingAction::SystemInfo));
readerSettings.push_back(SettingInfo::Action(StrId::STR_CUSTOMISE_STATUS_BAR, SettingAction::CustomiseStatusBar));
// Reset selection to first category
@@ -192,6 +194,9 @@ void SettingsActivity::toggleCurrentSetting() {
case SettingAction::Language:
startActivityForResult(std::make_unique<LanguageSelectActivity>(renderer, mappedInput), resultHandler);
break;
case SettingAction::SystemInfo:
startActivityForResult(std::make_unique<SystemInformationActivity>(renderer, mappedInput), resultHandler);
break;
case SettingAction::None:
// Do nothing
break;
@@ -21,6 +21,7 @@ enum class SettingAction {
ClearCache,
CheckForUpdates,
Language,
SystemInfo,
};
struct SettingInfo {
@@ -0,0 +1,94 @@
#include "SystemInformationActivity.h"
#include <GfxRenderer.h>
#include <I18n.h>
#include "MappedInputManager.h"
#include "SystemStatus.h"
#include "components/UITheme.h"
#include "fontIds.h"
static std::string formatBytes(uint64_t bytes) {
char buf[16];
if (bytes >= 1024ULL * 1024 * 1024) {
snprintf(buf, sizeof(buf), "%.1f GB", bytes / (1024.0 * 1024.0 * 1024.0));
} else if (bytes >= 1024ULL * 1024) {
snprintf(buf, sizeof(buf), "%.1f MB", bytes / (1024.0 * 1024.0));
} else if (bytes >= 1024ULL) {
snprintf(buf, sizeof(buf), "%.1f KB", bytes / 1024.0);
} else {
snprintf(buf, sizeof(buf), "%llu B", static_cast<unsigned long long>(bytes));
}
return buf;
}
void SystemInformationActivity::onEnter() {
Activity::onEnter();
requestUpdate();
}
void SystemInformationActivity::onExit() { Activity::onExit(); }
void SystemInformationActivity::loop() {
if (mappedInput.wasPressed(MappedInputManager::Button::Back)) {
finish();
}
}
void SystemInformationActivity::render(RenderLock&&) {
const auto& metrics = UITheme::getInstance().getMetrics();
const auto pageWidth = renderer.getScreenWidth();
const auto pageHeight = renderer.getScreenHeight();
renderer.clearScreen();
GUI.drawHeader(renderer, Rect{0, metrics.topPadding, pageWidth, metrics.headerHeight}, tr(STR_SYSTEM_INFO),
CROSSPOINT_VERSION);
const auto status = SystemStatus::collect();
// Layout: label on the left, value right of the midpoint
const int leftX = metrics.verticalSpacing * 3;
const int valueX = pageWidth / 2;
const int lineH = renderer.getLineHeight(UI_10_FONT_ID);
const int startY = metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing * 3;
auto drawRow = [&](int row, const char* label, const std::string& value) {
const int y = startY + row * (lineH + metrics.verticalSpacing);
renderer.drawText(UI_10_FONT_ID, leftX, y, label, true, EpdFontFamily::BOLD);
renderer.drawText(UI_10_FONT_ID, valueX, y, value.c_str());
};
// Device
drawRow(0, "Version", status.version);
drawRow(1, "Free heap", std::to_string(status.freeHeapBytes / 1024) + " KB");
const uint32_t h = status.uptimeSeconds / 3600;
const uint32_t m = (status.uptimeSeconds % 3600) / 60;
const uint32_t s = status.uptimeSeconds % 60;
char uptimeBuf[16];
snprintf(uptimeBuf, sizeof(uptimeBuf), "%uh %02um %02us", h, m, s);
drawRow(2, "Uptime", uptimeBuf);
// SD card
const std::string sdUsed = formatBytes(status.sdUsedBytes) + " / " + formatBytes(status.sdTotalBytes);
drawRow(3, "SD card", status.sdTotalBytes > 0 ? sdUsed : "N/A");
// WiFi (shown as-is; "Off" when not connected)
std::string wifiLabel = status.wifiMode;
if (status.rssi != 0) {
wifiLabel += " (" + std::to_string(status.rssi) + " dBm)";
}
drawRow(4, "WiFi", wifiLabel);
if (status.wifiMode != "Off") {
drawRow(5, "IP address", status.ip);
drawRow(6, "MAC address", status.macAddress);
} else {
drawRow(5, "MAC address", status.macAddress);
}
const auto labels = mappedInput.mapLabels(tr(STR_BACK), "", "", "");
GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
renderer.displayBuffer();
}
@@ -0,0 +1,14 @@
#pragma once
#include "activities/Activity.h"
class SystemInformationActivity final : public Activity {
public:
explicit SystemInformationActivity(GfxRenderer& renderer, MappedInputManager& mappedInput)
: Activity("SystemInformation", renderer, mappedInput) {}
void onEnter() override;
void onExit() override;
void loop() override;
void render(RenderLock&&) override;
};