Add theme engine, animated UI, and Bus Dump / Crypto / Exfil modules
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
This commit is contained in:
43
src/modules/themepick.cpp
Normal file
43
src/modules/themepick.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#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(); }
|
||||
Reference in New Issue
Block a user