mirror of
https://github.com/usatiuk/cardboy.git
synced 2025-10-28 15:17:48 +01:00
lockscreen show progressbar only on hold
This commit is contained in:
@@ -17,7 +17,8 @@ namespace {
|
||||
|
||||
using cardboy::sdk::AppContext;
|
||||
|
||||
constexpr std::uint32_t kRefreshIntervalMs = 500;
|
||||
constexpr std::uint32_t kRefreshIntervalMs = 100;
|
||||
constexpr std::uint32_t kUnlockHoldMs = 1500;
|
||||
|
||||
using Framebuffer = typename AppContext::Framebuffer;
|
||||
using Clock = typename AppContext::Clock;
|
||||
@@ -41,6 +42,8 @@ public:
|
||||
void onStart() override {
|
||||
cancelRefreshTimer();
|
||||
lastSnapshot = {};
|
||||
holdActive = false;
|
||||
holdProgressMs = 0;
|
||||
dirty = true;
|
||||
const auto snap = captureTime();
|
||||
renderIfNeeded(snap);
|
||||
@@ -53,12 +56,13 @@ public:
|
||||
void handleEvent(const cardboy::sdk::AppEvent& event) override {
|
||||
switch (event.type) {
|
||||
case cardboy::sdk::AppEventType::Button:
|
||||
if (anyNewPress(event.button))
|
||||
context.requestAppSwitchByName(kMenuAppName);
|
||||
handleButtonEvent(event.button);
|
||||
break;
|
||||
case cardboy::sdk::AppEventType::Timer:
|
||||
if (event.timer.handle == refreshTimer)
|
||||
if (event.timer.handle == refreshTimer) {
|
||||
advanceHoldProgress();
|
||||
updateDisplay();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -71,6 +75,8 @@ private:
|
||||
bool dirty = false;
|
||||
cardboy::sdk::AppTimerHandle refreshTimer = cardboy::sdk::kInvalidAppTimer;
|
||||
TimeSnapshot lastSnapshot{};
|
||||
bool holdActive = false;
|
||||
std::uint32_t holdProgressMs = 0;
|
||||
|
||||
void cancelRefreshTimer() {
|
||||
if (refreshTimer != cardboy::sdk::kInvalidAppTimer) {
|
||||
@@ -79,12 +85,45 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
static bool anyNewPress(const cardboy::sdk::AppButtonEvent& button) {
|
||||
const auto& current = button.current;
|
||||
const auto& previous = button.previous;
|
||||
return (current.a && !previous.a) || (current.b && !previous.b) || (current.start && !previous.start) ||
|
||||
(current.select && !previous.select) || (current.up && !previous.up) || (current.down && !previous.down) ||
|
||||
(current.left && !previous.left) || (current.right && !previous.right);
|
||||
static bool comboPressed(const cardboy::sdk::InputState& state) { return state.a && state.select; }
|
||||
|
||||
void handleButtonEvent(const cardboy::sdk::AppButtonEvent& button) {
|
||||
const bool comboNow = comboPressed(button.current);
|
||||
updateHoldState(comboNow);
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
void updateHoldState(bool comboNow) {
|
||||
if (comboNow) {
|
||||
if (!holdActive) {
|
||||
holdActive = true;
|
||||
dirty = true;
|
||||
}
|
||||
} else {
|
||||
if (holdActive || holdProgressMs != 0) {
|
||||
holdActive = false;
|
||||
holdProgressMs = 0;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void advanceHoldProgress() {
|
||||
if (holdActive) {
|
||||
const std::uint32_t next =
|
||||
std::min<std::uint32_t>(holdProgressMs + kRefreshIntervalMs, kUnlockHoldMs);
|
||||
if (next != holdProgressMs) {
|
||||
holdProgressMs = next;
|
||||
dirty = true;
|
||||
}
|
||||
if (holdProgressMs >= kUnlockHoldMs) {
|
||||
holdActive = false;
|
||||
context.requestAppSwitchByName(kMenuAppName);
|
||||
}
|
||||
} else if (holdProgressMs != 0) {
|
||||
holdProgressMs = 0;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void updateDisplay() {
|
||||
@@ -133,6 +172,29 @@ private:
|
||||
font16x8::drawText(fb, x, y, text, scale, true, letterSpacing);
|
||||
}
|
||||
|
||||
static void drawRectOutline(Framebuffer& fb, int x, int y, int w, int h) {
|
||||
if (w <= 0 || h <= 0)
|
||||
return;
|
||||
for (int dx = 0; dx < w; ++dx) {
|
||||
fb.drawPixel(x + dx, y, true);
|
||||
fb.drawPixel(x + dx, y + h - 1, true);
|
||||
}
|
||||
for (int dy = 0; dy < h; ++dy) {
|
||||
fb.drawPixel(x, y + dy, true);
|
||||
fb.drawPixel(x + w - 1, y + dy, true);
|
||||
}
|
||||
}
|
||||
|
||||
static void fillRect(Framebuffer& fb, int x, int y, int w, int h) {
|
||||
if (w <= 0 || h <= 0)
|
||||
return;
|
||||
for (int dy = 0; dy < h; ++dy) {
|
||||
for (int dx = 0; dx < w; ++dx) {
|
||||
fb.drawPixel(x + dx, y + dy, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::string formatDate(const TimeSnapshot& snap) {
|
||||
static const char* kWeekdays[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
|
||||
if (!snap.hasWallTime)
|
||||
@@ -169,7 +231,24 @@ private:
|
||||
|
||||
const std::string dateLine = formatDate(snap);
|
||||
drawCenteredText(framebuffer, timeY + font16x8::kGlyphHeight * scaleTime + 24, dateLine, scaleSmall, 1);
|
||||
drawCenteredText(framebuffer, framebuffer.height() - 40, "PRESS ANY BUTTON", scaleSmall, 1);
|
||||
const char* instruction = holdActive ? "KEEP HOLDING A+SELECT" : "HOLD A+SELECT";
|
||||
drawCenteredText(framebuffer, framebuffer.height() - 52, instruction, scaleSmall, 1);
|
||||
|
||||
if (holdActive || holdProgressMs > 0) {
|
||||
const int barWidth = framebuffer.width() - 64;
|
||||
const int barHeight = 14;
|
||||
const int barX = (framebuffer.width() - barWidth) / 2;
|
||||
const int barY = framebuffer.height() - 32;
|
||||
const int innerWidth = barWidth - 2;
|
||||
const int innerHeight = barHeight - 2;
|
||||
drawRectOutline(framebuffer, barX, barY, barWidth, barHeight);
|
||||
|
||||
const float ratio =
|
||||
std::clamp(holdProgressMs / static_cast<float>(kUnlockHoldMs), 0.0f, 1.0f);
|
||||
const int fillWidth = static_cast<int>(ratio * innerWidth + 0.5f);
|
||||
if (fillWidth > 0)
|
||||
fillRect(framebuffer, barX + 1, barY + 1, fillWidth, innerHeight);
|
||||
}
|
||||
|
||||
framebuffer.sendFrame();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user