UI: - Theme engine (5 palettes) persisted to NVS; live Theme switcher module - Animated shell: boot splash, CRT scanlines, breathing menu cursor, wipe-in transitions, spinners, progress bars New recon modules: - Bus Dump: SPI-NOR + I2C EEPROM readout to microSD (read-only) - Crypto Lab: entropy, magic-byte file-ID, XOR brute, AES-128 known-key - Exfil: SD browser + base64 dump export over USB serial, manifest writer README updated with the new module table and look-and-feel notes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AAhMHMRAQLQ9hSbBECKNfn
44 lines
1.6 KiB
C++
44 lines
1.6 KiB
C++
#include "../core/module.h"
|
|
#include "../core/ui.h"
|
|
#include "../core/theme.h"
|
|
#include <M5Cardputer.h>
|
|
|
|
// Live theme switcher. Preview swatches, [space]/arrows to cycle, choice
|
|
// saved to NVS so it sticks across reboots.
|
|
class ThemePicker : public Module {
|
|
public:
|
|
const char* name() const override { return "Theme"; }
|
|
const char* blurb() const override { return "restyle the UI"; }
|
|
|
|
bool onKey(char c) override {
|
|
if (c == '.' || c == ' ') { theme::set(theme::current() + 1); repaint(); return true; }
|
|
if (c == ';') { theme::set(theme::current() - 1); repaint(); return true; }
|
|
return false;
|
|
}
|
|
void onEnter() override { repaint(); }
|
|
|
|
void draw() override {
|
|
auto& d = M5.Display;
|
|
ui::lineC(0, ui::accent(), "theme: %s (%d/%d)",
|
|
theme::active().name, theme::current() + 1, theme::COUNT);
|
|
// swatch row
|
|
int y = ui::BODY_Y + 20;
|
|
for (int i = 0; i < theme::COUNT; i++) {
|
|
const Theme& t = theme::LIST[i];
|
|
int x = 6 + i * 30;
|
|
d.fillRoundRect(x, y, 24, 24, 4, ui::rgb(t.bg));
|
|
d.fillRect(x + 4, y + 4, 16, 5, ui::rgb(t.accent));
|
|
d.fillRect(x + 4, y + 11, 10, 4, ui::rgb(t.warn));
|
|
d.fillRect(x + 4, y + 16, 14, 4, ui::rgb(t.bad));
|
|
d.drawRoundRect(x, y, 24, 24, 4, i == theme::current() ? ui::glow() : ui::dim());
|
|
}
|
|
ui::line(5, "everything restyles instantly.");
|
|
ui::hintBar("; / . cycle [`]back");
|
|
}
|
|
private:
|
|
void repaint() { M5.Display.fillScreen(ui::bg());
|
|
ui::titleBar(name(), blurb()); draw(); }
|
|
};
|
|
|
|
Module* makeThemePicker() { return new ThemePicker(); }
|