Merge pull request #23 from jpirnay/feat-bmpviewer

feat: Amend back button handling, add "use as sleep screen" feature
This commit is contained in:
jpirnay
2026-04-06 10:41:15 +02:00
committed by GitHub
5 changed files with 74 additions and 2 deletions
+2
View File
@@ -442,5 +442,7 @@ STR_UPTIME: "Uptime"
STR_CHARGING: "Charging"
STR_GATHERING_DATA: "Gathering data..."
STR_READING: "Reading..."
STR_SET_SLEEP_SCREEN: "Set Sleep"
STR_SLEEP_SCREEN_SET: "Sleep screen updated!"
STR_WEATHER_MOON_INFO: "Moon"
STR_WEATHER_SUN_INFO: "Sun"
+30
View File
@@ -7,6 +7,7 @@
#include <SdFat.h>
#include <cassert>
#include <new>
#define SDCard SDCardManager::getInstance()
@@ -138,6 +139,35 @@ bool HalStorage::openFileForWrite(const char* moduleName, const String& path, Ha
bool HalStorage::removeDir(const char* path) { HAL_STORAGE_WRAPPED_CALL(removeDir, path); }
bool HalStorage::copyFile(const char* moduleName, const std::string& srcPath, const char* dstPath) {
HalFile src, dst;
if (!openFileForRead(moduleName, srcPath, src)) return false;
if (!openFileForWrite(moduleName, dstPath, dst)) {
src.close();
return false;
}
constexpr size_t BUF_SIZE = 4096;
auto* buf = new (std::nothrow) uint8_t[BUF_SIZE];
if (!buf) {
dst.close();
src.close();
return false;
}
bool ok = true;
while (src.available()) {
const auto bytesRead = src.read(buf, BUF_SIZE);
if (bytesRead <= 0) break;
if (dst.write(buf, bytesRead) != static_cast<size_t>(bytesRead)) {
ok = false;
break;
}
}
delete[] buf;
dst.close();
src.close();
return ok;
}
// HalFile implementation
// Allow doing file operations while ensuring thread safety via HalStorage's mutex.
// Please keep the list below in sync with the HalFile.h header
+1
View File
@@ -44,6 +44,7 @@ class HalStorage {
bool openFileForWrite(const char* moduleName, const std::string& path, HalFile& file);
bool openFileForWrite(const char* moduleName, const String& path, HalFile& file);
bool removeDir(const char* path);
bool copyFile(const char* moduleName, const std::string& srcPath, const char* dstPath);
uint64_t sdTotalBytes() const;
uint64_t sdUsedBytes();
+40 -2
View File
@@ -5,9 +5,15 @@
#include <HalStorage.h>
#include <I18n.h>
#include "../reader/ReaderUtils.h"
#include "CrossPointSettings.h"
#include "components/UITheme.h"
#include "fontIds.h"
namespace {
constexpr const char* SLEEP_BMP_PATH = "/sleep.bmp";
} // namespace
BmpViewerActivity::BmpViewerActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, std::string path)
: Activity("BmpViewer", renderer, mappedInput), filePath(std::move(path)) {}
@@ -49,7 +55,7 @@ void BmpViewerActivity::onEnter() {
}
// 4. Prepare Rendering
const auto labels = mappedInput.mapLabels(tr(STR_BACK), "", "", "");
const auto labels = mappedInput.mapLabels(tr(STR_BACK), "", "", tr(STR_SET_SLEEP_SCREEN));
GUI.fillPopupProgress(renderer, popupRect, 50);
renderer.clearScreen();
@@ -89,12 +95,44 @@ void BmpViewerActivity::onExit() {
renderer.displayBuffer(HalDisplay::FULL_REFRESH);
}
void BmpViewerActivity::setAsSleepScreen() {
// Only copy if the source isn't already /sleep.bmp
if (filePath != SLEEP_BMP_PATH) {
if (!Storage.copyFile("BMP", filePath, SLEEP_BMP_PATH)) {
LOG_ERR("BMP", "Failed to copy %s to %s", filePath.c_str(), SLEEP_BMP_PATH);
return;
}
}
// Switch sleep screen mode to CUSTOM so the copied image is used
SETTINGS.sleepScreen = CrossPointSettings::SLEEP_SCREEN_MODE::CUSTOM;
SETTINGS.saveToFile();
LOG_INF("BMP", "Set %s as sleep screen", filePath.c_str());
GUI.drawPopup(renderer, tr(STR_SLEEP_SCREEN_SET));
renderer.displayBuffer(HalDisplay::HALF_REFRESH);
}
void BmpViewerActivity::loop() {
// Keep CPU awake/polling so 1st click works
Activity::loop();
if (mappedInput.wasReleased(MappedInputManager::Button::Back)) {
// Long press BACK (1s+) goes to home screen
if (mappedInput.isPressed(MappedInputManager::Button::Back) && mappedInput.getHeldTime() >= ReaderUtils::GO_HOME_MS) {
onGoHome();
return;
}
// Short press BACK returns to the calling activity
if (mappedInput.wasReleased(MappedInputManager::Button::Back) &&
mappedInput.getHeldTime() < ReaderUtils::GO_HOME_MS) {
finish();
return;
}
// Next/Right button: set this image as the sleep screen
if (mappedInput.wasReleased(MappedInputManager::Button::Right)) {
setAsSleepScreen();
return;
}
}
+1
View File
@@ -16,4 +16,5 @@ class BmpViewerActivity final : public Activity {
private:
std::string filePath;
void setAsSleepScreen();
};