15#include <goodisplay/gdey029T94.h>
18static const char*
TAG =
"PinChangeView";
39 minLength_ = minLength < 4 ? 4 : minLength;
43 memset(currentPin_, 0,
sizeof(currentPin_));
44 memset(newPin_, 0,
sizeof(newPin_));
45 memset(confirmPin_, 0,
sizeof(confirmPin_));
59 init(minLength_, maxLength_);
66void PinChangeView::clearBuffer() {
67 char* buf = getCurrentBuffer();
78char* PinChangeView::getCurrentBuffer() {
91const char* PinChangeView::getStepTitle()
const {
105 if (onRetries_)
return onRetries_();
114void PinChangeView::addDigit(
char digit) {
115 if (length_ >= maxLength_)
return;
117 char* buf = getCurrentBuffer();
118 buf[length_++] = digit;
127void PinChangeView::backspace() {
129 char* buf = getCurrentBuffer();
130 buf[--length_] =
'\0';
140void PinChangeView::showMessage(
const char* msg) {
142 messageShownMs_ = esp_timer_get_time() / 1000;
150void PinChangeView::confirmStep() {
154 if (length_ < minLength_) {
155 showMessage(
ui::tr(
"core.pin_too_short"));
160 bool ok = onVerify_ ? onVerify_(currentPin_) : core::PinManager::instance().verifyBadgePin(currentPin_);
161 bool blocked = onBlocked_ ? onBlocked_() : core::PinManager::instance().isBadgeBlocked();
164 showMessage(
ui::tr(
"core.locked_out"));
166 showMessage(
ui::tr(
"core.wrong_pin"));
176 LOG_I(
TAG,
"Current PIN verified, entering new PIN");
182 if (length_ < minLength_) {
183 showMessage(
ui::tr(
"core.pin_too_short"));
192 LOG_I(
TAG,
"New PIN entered, confirming");
198 if (length_ < minLength_) {
199 showMessage(
ui::tr(
"core.pin_too_short"));
205 if (strcmp(newPin_, confirmPin_) != 0) {
206 showMessage(
ui::tr(
"core.pin_mismatch"));
209 memset(newPin_, 0,
sizeof(newPin_));
211 LOG_W(
TAG,
"PIN mismatch, re-enter new PIN");
216 bool changed = onChange_
217 ? onChange_(currentPin_, newPin_)
218 : core::PinManager::instance().setBadgePin(newPin_);
221 showMessage(
ui::tr(
"core.pin_changed"));
222 LOG_I(
TAG,
"PIN changed successfully");
224 showMessage(
ui::tr(
"core.error_generic"));
225 LOG_E(
TAG,
"Failed to set new PIN");
238 if (messageShownMs_ > 0 && message_ !=
nullptr) {
245 if (pinChanged_ && onComplete_) {
265 if (key >=
'0' && key <=
'9') {
284 length_ = strlen(newPin_);
287 length_ = strlen(currentPin_);
294 if (length_ >= minLength_) {
309 return ui::tr(
"core.hint_pin_input");
321 auto* gfx =
static_cast<Gdey029T94*
>(
display->getNativeHandle());
324 const uint16_t width =
display->getWidth();
325 const uint16_t height =
display->getHeight();
328 gfx->fillScreen(EPD_WHITE);
331 gfx->setTextColor(EPD_BLACK);
336 const char* title = title_ ? title_ :
ui::tr(
"core.change_pin");
339 const char* stepTitle = getStepTitle();
341 snprintf(stepStr,
sizeof(stepStr),
"%d/3: %s",
static_cast<int>(step_) + 1, stepTitle);
342 gfx->getTextBounds(stepStr, 0, 0, &x1, &y1, &w, &h);
343 gfx->setCursor((width - w) / 2,
STEP_Y);
346 int dotsToShow = length_ > 8 ? length_ : 8;
348 int startX = (width - totalWidth) / 2;
350 for (
int i = 0; i < dotsToShow; i++) {
364 snprintf(retriesStr,
sizeof(retriesStr),
"%s: %d",
ui::tr(
"core.retries"), retries);
366 gfx->getTextBounds(retriesStr, 0, 0, &x1, &y1, &w, &h);
367 gfx->setCursor((width - w) / 2,
PIN_Y + 25);
368 gfx->print(retriesStr);
371 gfx->fillRect(0,
MESSAGE_Y - 2, width, 20, EPD_WHITE);
374 gfx->getTextBounds(message_, 0, 0, &x1, &y1, &w, &h);
375 gfx->setCursor((width - w) / 2,
MESSAGE_Y);
Internationalization with English fallbacks in code and overlay translations loaded at runtime from a...
static constexpr int PIN_DOT_SIZE
static constexpr int PIN_Y
static constexpr int MESSAGE_Y
static constexpr int STEP_Y
static constexpr int PIN_DOT_SPACING
static constexpr int TITLE_Y
Display layout constants.
CDC Log: logging over TinyUSB CDC and UART.
#define LOG_W(tag, fmt,...)
#define LOG_I(tag, fmt,...)
#define LOG_E(tag, fmt,...)
uint8_t getBadgeRetries() const
bool isBadgeBlocked() const
Lockout timer handling.
static PinManager & instance()
Returns singleton PIN manager instance.
InputResult onKey(char key) override
Handles key input for PIN-change flow.
const char * getFooterHint() const override
Returns localized footer hint text.
void init(uint8_t minLength=4, uint8_t maxLength=16)
Initializes PIN-change wizard state.
static constexpr uint8_t MAX_PIN_LENGTH
static constexpr uint32_t MESSAGE_DISPLAY_MS
void onEnter(void *context) override
Resets wizard state when entering the view.
void render(bool partial) override
Renders PIN-change wizard UI.
uint8_t getRetriesRemaining() const
Returns remaining retry count for current PIN verification.
void onTick(uint32_t nowMs) override
Handles message timeout and completion callbacks.
IDisplay * getDisplayInstance()
Returns lazily created singleton display instance.
void drawFooterBar(Gdey029T94 *gfx, uint16_t width, uint16_t height, const char *prefix, const char *hint, bool force=false)
Draws footer bar with optional prefix and hint text.
void drawHeaderCentered(Gdey029T94 *gfx, const char *title, int y, uint16_t width)
Draws a centered header title.
void printText(Gdey029T94 *gfx, const char *text)
Draws CP437 text with the built-in 6x8 glyph font, byte-for-byte.
Centralized key-code constants for cdc_views.
const char * tr(const char *key)
Look up a translation by string key.
static constexpr char KEY_NO
Cancel / Back / Backspace.
static constexpr int TITLE_Y
Layout constants mirror the ones used by T9InputView.
static constexpr char KEY_YES
Confirm / OK / Save.