Files
Crosspoint/src/activities/settings/ClockSyncActivity.cpp
T
Justin Mitchell 57c389c0b6 Add touch-down visual feedback to settings menus
Handle touch-down events separately from tap events in settings activities to provide immediate visual feedback when menu items are touched, before the tap is completed. This improves UI responsiveness by updating the selected index on touch-down.
2026-06-19 14:41:21 -04:00

116 lines
3.3 KiB
C++

#include "ClockSyncActivity.h"
#include <GfxRenderer.h>
#include <HalClock.h>
#include <I18n.h>
#include <Logging.h>
#include <WiFi.h>
#include <cstdio>
#include "CrossPointSettings.h"
#include "MappedInputManager.h"
#include "components/UITheme.h"
#include "fontIds.h"
void ClockSyncActivity::onEnter() {
Activity::onEnter();
state = SYNCING;
syncedTime[0] = '\0';
requestUpdate();
}
void ClockSyncActivity::onExit() { Activity::onExit(); }
void ClockSyncActivity::runSync() {
if (WiFi.status() != WL_CONNECTED) {
LOG_INF("CLK", "Manual sync requested but WiFi is not connected");
state = NO_WIFI;
requestUpdate();
return;
}
const bool ok = halClock.syncFromNTP();
if (!ok) {
state = FAILED;
requestUpdate();
return;
}
// Mark as synced so the auto-sync hook stops firing on future WiFi connects.
SETTINGS.clockHasBeenSynced = 1;
SETTINGS.saveToFile();
// Read the freshly synced time back for the user-facing confirmation.
char buf[9];
if (halClock.formatTime(buf, sizeof(buf), SETTINGS.clockUtcOffsetQ, SETTINGS.clockFormat == 1)) {
snprintf(syncedTime, sizeof(syncedTime), "%s", buf);
}
state = SUCCESS;
requestUpdate();
}
void ClockSyncActivity::loop() {
if (state == SYNCING) {
// First-tick: render the "Syncing..." screen, then perform the (blocking) sync.
// requestUpdateAndWait below forces the render before we block on WiFi.
requestUpdateAndWait();
runSync();
return;
}
if (mappedInput.wasPressed(MappedInputManager::Button::Back) ||
mappedInput.wasPressed(MappedInputManager::Button::Confirm)) {
finish();
return;
}
int tapX = 0;
int tapY = 0;
if (mappedInput.wasScreenTapped(tapX, tapY)) {
finish();
}
}
void ClockSyncActivity::render(RenderLock&&) {
const auto& metrics = UITheme::getInstance().getMetrics();
const auto pageWidth = renderer.getScreenWidth();
const auto pageHeight = renderer.getScreenHeight();
renderer.clearScreen();
GUI.drawHeader(renderer, Rect{0, metrics.topPadding, pageWidth, metrics.headerHeight}, tr(STR_CLOCK_SYNC));
const int midY = pageHeight / 2;
switch (state) {
case SYNCING:
renderer.drawCenteredText(UI_12_FONT_ID, midY, tr(STR_CLOCK_SYNCING));
break;
case SUCCESS: {
renderer.drawCenteredText(UI_12_FONT_ID, midY - 20, tr(STR_CLOCK_SYNC_OK), true, EpdFontFamily::BOLD);
if (syncedTime[0] != '\0') {
char line[32];
snprintf(line, sizeof(line), "%s %s", tr(STR_CURRENT_TIME), syncedTime);
renderer.drawCenteredText(UI_10_FONT_ID, midY + 10, line);
}
break;
}
case NO_WIFI:
renderer.drawCenteredText(UI_12_FONT_ID, midY - 20, tr(STR_CLOCK_SYNC_NO_WIFI), true, EpdFontFamily::BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, midY + 10, tr(STR_CLOCK_SYNC_NO_WIFI_HINT));
break;
case FAILED:
renderer.drawCenteredText(UI_12_FONT_ID, midY - 20, tr(STR_CLOCK_SYNC_FAIL), true, EpdFontFamily::BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, midY + 10, tr(STR_CHECK_SERIAL_OUTPUT));
break;
}
if (state != SYNCING) {
const auto labels = mappedInput.mapLabels(tr(STR_BACK), tr(STR_OK_BUTTON), "", "");
GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
}
renderer.displayBuffer();
}